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
is) 构建的。这可以通过添加来解决:
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 )。
然后用于构建共享库的每个目录的对象库似乎是解决此问题的好方法。
解决方案
这是解决此问题的正确方法吗?
是的。
由于bar
(shared) 与foo
(static) 链接,两者都bar
必须foo
使用与位置无关的代码进行编译。
CMake 知道bar
是一个共享库,并且默认启用与位置无关的代码。但是由于foo
它是一个静态对象,即使它可以猜测它需要是 PIC 1,它默认不会为 PIC 启用 PIC foo
。
根据 SO 的问题What is the idiomatic way in CMAKE 添加 -fPIC 编译器选项?
您可以在所有目标上设置与位置无关的代码属性:
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
或在特定库中:
add_library(lib1 SHARED lib1.cpp) set_property(TARGET lib1 PROPERTY POSITION_INDEPENDENT_CODE ON)
1)这可能是一个建议的功能,也许它已经是。
推荐阅读
- entity-framework - 用于一对多关系的 EF Core 联接表
- npm - 'tns' 不是内部或外部命令、可运行程序或批处理文件
- javascript - 如何从具有相关字段的 Firestore 加载多个集合?
- python - Django:OperationalError:没有这样的列:User_profile.user_id
- c - “I/O 块状态”和“睡眠”有区别吗?
- javascript - 框架如何知道调用了哪个 api?
- wordpress - 在自己的 PHP 文件中使用 Elementor 图标
- android - 使用警报对话框android的颜色ListView项目
- r - 发布到闪亮服务器后无法将记录保存到数据库中
- swift - 如何从firebase读取数据并将其附加到数组