{"id":2973,"date":"2017-08-10T16:32:38","date_gmt":"2017-08-10T23:32:38","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=2973"},"modified":"2017-08-10T16:32:38","modified_gmt":"2017-08-10T23:32:38","slug":"exporting-and-importing-cmake-packages-with-find_package","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/linux\/cmake\/find_package\/","title":{"rendered":"Exporting and importing CMake packages with find_package"},"content":{"rendered":"<p>This tutorial shows how to export a CMake library to a package and import it from a different project using the find_package() command. This works faster as referencing the library project&#8217;s directory using the <strong>add_subdirectory()<\/strong> command, as the exporting mechanism allows precisely selecting which targets to export. We will use Visual Studio to create a basic library project for Raspberry Pi with a cross-compiler, export it to a package and import it from another project.<\/p>\n<ol>\n<li>Follow <a href=\"https:\/\/visualgdb.com\/tutorials\/linux\/cmake\/library\/\">this tutorial<\/a> to create a basic CMake library for Raspberry Pi and import it manually via add_subdirectory().<\/li>\n<li>Now we will change the library project to be exported to a package. Add the following lines to the CMakeLists.txt file that defines the library:\n<pre class=\"\">set(INSTALL_CMAKE_DIR c:\/Packages\/DemoLibraryClient)\r\ninstall(FILES public\/PublicHeader.h DESTINATION ${INSTALL_CMAKE_DIR}\/public)\r\ninstall(TARGETS CMakeLibraryDemo DESTINATION ${INSTALL_CMAKE_DIR} EXPORT FindCMakeLibraryDemo)\r\ninstall(EXPORT FindCMakeLibraryDemo DESTINATION ${INSTALL_CMAKE_DIR})<\/pre>\n<p>The lines above instruct CMake to install the PublicHeader.h file and the CMakeLibraryDemo target to the <strong>c:\/Packages\/DemoLibraryClient<\/strong> directory. It also configures CMake to generate a <strong>FindCMakeLibraryDemo.cmake<\/strong> file (EXPORT statement in the install TARGETS command) that will add the CMakeLibraryDemo target as an imported target to any project that includes this file. This mechanism will be used later when we import our package.<\/li>\n<li>If you try building the project now, CMake will show the following error:\n<pre class=\"\">\u00a0 CMake Error in CMakeLists.txt:\r\n\u00a0 Target \"CMakeLibraryDemo\" INTERFACE_INCLUDE_DIRECTORIES property contains\r\n\u00a0 path:\r\n\r\n\u00a0\u00a0\u00a0 \"C:\/projects\/CMakeLibraryDemo\/public\"\r\n\r\n\u00a0 which is prefixed in the source directory.<\/pre>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/iface.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2974\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/iface.png\" alt=\"iface\" width=\"1154\" height=\"783\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/iface.png 1154w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/iface-300x204.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/iface-1024x695.png 1024w\" sizes=\"(max-width: 1154px) 100vw, 1154px\" \/><\/a>This happens because CMake detects that the public include directory (that will be added to targets from other projects importing our library) resides inside the source directory (exporting a project to a package should break all ties to the original location of the source files so that they could be safely deleted).<\/li>\n<li>We can fix this by using the CMake generator expressions. Replace the <strong>target_include_directories(CMakeLibraryDemo PUBLIC public)<\/strong> line with this:\n<pre class=\"\">target_include_directories(CMakeLibraryDemo PUBLIC \r\n\u00a0\u00a0\u00a0 $&lt;BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}\/public&gt; \u00a0\r\n\u00a0\u00a0\u00a0 $&lt;INSTALL_INTERFACE:${INSTALL_CMAKE_DIR}\/public&gt;)<\/pre>\n<p>This syntax tells CMake to use a directory inside the source tree when building the package and use the directory under the installation directory (where we installed PublicHeader.h using INSTALL FILES command) while handling exporting.<\/li>\n<li>Now the build should succeed:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/26-export.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2960\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/26-export.png\" alt=\"26-export\" width=\"1154\" height=\"783\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/26-export.png 1154w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/26-export-300x204.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/26-export-1024x695.png 1024w\" sizes=\"(max-width: 1154px) 100vw, 1154px\" \/><\/a><\/li>\n<li>You can generate the package by right-clicking on libCMakeLibraryDemo.so in Solution Explorer and selecting &#8220;Install Target(s)&#8221;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/27-install.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2961\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/27-install.png\" alt=\"27-install\" width=\"1154\" height=\"783\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/27-install.png 1154w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/27-install-300x204.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/27-install-1024x695.png 1024w\" sizes=\"(max-width: 1154px) 100vw, 1154px\" \/><\/a><\/li>\n<li>CMake will create the c:\/Packages\/DemoLibraryClient directory and install the necessary files there:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/28-installed.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2962\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/28-installed.png\" alt=\"28-installed\" width=\"1154\" height=\"783\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/28-installed.png 1154w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/28-installed-300x204.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/28-installed-1024x695.png 1024w\" sizes=\"(max-width: 1154px) 100vw, 1154px\" \/><\/a><\/li>\n<li>Open the installation directory with Explorer and check its contents:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/29-folder.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2963\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/29-folder.png\" alt=\"29-folder\" width=\"839\" height=\"491\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/29-folder.png 839w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/29-folder-300x176.png 300w\" sizes=\"(max-width: 839px) 100vw, 839px\" \/><\/a>It should normally contain the library (.so file), the <strong>Find&lt;Package name&gt;.cmake<\/strong> file and the <strong>public<\/strong> directory with the public header (created via the INSTALL FILES command).<\/li>\n<li>Now we will create another CMake project that will import the package. Use the VisualGDB Linux Project Wizard to do that:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/30-client3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2964\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/30-client3.png\" alt=\"30-client3\" width=\"909\" height=\"619\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/30-client3.png 909w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/30-client3-300x204.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/30-client3-130x90.png 130w\" sizes=\"(max-width: 909px) 100vw, 909px\" \/><\/a><\/li>\n<li>Insert the following line in the CMakeLists.txt file of the new project:\n<pre class=\"\">find_package(CMakeLibraryDemo REQUIRED)<\/pre>\n<p>If you try building it now, CMake will complain that FindCMakeLibraryDemo.cmake file must be located in CMAKE_MODULE_PATH:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/31-nopkg.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2965\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/31-nopkg.png\" alt=\"31-nopkg\" width=\"1154\" height=\"783\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/31-nopkg.png 1154w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/31-nopkg-300x204.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/31-nopkg-1024x695.png 1024w\" sizes=\"(max-width: 1154px) 100vw, 1154px\" \/><\/a><\/li>\n<li>You can fix this by adding &#8220;c:\\Packages\\DemoLibraryClient&#8221; to the &#8220;Extra module directories&#8221; field on the CMake Project Settings page of VisualGDB Project Properties for your project:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/32-modules.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2966\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/32-modules.png\" alt=\"32-modules\" width=\"793\" height=\"594\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/32-modules.png 793w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/32-modules-300x225.png 300w\" sizes=\"(max-width: 793px) 100vw, 793px\" \/><\/a><\/li>\n<li>Now CMake will find the package and build the project, however running it will result in an error: the libCMakeLibraryDemo.so file will not be found:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/33-nolib.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2967\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/33-nolib.png\" alt=\"33-nolib\" width=\"1154\" height=\"783\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/33-nolib.png 1154w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/33-nolib-300x204.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/33-nolib-1024x695.png 1024w\" sizes=\"(max-width: 1154px) 100vw, 1154px\" \/><\/a><\/li>\n<li>This happens because the libraries imported from packages are assumed to be already installed on the target in a directory where the application can find them. If you have previously tested tested out the library as a part of <a href=\"https:\/\/visualgdb.com\/tutorials\/linux\/cmake\/library\/\">this tutorial<\/a>, it should be already deployed to <strong>\/tmp\/MyLibraryDemo<\/strong>. Simply add this directory to SOLIB_SEARCH_PATH and executable will be able to locate it:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/34-path1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2975\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/34-path1.png\" alt=\"34-path\" width=\"793\" height=\"594\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/34-path1.png 793w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/34-path1-300x225.png 300w\" sizes=\"(max-width: 793px) 100vw, 793px\" \/><\/a><\/li>\n<li>If you want to debug the library sources while debugging your application, add the &#8220;set solib-search-path &lt;directory with the .so file on the Windows machine&gt; to the gdb startup commands (when importing the project via add_subdirectory() and adding a reference, VisualGDB would do this automatically):<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/35-solib.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2969\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/35-solib.png\" alt=\"35-solib\" width=\"1154\" height=\"783\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/35-solib.png 1154w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/35-solib-300x204.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/35-solib-1024x695.png 1024w\" sizes=\"(max-width: 1154px) 100vw, 1154px\" \/><\/a><\/li>\n<li>Now the library will get loaded and the breakpoints inside its functions will work as well:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/bkpt.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2976\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/bkpt.png\" alt=\"bkpt\" width=\"1154\" height=\"783\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/bkpt.png 1154w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/bkpt-300x204.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2017\/06\/bkpt-1024x695.png 1024w\" sizes=\"(max-width: 1154px) 100vw, 1154px\" \/><\/a><\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how to export a CMake library to a package and import it from a different project using<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[77,79,33,85],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/2973"}],"collection":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/comments?post=2973"}],"version-history":[{"count":1,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/2973\/revisions"}],"predecessor-version":[{"id":2977,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/2973\/revisions\/2977"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=2973"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=2973"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=2973"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}