cmake - 使用具有多个实现的接口库时的链接器错误
问题描述
我正在将代码库移动到 cmake,具体取决于构建哪个可执行文件,需要特定库的不同实现。在某些情况下,这是因为生成的可执行文件具有不同的要求/功能,但在许多情况下,我们可以引入可以由未在生产中使用的单元测试控制的实现。
由于库需要依赖于接口而不是实现,因此在某些情况下,cmake 无法正确构建依赖关系树,从而导致链接步骤失败(此处描述的问题)。
例如,考虑以下人为的示例。存在 2 个库 a 和 b,其中 b 依赖于 a,a 有两个实现。我在以下位置定义了目标CMakeLists.txt
:
add_library(lib-a-intf INTERFACE)
target_include_directories(lib-a-intf INTERFACE lib-a)
add_library(lib-a-impl-a impl-a/impl-a.cpp)
target_link_libraries(lib-a-impl-a PUBLIC lib-a-intf)
add_library(lib-a-impl-b impl-b/impl-b.cpp)
target_link_libraries(lib-a-impl-b PUBLIC lib-a-intf)
add_library(lib-b lib-b.cpp)
target_link_libraries(lib-b PRIVATE lib-a-intf)
target_include_directories(lib-b PUBLIC lib-b)
然后可执行文件根据其要求提取所需的版本
add_executable(main main.cpp)
target_link_libraries(main lib-a-impl-b lib-b)
由于 cmake 无法正确设置链接顺序,因此无法将 do 链接到库 a 中定义的函数的未定义引用。
我知道一些解决方法,但它们不是最佳的。将库 a 实现定义为对象库可以工作,但不能很好地扩展,因为这些实现将为每个可执行文件重新编译。使用链接器--whole-archive
标志也有效,但也不能很好地扩展,因为它会导致大于必要的可执行文件,因为库 a 中未调用的符号不会被垃圾收集。
cmake 中有没有办法表明一个库实现了一个接口库,使得链接顺序是正确的?或者,有没有办法改变库的定义方式来解决这个问题?
解决方案
推荐阅读
- mysql - 从mysql表中选择列中的最大数时效率更高
- javascript - 如何从 API 获取 React JS 组件中多个项目的数据
- angularjs - 使用 $scope.$watch 处理 $interval.cancel 不起作用
- integration - 无法通过 PUT 功能更新(集成)
- wordpress - 每次用户购买 5 个相同类别时增加额外费用的插件
- parallel-processing - Pytorch softmax 沿着不同的掩码,没有 for 循环
- javascript - 如何从我的数据库中提取标题以创建悬停效果
- javascript - 带有 ES6 和 webpack 的 AngularJS 1.7 给出错误:未捕获的类型错误:无法读取未定义的属性“模块”
- java - JPA 搜索引发错误“已为此查找操作错误地提供了空 PK 的实例”
- database - 删除相关对象时如何维护外键?