如何强制CMake';s target_include_directories()使用绝对路径
如何强制CMake的函数如何强制CMake';s target_include_directories()使用绝对路径,cmake,Cmake,如何强制CMake的函数target\u include\u directories()将值视为绝对路径 例如,我想要这行代码: target_include_directories(foobar PRIVATE "%FOOBAR_INCLUDE%") 只需将%FOOBAR\u INCLUDE%添加到包含目录列表 然而,我们实际得到的是c:\path\to\foobar\%foobar\u INCLUDE% 我知道我能做到 target_include_directo
target\u include\u directories()
将值视为绝对路径
例如,我想要这行代码:
target_include_directories(foobar PRIVATE "%FOOBAR_INCLUDE%")
只需将%FOOBAR\u INCLUDE%
添加到包含目录列表
然而,我们实际得到的是c:\path\to\foobar\%foobar\u INCLUDE%
我知道我能做到
target_include_directories(foobar PRIVATE "$ENV{FOOBAR_INCLUDE}")
但那不是我想要的。这将扩展环境变量的值并插入FOOBAR\u INCLUDE
值的当前设置
我们需要它简单地推送环境变量,然后在开发过程中,开发人员将手动更改
FOOBAR\u INCLUDE
的值,而无需每次重新运行CMake。不可能添加看起来像相对目录的内容(即%FOOBAR\u INCLUDE%”
)以这种方式包含目录。CMake将始终尝试将这些操作转换为绝对路径。文件中或多或少说明了这一点:
相对路径被解释为相对于当前源目录
但也适用于target\u include\u directories()
命令
即使您试图绕过此问题,并手动设置目标的INCLUDE\u DIRECTORIES
属性:
set_target_properties(foobar PROPERTIES
INCLUDE_DIRECTORIES "%FOOBAR_INCLUDE%"
)
target_compile_definitions(foobar PRIVATE -I%FOOBAR_INCLUDE%)
CMake将在生成阶段抛出错误:
CMake Error in CMakeLists.txt:
Found relative path while evaluating include directories of "foobar":
"%FOOBAR_INCLUDE%"
您可以妥协,提供一个完整路径,但允许%FOOBAR\u INCLUDE%
变量保留:
target_include_directories(foobar PRIVATE "C:/%FOOBAR_INCLUDE%")
但这将您和您的开发伙伴与C:drive联系在一起
我建议采用您建议的方法,使用环境变量:
target_include_directories(foobar PRIVATE "$ENV{FOOBAR_INCLUDE}")
或者创建一个
FOOBAR\u INCLUDE
CMake缓存变量,每个开发人员可以在重新运行CMake之前填充该变量。如果每个开发人员的环境不同,则应重新配置CMake以匹配该环境。您可以通过生成器表达式诱使CMake接受文字值
target_include_directories(foobar PRIVATE $<1:%FOOBAR_INCLUDE%>)
所以只需传递到它的绝对路径
无需重新运行CMake
CMake的关键在于,如果更改配置,您需要重新运行它。因此-您更改了FOOBAR\u INCLUDE-您应该重新运行cmake。谢谢。它回答了我的问题,尽管我不喜欢“你不能”的答案。有一些公司发展的内部原因,我无法解释为什么它实际上需要成为一个未扩展的环境变量。我必须让当权者知道这一限制。谢谢,很好的把戏,Micha。遗憾的是,使用-I的想法是不可移植的。这只适用于GCC编译器和类似的编译器。它不适用于基于Windows的编译。这就是为什么target\u include\u directories()
如此强大,令人沮丧的是它只接受绝对路径。(TL;DR-I
对MSVC有效)的确,编译器标志不是“可移植的”,它们不是天生的。MSVC确实模拟了最基本的标志1:1,唯一的区别是它们被改为“-”表示“/”可选,b“-”和“/”正在使用。或者,if(MSVC)target\u compile\u定义(foobar PRIVATE/I%foobar\u INCLUDE%)else()。。endif()
如果你想保持纯洁,就可以这样做。CMake通过涵盖每个主要的编译器/平台/IDE组合,给人一种可移植性的错觉。在CMakeLists中有特定于编译器/平台/IDE的指令是很自然的,尤其是在做非常定制的事情时。