I wrote a shared library mylib1 that uses a 3rd-party shared library, in my case libtinyxml2 (for this problem the 3rd-party library is irrelevant: it can be any library). And I wrote an application app1 which depends on mylib1.
Building mylib1 succeeds, but building app1 fails, presumably because the linker was not told to link against libtinyxml2 when linking app1.
What am I missing?
[I][~/Programs/cmake-jenkins/big_proj/src/build]$ make
[ 25%] Building CXX object mylib1/CMakeFiles/mylib1.dir/src/my_functions.cpp.o
[ 50%] Linking CXX shared library libmylib1.so
[ 50%] Built target mylib1
[ 75%] Building CXX object app1/CMakeFiles/app1.dir/src/main.cpp.o
[100%] Linking CXX executable app1
../mylib1/libmylib1.so: undefined reference to `tinyxml2::StrPair::Reset()'
../mylib1/libmylib1.so: undefined reference to `tinyxml2::StrPair::~StrPair()'
collect2: error: ld returned 1 exit status
make[2]: *** [app1/CMakeFiles/app1.dir/build.make:97: app1/app1] Error 1
make[1]: *** [CMakeFiles/Makefile2:402: app1/CMakeFiles/app1.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
Folder structure
.
├── app1
│ ├── CMakeLists.txt
│ ├── src
│ │ ├── include
│ │ │ └── functions_p.hpp
│ │ └── main.cpp
├── CMakeLists.txt
└── mylib1
├── CMakeLists.txt
├── src
│ ├── include
│ │ └── my_functions.hpp
│ └── my_functions.cpp
./CMakeLists.txt
# Top level CMakeLists.txt
cmake_minimum_required(VERSION 3.8.2)
add_subdirectory(app1)
add_subdirectory(mylib1)
app1/CMakeLists.txt
project("app1" CXX)
set(APP1_SOURCE_FILES src/main.cpp )
add_executable(app1 ${APP1_SOURCE_FILES})
target_include_directories(app1
PRIVATE src/include)
target_link_libraries(app1 mylib1)
mylib1/CMakeLists.txt
project("lib1" CXX)
find_library(TINYXML_LIB tinyxml2 REQUIRED)
set(MYLIB1_SOURCE_FILES src/my_functions.cpp )
set(MYLIB_INCLUDE_FILES src/include/my_functions.hpp)
add_library(mylib1 SHARED ${MYLIB1_SOURCE_FILES} ${MYLIB1_INCLUDE_FILES} )
target_include_directories(mylib1
PUBLIC src/include)
# I have checked that TINYXML_LIB is set, so the library IS found.
target_link_libraries(mylib1 PUBLIC ${TINYXML_LIB})
The readelf output shows the library has a dependency to libtinyxml2.so.6, and this file exists as /usr/lib/libtinyxml2.so.6 on my system.
[I][~/Programs/cmake-jenkins/big_proj/src/build]$ readelf -d mylib1/libmylib1.so
Dynamic section at offset 0x16cd0 contains 29 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libtinyxml2.so.6]
0x0000000000000001 (NEEDED) Shared library: [libstdc++.so.6]
0x0000000000000001 (NEEDED) Shared library: [libm.so.6]
0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000e (SONAME) Library soname: [libmylib1.so]
Running the generated Makefile in verbose mode shows that indeed when app1 is linked, it does not link against libtinyxml2:
[ 75%] Linking CXX executable app1
cd /home/danb/Programs/cmake-jenkins/big_proj/src/build/app1 && /usr/bin/cmake -E cmake_link_script CMakeFiles/app1.dir/link.txt --verbose=1
/usr/bin/c++ CMakeFiles/app1.dir/src/main.cpp.o -o app1 -Wl,-rpath,/home/danb/Programs/cmake-jenkins/big_proj/src/build/mylib1 ../mylib1/libmylib1.so