【问题标题】:Include header of CMake targets in a object library在对象库中包含 CMake 目标的标头
【发布时间】:2019-12-06 15:03:43
【问题描述】:

场景:

我正在将应用程序构建系统移植到 CMake。依赖项已经安装在系统上或将通过 conan 处理。

假设项目的结构如下:

- include/
  - BigFoo/
    - *.hpp
- src/
  - BigFoo/
    - *.cpp
  - main.cpp
  - *.qml
- test/
  - BigFoo/
    - *Test.cpp

我的目标是在主应用程序和单元测试中重用 BigFoo 的编译输出 (*.o)。我不想要 BigFoo 的内部库(*.a 或 *.so)。

BigFoo 正在使用来自目标系统的 Qt5 和 Boost 组件。它还使用作为柯南包提供的组件。

目前的做法:

  • 将 BigFoo 构建为静态库 => 通过 target_link_library() 处理依赖项
  • 构建 main.cpp 和 *.qml => 与 BigFoo 的链接
  • 构建 BigFoo/*Test.cpp => 与 BigFoo 的链接

所需的方法:

  • 将 BigFoo 构建为对象库 => 包含依赖项头
  • 使用 BigFoo_Object 构建 main.cpp、*.qml => 链接依赖项
  • 使用 BigFoo_Object 构建 BigFoo/*Test.cpp => 链接依赖项

所需方法的问题:

在构建 OBJECT 库时,我无法通过 target_include_directories() 包含多个组件的依赖项(Boost::XYZ Qt5::XYZ CONAN_PKG::XYZ 等)。

add_library(Core OBJECT)

# I want to do something like this:
target_include_directories(Core PUBLIC 
    Qt5::Core
    Qt5::Qml
    Qt5::Quick
    Qt5::Scxml
    CONAN_PKG::XYZ
    CONAN_PKG::XYZ
)

结果是 CMake(当然)添加了头文件包含路径,如下所示...

-I../../../Application/Qt5::Qml

后来又失败了,因为它不能拆解 Qt 的包含语句。

在构建静态库时,标头包含由 target_link_libraries() 处理,我现在有点困惑如何在不链接任何内容的 OBJECT 库上执行此操作。

我的问题:

  1. 如何在 OBJECT 库目标中包含 find_package() 和 CONAN_PKG 提供的 CMake 目标的标头?
  2. 是否有更好/更好的方法来重用 BigFoo,这样我就不会重复编译?

PS:我使用的是 cmake 3.13

【问题讨论】:

  • 您想要的方法似乎合理,但您需要更具体地使用“我无法包含”。为什么?有没有错误?在编译或 CMake 配置期间?此外,您使用哪个 CMake 版本,OBJECT 库在较新的版本中有更好的支持。
  • 您是否在 CMakeLists.txt 中包含了 conan_basic_setup(TARGETS)? CONAN_PKG 仅在您选择 TARGETS 时才会导出
  • 感谢您的提示,我已经更新了问题。
  • 是的,我在 conan_basic_setup 上使用了 TARGETS 标志。我还检查了生成的柯南 *.cmake 文件。所有需要的依赖项都导出为 INTERFACE + IMPORTED lib。

标签: c++ cmake conan


【解决方案1】:

我知道这似乎是无稽之谈,因为对象库根本没有链接。但这只是 CMake 对象库的尴尬之一。这可能是您需要的:

add_library(Core OBJECT)

target_link_libraries(Core PUBLIC 
    Qt5::Core
    Qt5::Qml
    Qt5::Quick
    Qt5::Scxml
    CONAN_PKG::XYZ
    CONAN_PKG::XYZ
)

Object libraries may be used as the target (first) argument of target_link_libraries to specify dependencies of their sources on other libraries.

【讨论】:

  • 谢谢!我从没想过这个功能是对象库上下文中名为“链接”的函数的一部分。对于其他人:这会将传递的目标中的所有包含目录添加到带有“-isystem”的编译命令
  • 不客气。并且 target_link_libraries() 总是添加导入目标的包含目录,而不仅仅是对象库。当您的依赖项是导入目标时,您也可以避免使用可执行文件和共享库的 target_include_directories()。
  • 如何在 CMake 3.10(Ubuntu 18.04 附带的 CMake 3.10 上执行此操作,其中 target_link_libraries 尚不允许应用于对象库?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-15
  • 1970-01-01
  • 1970-01-01
  • 2012-07-18
相关资源
最近更新 更多