# Linking to a library of my own code that requires 3rd party library

**URL:** https://discourse.cmake.org/t/linking-to-a-library-of-my-own-code-that-requires-3rd-party-library/1526
**Category:** Usage
**Tags:** os:linux, comp:gcc
**Created:** [July 9, 2020, 7:10pm UTC](https://discourse.cmake.org/t/linking-to-a-library-of-my-own-code-that-requires-3rd-party-library/1526 "2020-07-09T19:10:10Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![DavidA](https://discourse.cmake.org/user_avatar/discourse.cmake.org/davida/32/128_2.png) [@DavidA](https://discourse.cmake.org/u/DavidA)
#### Post date: [July 9, 2020, 7:10pm UTC](https://discourse.cmake.org/t/linking-to-a-library-of-my-own-code-that-requires-3rd-party-library/1526/1 "2020-07-09T19:10:10Z")

</div>

I have a working CMake test project that consists of my C++ code linked to a 3rd party library called DPDK, targeting Linux. I now want to separate my code into a main.cpp and my own library of my functions that require DPDK. I have two CMakeLists.txt files, here is an outline of each:

**Top-level CMakeLists.txt**

```
project(main VERSION 1.0 LANGUAGES CXX C)
set(_target_name dpdk_test)
set(_dpdk_version dpdk-stable-18.11.8)

add_subdirectory(dpdk)

add_executable(${_target_name} main.cpp )

target_include_directories(${_target_name} PRIVATE dpdk/include)
target_include_directories(${_target_name} PRIVATE /opt/dpdk/${_dpdk_version}/x86_64-native-linuxapp-gcc/include)

target_link_libraries(${_target_name} dpdk)

# Enable the -pthread compiler and linker flag
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(${_target_name}
    Threads::Threads)

```

**’dpdk’ CMakeLists.txt**

```
set (_lib_name "dpdk")
set(_dpdk_version dpdk-stable-18.11.8)

add_definitions(
    -DRTE_MACHINE_CPUFLAG_SSE 
<snip>)

add_library(${_lib_name} STATIC "")

target_sources(${_lib_name} 
    PRIVATE
        ThreadDpdk.cpp
<snip>
)

target_include_directories(${_lib_name} PRIVATE /opt/dpdk/${_dpdk_version}/x86_64-native-linuxapp-gcc/include)

# Enable the -pthread compiler and linker flag
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(${_lib_name}
    Threads::Threads)

# Library paths
set(_lib64_path /usr/lib64/)
set(_dpdk_path /opt/dpdk/${_dpdk_version}/x86_64-native-linuxapp-gcc/lib/)

target_link_libraries(${_lib_name}
     ${_lib64_path}libdl.so
     ${_lib64_path}libutil.so
     ${_lib64_path}libm.so
     -Xlinker -export-dynamic

     # dpdk libraries
     ${_dpdk_path}librte_flow_classify.a
     -Wl,--whole-archive
     ${_dpdk_path}librte_pipeline.a
     <snip>
     -Wl,--no-whole-archive
     ${_dpdk_path}librte_pdump.a
     <snip>
     -Wl,--whole-archive
     ${_dpdk_path}librte_acl.a
     -Wl,--no-whole-archive
      <snip>
     -Wl,--whole-archive
     ${_dpdk_path}librte_cfgfile.a 
<snip>
     -Wl,--no-whole-archive
     
     -lrt -lm -lnuma -ldl
     ${_lib64_path}libconfig.so

     -Wl,-export
     -Dynamic 
     #-L/opt/dpdk/${_dpdk_version}/examples/l2fwd/build/lib -L/opt/dpdk/${_dpdk_version}/x86_64-native-linuxapp-gcc/lib 
     -Wl,--as-needed 
     -Wl,-Map=${_target_name}.map 
     -Wl,--cref      
     )

```

**My question**

When I build the project, the library builds ok, but linking the executable fails:

```
[60%] Built target dpdk
[66%] Linking CXX executable dpdk_test
/opt/dpdk/dpdk-stable-18.11.8/x86_64-native-linuxapp-gcc/lib/librte_eal.a(eal_common_devargs.o): 
In function `rte_devargs_layers_parse':
eal_common_devargs.c:(.text+0x159): undefined reference to `rte_kvargs_parse_delim'

```

My question is, do I need to specify the DPDK libraries in the top-level CMakeLists.txt file, or is it sufficient to specify them in the library’s CMakeLists.txt file? (main.cpp does not call DPDK functions).

I think I need this clear in my thinking before I go further.

---

<div class="post-metadata">

### Author: ![kyle.edwards](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/k/65b543/32.png) [@kyle.edwards](https://discourse.cmake.org/u/kyle.edwards)
#### Post date: [July 9, 2020, 7:27pm UTC](https://discourse.cmake.org/t/linking-to-a-library-of-my-own-code-that-requires-3rd-party-library/1526/2 "2020-07-09T19:27:15Z")

</div>

> [@DavidA](#):
>
> My question is, do I need to specify the DPDK libraries in the top-level CMakeLists.txt file, or is it sufficient to specify them in the library’s CMakeLists.txt file? (main.cpp does not call DPDK functions).

If main does not call DPDK then you only need to link it from the library, not from main.

Also, you have a lot of flags in `target_link_libraries()` that should be in `target_link_options()` instead. I’m not sure how exactly to handle `--whole-archive` and `--no-whole-archive` in a more CMake-like way… @brad.king any thoughts?

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [July 10, 2020, 5:16am UTC](https://discourse.cmake.org/t/linking-to-a-library-of-my-own-code-that-requires-3rd-party-library/1526/3 "2020-07-10T05:16:03Z")

</div>

> [@DavidA](#):
>
> ```auto
> target_include_directories(${_lib_name} PRIVATE /opt/dpdk/${_dpdk_version}/x86_64-native-linuxapp-gcc/include)
> 
> ```

I thing, that should be PUBLIC, than it is automatically imported with

> [@DavidA](#):
>
> `target_link_libraries(${_target_name} dpdk)`

This imports too the dependent defines and link library list … Don’t repeat yourself. So you my skip this:

> [@DavidA](#):
>
> ```auto
> # Enable the -pthread compiler and linker flag
> set(THREADS_PREFER_PTHREAD_FLAG ON)
> find_package(Threads REQUIRED)
> target_link_libraries(${_target_name}
> Threads::Threads)
> 
> ```

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [July 10, 2020, 10:04am UTC](https://discourse.cmake.org/t/linking-to-a-library-of-my-own-code-that-requires-3rd-party-library/1526/4 "2020-07-10T10:04:08Z")

</div>

Rather than `--whole-archive/--no-whole-archive` pairs, one could use the `-force_load` flag that applies only to the immediately following library. See [CMake Issue 20078](https://gitlab.kitware.com/cmake/cmake/-/issues/20078) for discussion of adding a first-class way to attach such a flag. Without such a feature (or possibly the workaround discussed in the issue), the only way to reliably list a sequence of flags and libraries and make sure they appear in order on the final link line is to put them directly in the `target_link_libraries` call for the final target that needs to have all objects from all the `.a` files.

---

<div class="post-metadata">

### Author: ![DavidA](https://discourse.cmake.org/user_avatar/discourse.cmake.org/davida/32/128_2.png) [@DavidA](https://discourse.cmake.org/u/DavidA)
#### Post date: [July 10, 2020, 11:03am UTC](https://discourse.cmake.org/t/linking-to-a-library-of-my-own-code-that-requires-3rd-party-library/1526/5 "2020-07-10T11:03:41Z")

</div>

Thanks for your replies. I am rather confused as, if I build with ninja -v, I see the compile commands for the source files and then a link command for the executable, which begins:

```auto
/opt/rh/devtoolset-7/root/usr/bin/g++ -I../dpdk/include -I../include -I/opt/dpdk/dpdk-stable-18.11.8/x86_64-native-linuxapp-gcc/include -I../dpdk/../include -march=native -g -pthread -std=c++1y -MD -MT CMakeFiles/dpdk_test.dir/main.cpp.o -MF CMakeFiles/dpdk_test.dir/main.cpp.o.d -o CMakeFiles/dpdk_test.dir/main.cpp.o -c ../main.cpp
[6/6] : && /opt/rh/devtoolset-7/root/usr/bin/g++ -march=native -g   
CMakeFiles/dpdk_test.dir/main.cpp.o CMakeFiles/dpdk_test.dir/Threads.cpp.o CMakeFiles/dpdk_test.dir/ThreadMon.cpp.o 
CMakeFiles/dpdk_test.dir/ThreadMSG.cpp.o CMakeFiles/dpdk_test.dir/_kbhit.cpp.o  
-o dpdk_test  
dpdk/libdpdk.a  
/usr/lib64/libdl.so /usr/lib64/libutil.so /usr/lib64/libm.so -Xlinker  
-export-dynamic /opt/dpdk/dpdk-stable-18.11.8/x86_64-native-linuxapp-gcc/lib/librte_flow_classify.a  
-Wl,--whole-archive /opt/dpdk/dpdk-stable-18.11.8/x86_64-native-linuxapp-gcc/lib/librte_pipeline.a  
/opt/dpdk/dpdk-stable-18.11.8/x86_64-native-linuxapp-gcc/lib/librte_table.a
etc.

```

That link command links to libdpdk.a (my library) as expected, but it also links to all the 3rd party dpdk libraries, which I don’t expect.

Furthermore, I don’t see a linker command for libdpdk.a itself.

Any ideas please?

---

<div class="post-metadata">

### Author: ![fenrir](https://discourse.cmake.org/user_avatar/discourse.cmake.org/fenrir/32/734_2.png) [@fenrir](https://discourse.cmake.org/u/fenrir)
#### Post date: [July 10, 2020, 11:52am UTC](https://discourse.cmake.org/t/linking-to-a-library-of-my-own-code-that-requires-3rd-party-library/1526/6 "2020-07-10T11:52:43Z")

</div>

This is what you get if you don’t specify `PRIVATE` for `target_link_libraries` of your library - the dependencies are carried to the target that links to it.

---

<div class="post-metadata">

### Author: ![DavidA](https://discourse.cmake.org/user_avatar/discourse.cmake.org/davida/32/128_2.png) [@DavidA](https://discourse.cmake.org/u/DavidA)
#### Post date: [July 10, 2020, 12:49pm UTC](https://discourse.cmake.org/t/linking-to-a-library-of-my-own-code-that-requires-3rd-party-library/1526/7 "2020-07-10T12:49:50Z")

</div>

I tried PRIVATE but the result was the same.

---

<div class="post-metadata">

### Author: ![DavidA](https://discourse.cmake.org/user_avatar/discourse.cmake.org/davida/32/128_2.png) [@DavidA](https://discourse.cmake.org/u/DavidA)
#### Post date: [July 10, 2020, 2:07pm UTC](https://discourse.cmake.org/t/linking-to-a-library-of-my-own-code-that-requires-3rd-party-library/1526/8 "2020-07-10T14:07:26Z")

</div>

As my project was quite complicated I have started again with a simple example I found online.

**Top level CMakeLists.txt**

```auto
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)

project("To Do List")

include_directories(${CMAKE_CURRENT_SOURCE_DIR})

add_subdirectory(ToDoCore)

add_executable(toDo main.cc)
target_link_libraries(toDo PRIVATE toDoCore)

```

**Library CMakeLists.txt**

```auto
set (_lib_name "toDoCore")

add_library(${_lib_name})

target_sources(${_lib_name} 
    PRIVATE
         ToDo.cc
)

target_link_libraries(${_lib_name} 
     PRIVATE ${_lib64_path}libdl.so
     PRIVATE ${_lib64_path}libutil.so
     PRIVATE ${_lib64_path}libm.so
)

```

**Build output**

```auto
$ ninja -v
[1/4] /usr/bin/c++ -I../ -MD -MT ToDoCore/CMakeFiles/toDoCore.dir/ToDo.cc.o -MF ToDoCore/CMakeFiles/toDoCore.dir/ToDo.cc.o.d -o ToDoCore/CMakeFiles/toDoCore.dir/ToDo.cc.o -c ../ToDoCore/ToDo.cc
[2/4] : && /usr/local/bin/cmake -E remove ToDoCore/libtoDoCore.a && /usr/bin/ar qc ToDoCore/libtoDoCore.a ToDoCore/CMakeFiles/toDoCore.dir/ToDo.cc.o && /usr/bin/ranlib ToDoCore/libtoDoCore.a && :
[3/4] /usr/bin/c++ -I../ -MD -MT CMakeFiles/toDo.dir/main.cc.o -MF CMakeFiles/toDo.dir/main.cc.o.d -o CMakeFiles/toDo.dir/main.cc.o -c ../main.cc
[4/4] : && /usr/bin/c++ -rdynamic CMakeFiles/toDo.dir/main.cc.o -o toDo ToDoCore/libtoDoCore.a -ldl -lutil -lm && :

```

This demonstrates that the external libraries specified in the ‘library’ CMakeLists.txt don’t get linked into that library, but get linked into the executable.

From [https://stackoverflow.com/a/14480396/4940771](https://stackoverflow.com/a/14480396/4940771) I read:

```auto
I think it's CMake's default behavior to not link project2 to the external library, but to link both libraries to the executable. From the book "Mastering CMake".

Since static libraries do not link to the libraries on which they depend, it is important for CMake to keep track of the libraries so they can be specified on the link line of the executable being created.

```

What would be the way around this (i.e. to include the libraries in the target library)? Use “ar” in some way?

---

<div class="post-metadata">

### Author: ![DavidA](https://discourse.cmake.org/user_avatar/discourse.cmake.org/davida/32/128_2.png) [@DavidA](https://discourse.cmake.org/u/DavidA)
#### Post date: [July 13, 2020, 2:01pm UTC](https://discourse.cmake.org/t/linking-to-a-library-of-my-own-code-that-requires-3rd-party-library/1526/9 "2020-07-13T14:01:21Z")

</div>

I have fixed this problem by linking to shared dpdk libraries, rather than static libraries. I have unresolved symbols but will discuss that in another thread. We can close this issue now.
