CMake:包含目录的排序(如何混合基于系统和用户的包含路径?)

jan*_*048 8 c++ linker cmake

我有一个CMake项目,包括和链接两个库,说AB(实际上它超过两个,其中一个是增强的东西,但这在这里并不重要).两者都通过FindSomething.cmake脚本(正确)填充标准CMake变量来定位,包括通过添加目录

INCLUDE_DIRECTORIES(${A_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${B_INCLUDE_DIRS})
Run Code Online (Sandbox Code Playgroud)

后来通过连接完成

TARGET_LINK_LIBRARIES(mytarget ${A_LIBRARIES} ${B_LIBRARIES})
Run Code Online (Sandbox Code Playgroud)

现在,问题是这两个库可以驻留在基于用户的位置或系统目录中(顺便说一句,我是在linux上,CMake 2.8.2) - 或两者兼而有之.假设A只是in $HOME/usr/include$HOME/usr/libwhile B(在我的情况下是boost)驻留在系统路径(/usr/include/usr/lib)和基于用户的路径中 - 在不同的版本中.可以使用查找脚本查找系统或基于用户的库B,这是有效的.

当我想B从系统路径链接时,麻烦就开始了.${B_INCLUDE_DIRS}${B_LIBRARIES}正确指向标头和库的系统范围位置.但仍有${A_INCLUDE_DIRS}一点指向非系统包含目录,最终还会B从此位置获取库的标题,而链接则B使用系统路径(via ${B_LIBRARIES})中的版本,这会导致冲突,即链接错误.

改变INCLUDE_DIRECTORIES语句的顺序似乎没有任何改变.我通过nm --line-numbers目标文件检查了导致链接错误的符号的来源.

我能做什么?有诀窍吗?

  • 强制包含目录的顺序(即使这也意味着优先考虑系统路径,尽管还指定了基于用户的位置)?
  • 告诉CMake使用${A_INCLUDE_DIRS}来自A${B_INCLUDE_DIRS}来自所有标头的所有标头B

fmo*_*ncy 5

如果AB是包含不同头文件和路径的不同库,那么做你现在正在做的事情应该没有问题。

话虽如此,如果AB是在同一位置包含相同名称的头文件的类似库,那就有问题了。在这种情况下,include_directory()调用的顺序很重要。我运行了一个小测试,我有一个头文件的三个副本。第一个副本位于我的系统路径中(比如/usr/include)。其他副本位于两个用户定义的位置(例如/tmp/include1/tmp/include2)。/tmp/include1如果我include_directory()按以下顺序调用,则首先找到并使用该文件:

include_directory("/tmp/include1")
include_directory("/tmp/include2")
Run Code Online (Sandbox Code Playgroud)

/tmp/include2如果我include_directory()按以下顺序调用,则首先找到并使用该文件:

include_directory("/tmp/include2")
include_directory("/tmp/include1")
Run Code Online (Sandbox Code Playgroud)

如果我没有放置任何include_directory()语句,则系统路径中的标题将被找到并使用。

您可能需要重新检查您FindSomething.cmake的写作方式。find_*()CMake 命令的搜索顺序可以在CMake 文档中找到,

据我所知,如果在两个位置都可以找到头文件,现在可以告诉 CMake${A_INCLUDE_DIRS}用于所有头文件A${B_INCLUDE_DIRS}所有B头文件。这完全取决于include_directory()调用的顺序。如果FindSomething.cmake写得正确,如果CMAKE_MODULE_PATH(这是 CMake 将查找Find*.cmake文件的位置)设置正确并且所有路径都正确,那么您应该很高兴。如果没有,我将需要有关您当前 CMake/库设置的更多信息。


Jay*_*Jay 5

这是 CMake 所说的include_directories()

include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])

您可以指定要在系统包含目录之前或之后搜索包含目录,然后再将这些目录告知系统。

您也可能特定于某个目标:

target_include_directories(target [SYSTEM] [BEFORE] [items1...] [[items2...] ...])