{"id":4871,"date":"2019-06-14T17:57:19","date_gmt":"2019-06-15T00:57:19","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=4871"},"modified":"2019-06-14T17:57:19","modified_gmt":"2019-06-15T00:57:19","slug":"using-the-target_link_libraries-statement-to-control-the-linked-libraries","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/linux\/cmake\/target_link_libraries\/","title":{"rendered":"Using the target_link_libraries() statement to control the linked libraries"},"content":{"rendered":"<p>This tutorial shows various ways to use CMake&#8217;s <strong>target_link_libraries()<\/strong> statement and explains the differences between them. We will create a basic Raspberry Pi project using the sqlite3 library and will then show different ways of using <strong>target_link_libraries()<\/strong> to reference the necessary libraries.<\/p>\n<p>In this tutorial we will use Visual Studio and VisualGDB, however the steps described below will work with any other CMake-based environment.<\/p>\n<ol>\n<li>Connect to your Raspberry Pi via SSH and install the <strong>libsqlite3-dev<\/strong> package. If you are using <a href=\"https:\/\/sysprogs.com\/SmarTTY\/\">SmarTTY<\/a>, the Tools-&gt;Manage Linux Packages command can help you find the exact package name easier:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/01-instpkg.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4872\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/01-instpkg.png\" alt=\"\" width=\"962\" height=\"617\" \/><\/a><\/li>\n<li>Start Visual Studio and open the VisualGDB Linux Project Wizard:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/02-newprj.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4873\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/02-newprj.png\" alt=\"\" width=\"941\" height=\"653\" \/><\/a><\/li>\n<li>On the first page select &#8220;Create Application -&gt; CMake -&gt; Ninja&#8221;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/03-cmake.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4874\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/03-cmake.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>On the next page select your Raspberry Pi cross-toolchain and pick the SSH connection for your Pi. Ensure the &#8220;test connection&#8221; checkbox is checked so that VisualGDB can check that all the necessary packages are present:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/04-toolchain.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4875\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/04-toolchain.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Press &#8220;Finish&#8221; to create the project. Once it is created, open VisualGDB Project Properties and click &#8220;Synchronize Sysroot&#8221; on the <strong>CMake project settings<\/strong> page. This will copy the sqlite libraries from the Raspberry Pi into the toolchain so that you can reference them from the projects built with that toolchain: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/05-sync-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4892\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/05-sync-1.png\" alt=\"\" width=\"974\" height=\"557\" \/><\/a><\/li>\n<li>Replace the contents of the main source file with the following basic project demonstrating the use of sqlite3:\n<pre class=\"\">#include &lt;iostream&gt;\r\n#include &lt;sqlite3.h&gt;\r\n\r\nusing namespace std;\r\n\r\nint main(int argc, char *argv[])\r\n{\r\n    int rc = sqlite3_initialize();\r\n    if (rc != SQLITE_OK)\r\n    {\r\n        printf(\"sqlite3_initialize() failed: error %d\\n\", rc);\r\n        return 1;\r\n    }\r\n    sqlite3 *db = nullptr;\r\n    rc = sqlite3_open(\"test.db\", &amp;db);\r\n    if (rc != SQLITE_OK)\r\n    {\r\n        printf(\"sqlite3_open() failed: error %d\\n\", rc);\r\n        return 1;\r\n    }\r\n\r\n    sqlite3_close(db);\r\n    return 0;\r\n}<\/pre>\n<\/li>\n<li>Try building the project. As we have included the header files (that provide the definitions for <strong>sqlite3_xxx()<\/strong> functions), but have not referenced the library defining them, the linker will fail due to missing definitions for the sqlite3 functions:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/06-code.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4877\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/06-code.png\" alt=\"\" width=\"1131\" height=\"807\" \/><\/a><\/li>\n<li>In order to fix the &#8220;<strong>undefined reference to &#8216;sqlite3_initialize&#8217;<\/strong>&#8221; errors, we need to locate the library that defines those symbols. This can be done by either checking the sqlite3 documentation, or searching for all libraries on Raspberry Pi for the name of the missing symbol (<strong>sqlite3_initialize<\/strong>):<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/07-libname.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4878\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/07-libname.png\" alt=\"\" width=\"786\" height=\"593\" \/><\/a><\/li>\n<li>Once you have located the library, add its full path to the Linked Libraries field under the VS properties for your main CMake target. Note that if the project is built on the Windows side, you would need to use the <strong>${CMAKE_SYSROOT}<\/strong> prefix to refer to the sysroot directory (a copy of the Raspberry Pi&#8217;s file system that is bundled with the toolchain). In this example the library path would be <strong>${CMAKE_SYSROOT}\/usr\/lib\/arm-linux-gnueabihf\/libsqlite3.a<\/strong>: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/08-sysroot.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4879\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/08-sysroot.png\" alt=\"\" width=\"1131\" height=\"807\" \/><\/a><\/li>\n<li>Alternatively, simply edit the <strong>target_link_libraries()<\/strong> statement for your library manually. Now the build will fail due to missing <strong>pthread<\/strong> and <strong>dl<\/strong> functions:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/09-thread.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4880\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/09-thread.png\" alt=\"\" width=\"1131\" height=\"807\" \/><\/a><\/li>\n<li>You could locate the library names for <strong>pthread<\/strong> and <strong>dl<\/strong> functions using similar steps as we used for <strong>libsqlite3<\/strong>, however in this tutorial we will use just the short names for simplicity (we will explain the differences between the short names and full paths inside <strong>target_link_libraries()<\/strong> later):<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/10-otherlibs.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4881\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/10-otherlibs.png\" alt=\"\" width=\"1131\" height=\"807\" \/><\/a><\/li>\n<li>Press F5 to start debugging and ensure the program runs successfully:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/11-opened.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4882\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/11-opened.png\" alt=\"\" width=\"1131\" height=\"807\" \/><\/a><\/li>\n<li>Open the CMakeLists.txt file and locate the <strong>target_link_libraries()<\/strong> statement. It will normally have the following contents:\n<pre class=\"\">target_link_libraries(TargetLinkLibrariesDemo \r\n\t${CMAKE_SYSROOT}\/usr\/lib\/arm-linux-gnueabihf\/libsqlite3.a\r\n\tpthread\r\n\tdl)<\/pre>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/12-libs.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4883\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/12-libs.png\" alt=\"\" width=\"1131\" height=\"807\" \/><\/a>Each Linux library normally comes with 2 versions: a static and a dynamic one. The static library is typically called <strong>lib&lt;name&gt;.a,<\/strong> while the dynamic library is called <strong>lib&lt;name&gt;.so<\/strong> or <strong>lib&lt;name&gt;.so.&lt;version&gt;<\/strong>. If you are using a static library, the code from it will be copied to your executable during the linking, so you won&#8217;t need to have a copy of the library on the target. This is particularly useful for devices with limited storage.<\/li>\n<li>The <strong>target_link_libraries()<\/strong> statement allows specifying both full library paths and just library names (without the <strong>lib<\/strong> prefix). Change the statement to use the syntax below and build your project again:\n<pre class=\"\">target_link_libraries(TargetLinkLibrariesDemo \r\n    sqlite3\r\n    pthread\r\n    dl)<\/pre>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/14-short.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4885\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/14-short.png\" alt=\"\" width=\"1131\" height=\"807\" \/><\/a><\/li>\n<li>Try running the project so that it gets deployed to Raspberry Pi and then show the dynamic library dependencies for it using the &#8216;ldd&#8217; tool:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/17-dep.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4886\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/17-dep.png\" alt=\"\" width=\"1011\" height=\"414\" \/><\/a>As you can see, CMake has automatically picked the dynamic version of the library instead of the static one, so the program will expect the <strong>libsqlite3.so.0<\/strong> file to be present on the target.<\/li>\n<li>We can instruct CMake to prefer the static version of <strong>libsqlite3<\/strong> without hardcoding the full path by using the <strong>find_library()<\/strong> command. Replace the <strong>target_link_libraries()<\/strong> statement with the following code:\n<pre class=\"\">find_library(sqlite3 libsqlite3.a sqlite3)\r\ntarget_link_libraries(TargetLinkLibrariesDemo \r\n    ${sqlite3}\r\n    pthread\r\n    dl)<\/pre>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/18-static.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4887\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/18-static.png\" alt=\"\" width=\"1131\" height=\"807\" \/><\/a>The <strong>find_library()<\/strong> statement will try to find a library with the specified names (first trying <strong>libsqlite3.a<\/strong>, then <strong>libsqlite3.*<\/strong>) and will remember the path of the library in the sqlite3 variable. Note that &#8220;<strong>${sqlite3}&#8221;<\/strong> in <strong>target_link_libraries()<\/strong> means &#8220;the library pointed by the sqlite3 variable&#8221; and &#8220;sqlite3&#8221; would mean &#8220;<strong>libsqlite3.*<\/strong>&#8220;.<\/li>\n<li>You can see what exactly is going on by using VisualGDB&#8217;s CMake debugger. Right-click on the project in Solution Explorer and select &#8220;Launch CMake Debugger&#8221;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/19-debug.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4888\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/19-debug.png\" alt=\"\" width=\"1131\" height=\"807\" \/><\/a><\/li>\n<li>Step to the <strong>target_link_libraries()<\/strong> line and check the <strong>sqlite3<\/strong> variable. It will display the path of the library found by CMake:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/20-path.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4889\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/20-path.png\" alt=\"\" width=\"1131\" height=\"807\" \/><\/a><\/li>\n<li>You can double-check that the program produced by CMake no longer has a dependency on <strong>libsqlite3.so<\/strong> by running ldd again: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/21-deps.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4890\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/21-deps.png\" alt=\"\" width=\"1011\" height=\"414\" \/><\/a><\/li>\n<li>One last way to improve this example would be to tell CMake that the <strong>libsqlite3.a<\/strong> library also needs <strong>dl<\/strong> and <strong>pthread<\/strong>. This could be done in 3 steps:\n<ol>\n<li>Finding the exact location of <strong>libsqlite3.a<\/strong><\/li>\n<li>Registering it with CMake as an imported library<\/li>\n<li>Adding dl and pthread to the INTERFACE part of its own <strong>target_link_libraries()<\/strong> statement.<\/li>\n<\/ol>\n<p>The following CMake statements will do what we have described above:<\/p>\n<pre class=\"\">find_library(sqlite3 libsqlite3.a)\r\n\r\nadd_library(sqlite3 STATIC IMPORTED)\r\nset_target_properties(sqlite3 PROPERTIES IMPORTED_LOCATION ${sqlite3})\r\n\r\ntarget_link_libraries(sqlite3 INTERFACE pthread dl)\r\n\r\ntarget_link_libraries(TargetLinkLibrariesDemo sqlite3)<\/pre>\n<p>Now the project will link with both <strong>pthread<\/strong> and <strong>dl<\/strong> without referencing them explicitly:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/lib.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4893\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2019\/06\/lib.png\" alt=\"\" width=\"1131\" height=\"807\" \/><\/a>This happens because the main application references the imported <strong>sqlite3<\/strong> library that has <strong>pthread<\/strong> and <strong>dl<\/strong> in its interface (i.e. settings that are applied to all targets that reference a certain target). If your project had multiple applications, you would only need to reference the <strong>sqlite3<\/strong> library from each of them and the libraries required by it would be automatically added to each of the built applications.<\/li>\n<\/ol>\n<p>For more complex projects involving multiple libraries, consider using CMake&#8217;s package system described in our <a href=\"https:\/\/visualgdb.com\/tutorials\/linux\/cmake\/find_package\/\">find_package()<\/a> tutorial.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows various ways to use CMake&#8217;s target_link_libraries() statement and explains the differences between them. We will create a<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[172],"tags":[77,79,33],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/4871"}],"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=4871"}],"version-history":[{"count":1,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/4871\/revisions"}],"predecessor-version":[{"id":4894,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/4871\/revisions\/4894"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=4871"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=4871"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=4871"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}