我有一个CMake项目,包括和链接两个库,说A和B(实际上它超过两个,其中一个是增强的东西,但这在这里并不重要).两者都通过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目标文件检查了导致链接错误的符号的来源.
我能做什么?有诀窍吗?
${A_INCLUDE_DIRS}来自A和${B_INCLUDE_DIRS}来自所有标头的所有标头B?如果A和B是包含不同头文件和路径的不同库,那么做你现在正在做的事情应该没有问题。
话虽如此,如果A和B是在同一位置包含相同名称的头文件的类似库,那就有问题了。在这种情况下,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/库设置的更多信息。
这是 CMake 所说的include_directories():
include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])
您可以指定要在系统包含目录之前或之后搜索包含目录,然后再将这些目录告知系统。
您也可能特定于某个目标:
target_include_directories(target [SYSTEM] [BEFORE] [items1...] [[items2...] ...])