Dynamic libraries and CMake
On Unix-like platforms, CMake variable CMAKE_DL_LIBS is populated to link with target_link_libraries(), providing functions like “dlopen” and “dladdr”. For some libdl functions it’s necessary to also define “_GNU_SOURCE” like:
add_library(mylib SHARED mylib.c)
target_link_libraries(mylib PRIVATE ${CMAKE_DL_LIBS})
target_compile_definitions(mylib PRIVATE _GNU_SOURCE)
On Windows different mechanisms can be used to access dynamic libraries. With MSYS2 libdl is available via mingw-w64-x86_64-dlfcn.
Run path (Rpath)
On Unix-like systems, the concept of run path is the search path for libraries used by a binary at runtime. For Windows there is no separate Rpath, just PATH is used–necessary .dll files must be on PATH environment variable at the time of running a binary. For Unix-like systems life can be easier since the Rpath is compiled into a binary. Optionally, using $ORIGIN in Rpath allows relocating binary packages.
For CMake, we use these options on virtually all our projects. We have them set all the time – no need for “if()” statements.
include(GNUInstallDirs)
set(CMAKE_INSTALL_NAME_DIR ${CMAKE_INSTALL_FULL_LIBDIR})
set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_FULL_LIBDIR})
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH true)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS true)
Exporting symbols for MSVC-based compilers is necessary to generate a “my.lib” corresponding to the “my.dll”.
To have the installed CMake binaries work correctly, it’s necessary to set CMAKE_PREFIX_PATH at configure time. That is, the configure-build-install sequence for shared library project in CMake is like:
cmake -Bbuild -DBUILD_SHARED_LIBS=on -DCMAKE_INSTALL_PREFIX=/opt/my_program
cmake --build build
cmake --install build
In general the rpath in a binary can be checked like:
- Linux:
readelf -d /path/to/binary | head -n 25
- macOS:
otool -l /path/to/binary | tail
References: