将CMake对象库与共享库结合使用

时间:2018-05-30 09:09:53

标签: c++ cmake

我有以下CMakeLists.txt定义对象库和共享库,具体取决于对象库,如下所示:

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
)

链接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

这是因为foo.cpp不是使用-fPIC构建的(bar.cpp是)。这可以通过添加:

来解决
set_property(TARGET foo PROPERTY POSITION_INDEPENDENT_CODE ON)

这是解决此问题的正确方法吗?在我看来,应该有一个更清洁的解决方案。我觉得CMake在这里更聪明,并且看到来自foo的对象仅用于需要-fPIC的上下文中。我正在使用CMake 3.11。

某些背景;在我们的项目中,我们需要从分散在不同目录中的许多来源构建单个共享库。现在,我们为每个目录创建单独的共享库。这些库中的大多数依赖于Bison源,后台依赖于add_custom_command构建。这引入了库之间的编译时依赖性,严重限制了我们可以对构建进行并行化的程度(参见:https://gitlab.kitware.com/cmake/cmake/issues/15555)。

每个目录的对象库然后用于构建共享库似乎是解决此问题的一个很好的解决方案。

1 个答案:

答案 0 :(得分:5)

  

这是解决此问题的正确方法吗?

是的。

由于bar(共享)与foo(静态)相关联,因此必须使用与位置无关的代码编译barfoo

CMake知道bar是共享库,enables position independent code by default。但由于foo是一个静态对象,即使它可能猜测它需要是PIC 1 ,它默认情况下不会为foo启用PIC。

根据SO的问题What is the idiomatic way in CMAKE to add the -fPIC compiler option?

  

您可以在所有目标上设置与位置无关的代码属性:

set(CMAKE_POSITION_INDEPENDENT_CODE ON)
     

或在特定的图书馆:

add_library(lib1 SHARED lib1.cpp)
set_property(TARGET lib1 PROPERTY POSITION_INDEPENDENT_CODE ON)
     

参考:CMAKE_POSITION_INDEPENDENT_CODE cmake build system

1)这可能是建议的功能,也许已经是。