I have the following CMakeLists.txt defining an object library and a shared library depending on the object library, as follows:
add_library(foo OBJECT
foo.cpp
)
add_library(bar SHARED
bar.cpp
$<TARGET_OBJECTS:foo>
)
add_executable(baz baz.cpp)
target_link_libraries(baz
PUBLIC bar
)
I get the following linker error when linking baz
:
/usr/bin/ld: CMakeFiles/foo.dir/foo.cpp.o: relocation R_X86_64_PC32 against symbol `_ZSt4cout@@GLIBCXX_3.4' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
This is because foo.cpp
is not build with -fPIC
(bar.cpp
is). This can be solved by adding:
set_property(TARGET foo PROPERTY POSITION_INDEPENDENT_CODE ON)
Is this the right way to fix this issue? I seems to me there should be a cleaner solution for this. I feel CMake can be smarter here and see that the objects from foo
are only used in a context where -fPIC
is required. I am using CMake 3.11.
Some context; in our project, we need to build a single shared library from a lot of sources scattered around in different directories. Right now, we create separate shared libraries for each directory. Most of these libraries depend on Bison sources, which behind the scenes depend on add_custom_command
to be build. This introduces compile time dependencies between the libraries, seriously limiting how much we can parallelize the build (see: https://gitlab.kitware.com/cmake/cmake/issues/15555).
Object libraries per directory which are then used to build the shared library seem to be a nice solution for this problem.
To add a library in CMake, use the add_library() command and specify which source files should make up the library. Rather than placing all of the source files in one directory, we can organize our project with one or more subdirectories. In this case, we will create a subdirectory specifically for our library.
Specify libraries or flags to use when linking a given target and/or its dependents. Usage requirements from linked library targets will be propagated. Usage requirements of a target's dependencies affect compilation of its own sources.
To build everything, just place yourself into the build directory and run: /tmp/example/library/build $ cmake .. That's it, you should find mymath. h under /usr/local/include as well as libmymath.so under /usr/local/lib .
Is this the right way to fix this issue?
Yes it is.
Since bar
(shared) is linked against foo
(static), both of bar
and foo
must be compiled with position independent code.
CMake knows bar
is a shared library, and enables position independent code by default. But since foo
is a static object, even though it could guess it needs to be PIC1, it does not enable PIC by default for foo
.
According to SO's question What is the idiomatic way in CMAKE to add the -fPIC compiler option?
You can set the position independent code property on all targets:
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
or in a specific library:
add_library(lib1 SHARED lib1.cpp) set_property(TARGET lib1 PROPERTY POSITION_INDEPENDENT_CODE ON)
Reference: CMAKE_POSITION_INDEPENDENT_CODE cmake build system
1) This could be a suggested feature, maybe it is already.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With