emilk / loguru

A lightweight C++ logging library

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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?