【问题标题】:cmake and include directories across projects跨项目的 cmake 和包含目录
【发布时间】:2016-07-10 17:31:13
【问题描述】:

我正在尝试将一个由 cmake 管理的大型项目拆分为一组较小的项目。我无法让 cmake 接受包含目录的传播。我目前正在使用 ubuntu 14.04 (2.8) 附带的 cmake 版本。如果确实有必要,我可以切换到 3.x,但如果我能提供帮助,我宁愿不要。

考虑一个示例,其中我的源代码树的某个目录由一个可分离的、可隔离的库组成。它在我的源代码树中没有其他依赖项,并且到目前为止由

ADD_SUBDIRECTORY(smdir)

在 smdir 内:

ADD_LIBRARY(something STATIC something.c something.h)

something 用作依赖项的其他领域,以下工作完美:

ADD_LIBRARY(something_else STATIC ...)
TARGET_LINK_LIBRARIES(something_else something)

所有这些都发生在 cmake 宏/函数中,这些宏/函数会进行一些其他名称修改,所以如果此处列出的精确代码略有不正确,请原谅我。

我现在要做的是将something 完全从我的源代码树中拉出。我应该注意,这些是用于裸机微控制器的嵌入式库,而不是我在构建机器上安装的东西。

something 的基本编译脚本几乎可以按预期工作,只需进行少量更改。我将这个(现在是外部编译和管理的)库与代码库的其余部分集成的方法是从构建树中导出已编译的库,并将其导入到我的其他项目中。这种方法主要基于https://cmake.org/Wiki/CMake/Tutorials/Exporting_and_Importing_TargetsExporting from a Build Tree 部分。我尝试通过以下方式做到这一点:

TARGET_INCLUDE_DIRECTORIES(something PUBLIC /path/to/smdir/src)
EXPORT(TARGETS something FILE something-config.cmake)
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/something-config.cmake 
            DESTINATION ${PLATFORM_PACKAGES_PATH})

其中 ${PLATFORM_PACKAGES_PATH} 是某个系统文件夹,我打算在其中收集所有这些配置文件。生成的配置文件看起来很合理,并且安装到正确的位置就好了,并且有以下几行(以及许多其他行):

add_library(something STATIC IMPORTED)
set_target_properties(something PROPERTIES
  INTERFACE_INCLUDE_DIRECTORIES "/path/to/smdir/src"
)
set_property(TARGET something APPEND PROPERTY IMPORTED_CONFIGURATIONS RELWITHDEBINFO)
set_target_properties(something PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_RELWITHDEBINFO "C" IMPORTED_LOCATION_RELWITHDEBINFO "/correct/path/to/something.a")

导入这个库时出现问题,我使用的是:

ADD_LIBRARY(something STATIC IMPORTED)
SET_PROPERTY(TARGET something PROPERTY IMPORTED_LOCATION "${PLATFORM_PACKAGES_PATH}") 
GET_PROPERTY(public_include_dirs TARGET something PROPERTY INTERFACE_INCLUDE_DIRECTORIES)

任何将某些内容列为依赖项的库的构建都不包括 gcc 命令中某些内容的 INCLUDE_FOLDERS。我尝试在此处使用 GET_PROPERTY 读取的 public_include_dirs 变量为空白。

我们将不胜感激任何帮助或见解,包括有关“更清洁”或更好方法的建议。

【问题讨论】:

  • 您错误地解释了参考教程的Exporting from a Build Tree 部分:add_library(IMPORTED)SET_PROPERTY(TARGET .. IMPORTED_LOCATION)包含在您之前导出的.cmake 文件中。您需要包含此文件才能生效:include("${PLATFORM_PACKAGES_PATH}/something-config.cmake")。另请注意,导出的构建树通常是 not installed: The file created by this command is specific to the build tree and should never be installed.
  • @Tsyvarev 啊。这让事情变得更有意义了,尽管有以下两个警告: (a) 鉴于 *config.cmake 中的路径是硬编码和绝对的,在构建树之外安装它会有什么问题? (b) 如果不导入文件并按照问题中列出的方式使用它,如果实际上找不到 *config.cmake,cmake 仍然会死掉。我认为这意味着 cmake 在某些时候实际上正在使用该文件。
  • what would be the problem in installing it outside the build tree? - 导出会丢失原始构建树的许多属性。这就是为什么导出的树不适合安装的原因。 I took this to mean that cmake is actually using the file at some point. - include() 点 CMake 只解释包含文件中的所有命令。

标签: gcc cmake


【解决方案1】:

如果您完全提取了模块,那么从导入项目的角度来看,您实际上已经创建了一个第 3 方库。

因此,如果您已经在导出cmake 包/配置脚本,为什么不使用find_package() 正常导入它们。将-DCMAKE_PREFIX_PATH 传递给您最初使用-DCMAKE_INSTALL_PREFIX 安装提取库的位置。

总结一下:

  1. 在提取的库上调用 cmake 时传递 -DCMAKE_INSTALL_PREFIX=/path/to/target/prefixmake && make install它。
  2. 使用 find_package() 在您的导入项目中重构您的 cmake 逻辑。
  3. 使用库正常使用target_link_libraries() 来获取提取库的引用。
  4. 在您的导入项目上调用 cmake 时传递 -DCMAKE_PREFIX_PATH=/path/to/target/prefix。然后make它。

【讨论】:

  • 在构建机器上安装库没有内在的用处(为其他平台交叉编译)。使用构建树本身似乎很有吸引力——而且可能更容易。发布的代码是一个最小的示例。我实际上正在为多个平台重建库(并修改名称以反映目标平台)。到目前为止,我已将安装限制为仅将 config.cmake 复制到文件夹中。我想我可以创建一个人工 INSTALL_PREFIX 来创建一个 cmake 可以轻松识别的“安装”,这对我来说似乎不自然。不过,我会试一试。
  • 那为什么不在你的本地构建树中为它创建一个dist子目录并传递一个指向dist目录的CMAKE_INSTALL_PREFIX呢?
  • 我最终将我的 ${PLATFORM_PACKAGES_PATH} 更改为完整的安装前缀,而不是仅将其用作配置文件的容器。需要一些努力才能使它适合 find_packages,但它现在终于可以编译了 - 以沿链向上传递标头的一些问题为模。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-13
  • 2013-10-10
  • 1970-01-01
  • 2015-07-31
相关资源
最近更新 更多