I am trying to use an external third-party shared library file in my project using the CMake build system, where I have access to just the .so file and its relevant headers. As a minimal example, pretend this external library (called hello
) is defined as follows:
hello.h
#pragma once
void hello(void);
hello.c
#include "hello.h"
#include <stdio.h>
void hello(void)
{
printf("Hello world!\n");
}
The example library could have been built externally with (specifics here don't matter):
g++ -shared -o libhello.so -fPIC hello.c
This shared library is confirmed to have a hello
function in its external table using nm -gDC libhello.so
:
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
0000000000001119 T hello()
w __cxa_finalize
w __gmon_start__
U puts
Given access to libhello.so
and hello.h
(the real external library, the Chromium Embedded Framework
or CEF
is obviously more complicated than this with multiple directories), I naively copy the relevant headers and shared library into my project so that I can use this hello
function.
This is my resulting project folder structure:
├── CMakeLists.txt
├── libs
│ └── hello
│ ├── include
│ │ └── hello.h
│ └── libhello.so
└── src
└── main.cpp
The main.cpp
file is obviously nothing special:
#include "hello.h"
int main(void)
{
hello();
return 0;
}
The important part, the CMakeLists.txt
file, is written like this:
cmake_minimum_required(VERSION 3.0)
project(test)
add_library(HELLO SHARED IMPORTED)
set_target_properties(
HELLO
PROPERTIES
IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/libs/hello/libhello.so"
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/libs/hello/include/"
)
add_executable(index src/main.cpp)
target_link_libraries(index HELLO)
Building and attempting to run client program is performed as follows from the root of this directory:
mkdir build
cd ./build
cmake ..
make
./index
I am met with the following error message:
Scanning dependencies of target index
[ 50%] Building CXX object CMakeFiles/index.dir/src/main.cpp.o
[100%] Linking CXX executable index
/usr/bin/ld: CMakeFiles/index.dir/src/main.cpp.o: in function `main':
main.cpp:(.text+0x9): undefined reference to `hello()'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/index.dir/build.make:85: index] Error 1
make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/index.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
How do I resolve this linking error in my project? If platform-specifics matter, I am on Ubuntu 20.04 WSL2 with cmake --version
of 3.16.3
.
UPDATE #1:
Attempting to use the more idiomatic target_include_directories
yields the same error (new CMakeLists.txt
as follows):
cmake_minimum_required(VERSION 3.0)
project(test)
add_library(HELLO SHARED IMPORTED)
set_target_properties(
HELLO
PROPERTIES
IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/libs/hello/libhello.so"
#INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/libs/hello/include/"
)
add_executable(index src/main.cpp)
target_include_directories(index PUBLIC ${CMAKE_SOURCE_DIR}/libs/hello/include/)
target_link_libraries(index HELLO)
UPDATE #2:
Running the compilation make step with make VERBOSE=1
yields the following additional diagnostic information:
make VERBOSE=1
/usr/bin/cmake -S/home/anish/repos/hello_test -B/home/anish/repos/hello_test/build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /home/anish/repos/hello_test/build/CMakeFiles /home/anish/repos/hello_test/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/home/anish/repos/hello_test/build'
make -f CMakeFiles/index.dir/build.make CMakeFiles/index.dir/depend
make[2]: Entering directory '/home/anish/repos/hello_test/build'
cd /home/anish/repos/hello_test/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/anish/repos/hello_test /home/anish/repos/hello_test /home/anish/repos/hello_test/build /home/anish/repos/hello_test/build /home/anish/repos/hello_test/build/CMakeFiles/index.dir/DependInfo.cmake --color=
Dependee "/home/anish/repos/hello_test/build/CMakeFiles/index.dir/DependInfo.cmake" is newer than depender "/home/anish/repos/hello_test/build/CMakeFiles/index.dir/depend.internal".
Dependee "/home/anish/repos/hello_test/build/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/home/anish/repos/hello_test/build/CMakeFiles/index.dir/depend.internal".
Scanning dependencies of target index
make[2]: Leaving directory '/home/anish/repos/hello_test/build'
make -f CMakeFiles/index.dir/build.make CMakeFiles/index.dir/build
make[2]: Entering directory '/home/anish/repos/hello_test/build'
[ 50%] Building CXX object CMakeFiles/index.dir/src/main.cpp.o
/usr/bin/c++ -I/home/anish/repos/hello_test/libs/hello/include -o CMakeFiles/index.dir/src/main.cpp.o -c /home/anish/repos/hello_test/src/main.cpp
[100%] Linking CXX executable index
/usr/bin/cmake -E cmake_link_script CMakeFiles/index.dir/link.txt --verbose=1
/usr/bin/c++ -rdynamic CMakeFiles/index.dir/src/main.cpp.o -o index -Wl,-rpath,/home/anish/repos/hello_test/libs/hello ../libs/hello/libhello.so
/usr/bin/ld: CMakeFiles/index.dir/src/main.cpp.o: in function `main':
main.cpp:(.text+0x9): undefined reference to `hello()'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/index.dir/build.make:85: index] Error 1
make[2]: Leaving directory '/home/anish/repos/hello_test/build'
make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/index.dir/all] Error 2
make[1]: Leaving directory '/home/anish/repos/hello_test/build'
make: *** [Makefile:84: all] Error 2