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

时间:2011-10-13 10:16:13

标签: c++ linker cmake

我有一个包含和链接两个库的CMake项目,比如AB(实际上它超过两个,其中一个是提升的东西,但这并不是真的这里的问题)。两者都通过FindSomething.cmake脚本定位,这些脚本(正确地)填充标准CMake变量,包括通过

添加目录
INCLUDE_DIRECTORIES(${A_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${B_INCLUDE_DIRS})

后来通过

完成链接
TARGET_LINK_LIBRARIES(mytarget ${A_LIBRARIES} ${B_LIBRARIES})

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

如果我想从系统路径链接B,则会出现问题。B${B_INCLUDE_DIRS}正确指向标头和库的系统范围位置。但仍有${B_LIBRARIES}指向非系统包含目录,最终还会从此位置获取库${A_INCLUDE_DIRS}的标头,而B的链接使用来自该位置的版本系统路径(通过B)导致冲突,即链接错误。

更改${B_LIBRARIES}语句的顺序似乎没有任何改变。我通过目标文件上的INCLUDE_DIRECTORIES检查了导致链接错误的符号的来源。

我该怎么办?是否有诀窍

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

3 个答案:

答案 0 :(得分:3)

使用第三方库时,我会一直这样做

图书馆A + B头文件:

third_party / include / libA_name /< - 将头文件放在那里

third_party / include / libB_name /< - 将头文件放在那里

在源文件中,您总是会像这样使用它

#include "libA_name/file.h" <-- no ambiguity possible

#include "libB_name/file.h" <-- no ambiguity possible

然后你仍然可以使用-I“third_party / include”作为include文件夹,在源文件中不会出现排序歧义。

这也消除了系统头文件中的自定义头文件的歧义,这些文件可能会不时地与第三方库发生冲突。

答案 1 :(得分:3)

以下是CMake对include_directories()所说的内容:

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

您可以指定您希望在系统包含目录之前或之后搜索包含目录,并告诉它有关这些目录的信息。

您也可能特定于目标:

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

答案 2 :(得分:2)

如果AB是包含不同头文件和路径的不同库,那么执行您现在正在执行的操作应该没有问题。

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

include_directory("/tmp/include1")
include_directory("/tmp/include2")

如果我按以下顺序拨打/tmp/include2电话,则会找到并使用include_directory()中的文件:

include_directory("/tmp/include2")
include_directory("/tmp/include1")

如果我没有输入include_directory()语句,则会找到并使用系统路径中的标题。

您可能需要重新检查FindSomething.cmake的撰写方式。可以在CMake documentation

中找到find_*() CMake命令的搜索顺序

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