我有一个包含和链接两个库的CMake项目,比如A
和B
(实际上它超过两个,其中一个是提升的东西,但这并不是真的这里的问题)。两者都通过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
检查了导致链接错误的符号的来源。
我该怎么办?是否有诀窍
nm --line-numbers
来自${A_INCLUDE_DIRS}
和A
的所有标头来自${B_INCLUDE_DIRS}
的所有标头?答案 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)
如果A
和B
是包含不同头文件和路径的不同库,那么执行您现在正在执行的操作应该没有问题。
话虽如此,如果A
和B
是在同一位置包含相同名称的头文件的类似库,那么这是有问题的。在这种情况下,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 /库设置的更多信息。