CMake: Errors when linking to shared library
abhaybd opened this issue · comments
I'm trying to use Loguru as a dependency for my shared library, but it's crashing with link-time errors. I have found a workaround that solves the issue, but this should probably be fixed, or at least documented.
Simple example:
main.cpp
:
#include <loguru.hpp>
void foo();
int main() {
LOG_F(INFO, "Hello, world!");
foo();
}
library.cpp
:
#include <loguru.hpp>
void foo() {
LOG_F(INFO, "Foo was called!");
}
CMakeLists.txt
:
cmake_minimum_required(VERSION 3.10)
project(loguru_cmake_example CXX)
include(FetchContent)
FetchContent_Declare(LoguruGitRepo
GIT_REPOSITORY "https://github.com/emilk/loguru" # can be a filesystem path
GIT_TAG "master"
)
FetchContent_MakeAvailable(LoguruGitRepo) # defines target 'loguru::loguru'
add_library(lib SHARED library.cpp)
target_link_libraries(lib PRIVATE loguru::loguru)
add_executable(main main.cpp)
target_link_libraries(main PRIVATE loguru::loguru lib)
After configuring with CMake (version 3.16.3), running make -j $(nproc)
yields:
/usr/bin/ld: _deps/logurugitrepo-build/libloguru.a(loguru.cpp.o): relocation R_X86_64_PC32 against symbol `_ZN6loguru19g_flush_interval_msE' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: bad value
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/lib.dir/build.make:85: liblib.so] Error 1
make[1]: *** [CMakeFiles/Makefile2:126: CMakeFiles/lib.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
Workaround
This error can be fixed by adding set(BUILD_SHARED_LIBS ON)
before the FetchContent_MakeAvailable(...)
call. After adding this line, I get a new error:
/usr/bin/ld: _deps/logurugitrepo-build/libloguru.so.2.1.0: undefined reference to `dladdr'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/main.dir/build.make:86: main] Error 1
make[1]: *** [CMakeFiles/Makefile2:99: CMakeFiles/main.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
I found that I can fix this new error by adding set(LOGURU_STACKTRACES ON)
before the FetchContent_MakeAvailable(...)
call.
After adding these lines, the new CMakeLists.txt
looks like:
cmake_minimum_required(VERSION 3.10)
project(loguru_cmake_example CXX)
include(FetchContent)
FetchContent_Declare(LoguruGitRepo
GIT_REPOSITORY "https://github.com/emilk/loguru" # can be a filesystem path
GIT_TAG "master"
)
set(BUILD_SHARED_LIBS ON)
set(LOGURU_STACKTRACES ON)
FetchContent_MakeAvailable(LoguruGitRepo) # defines target 'loguru::loguru'
add_library(lib SHARED library.cpp)
target_link_libraries(lib PRIVATE loguru::loguru)
add_executable(main main.cpp)
target_link_libraries(main PRIVATE loguru::loguru lib)
And compilation now works. Note that this issue only happens when linking a shared library against loguru, static libraries and executables work fine.
How can this issue be fixed without requiring users to implement these workarounds, or at least document that these statements are necessary for shared libraries?