【问题标题】:Combining CMake object libraries with shared libraries将 CMake 对象库与共享库相结合
【发布时间】:2018-11-09 01:46:59
【问题描述】:

我有如下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)。

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

【问题讨论】:

  • 编译器标志等 CMake 属性将在需要的范围内渗透到所有相关目标。但是,您想要的基本上是某些属性也可以“涓涓细流”。我不认为这就是它的工作方式,甚至从 CMake 开发人员的角度来看它也不是预期的工作方式。当然,你可以为 CMake 编写一个补丁来做到这一点,但我怀疑它是否会被主线接受,只是说...... :-)
  • @ArneVogel,确实有道理。
  • 我很高兴,如果你昨天没有问这个问题,我今天会问这个问题。 :-)

标签: c++ cmake


【解决方案1】:

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

是的。

由于bar(共享)与foo(静态)链接,barfoo 都必须使用与位置无关的代码进行编译。

CMake 知道bar 是一个共享库,而enables position independent code by default。但是由于foo是一个静态对象,即使它可以猜到它需要是PIC1,它默认不会为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_CODEcmake build system


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

【讨论】:

  • 请注意foo 不是静态库。它是 CMake 术语中的 OBJECT 库,实际上只是目标文件的集合。
  • @Angew 静态库只是由ar 归档的一堆对象(.o);)但是好的,我会解决的 ^^
  • 我知道它们在磁盘上几乎是等价的,但它们在 CMake-verse 中却截然不同,我觉得将它们混合起来可能会造成混淆。
  • “即使它可以猜测它需要是 PIC” - 据我了解,CMake 从不 尝试根据其库属性 猜测 用法。更有可能可能是 add_library(foo OBJECT SHARED ...) 通知 CMake,该库的对象将用于 SHARED 库,因此与 PIC 相关的选项应该相同。 (当编译它们的源代码时,PIC 似乎是 STATIC 和 SHARED 库之间的唯一区别)。
猜你喜欢
  • 1970-01-01
  • 2016-02-16
  • 1970-01-01
  • 2017-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-09
  • 2023-03-21
相关资源
最近更新 更多