如何在自定义CMake命令中包含文字双引号?
我正在尝试创建一个自定义命令,该命令使用一些环境变量运行,例如LDFLAGS,如果它包含空格,则需要引用其值:如何在自定义CMake命令中包含文字双引号?,cmake,escaping,quotes,literals,Cmake,Escaping,Quotes,Literals,我正在尝试创建一个自定义命令,该命令使用一些环境变量运行,例如LDFLAGS,如果它包含空格,则需要引用其值: LDFLAGS="-Lmydir -Lmyotherdir" 由于CMake的转义规则,我找不到在CMake自定义命令中包含此参数的方法。以下是我迄今为止所尝试的: COMMAND LDFLAGS="-Ldir -Ldir2" echo blah VERBATIM) 产生“LDFLAGS=\”-Ldir-Ldir2\”回音废话 COMMAND LDFLAGS=\"-Ldir -Ld
LDFLAGS="-Lmydir -Lmyotherdir"
由于CMake的转义规则,我找不到在CMake自定义命令中包含此参数的方法。以下是我迄今为止所尝试的:
COMMAND LDFLAGS="-Ldir -Ldir2" echo blah VERBATIM)
产生“LDFLAGS=\”-Ldir-Ldir2\”回音废话
COMMAND LDFLAGS=\"-Ldir -Ldir2\" echo blah VERBATIM)
产生LDFLAGS=\“-Ldir-Ldir2\”回音废话
COMMAND LDFLAGS=\"-Ldir -Ldir2\" echo blah VERBATIM)
看起来要么整个字符串都被引用,要么转义的引号在用作命令的一部分时无法解析
我希望能够包含文本双引号,或者能够更好地为命令设置环境变量。请注意,我仍然使用cmake2.8,因此在3.2中没有新的“env”命令
请注意,这不是重复的,因为这些引用方法都不适用于这种特殊情况。好的,我删除了我的原始答案,因为@Florian提出的答案更好。有一个额外的调整需要多个引用参数。考虑这样的环境变量列表:
set(my_env_vars LDFLAGS="-Ldir1 -Ldir2" CFLAGS="-Idira -Idirb")
为了生成所需的扩展,请转换为字符串,然后替换代码>带有空格
set(my_env_string "${my_env_vars}") #produces LDFLAGS="...";CFLAGS="..."
string(REPLACE ";" " " my_env_string "${my_env_string}")
然后,您可以继续@Florian的精彩回答,并添加自定义启动规则。如果字符串中需要分号,则首先需要将其转换为其他名称
请注意,在本例中,我不需要使用env
启动:
set_target_properties(mytarget PROPERTIES RULE_LAUNCH_CUSTOM "${my_env_string}")
这当然取决于你的外壳
再想一想,我的原始答案如下,因为我还有一个案例,我无法访问目标名称
set(my_env LDFLAGS=\"-Ldir -Ldir2" CFLAGS=\"-Idira -Idirb\")
add_custom_command(COMMAND sh -c "${my_env} grep LDFLAGS" VERBATIM)
这种技术仍然需要替换列表->字符串转换中的分号。当触及命令
的边界时,通常建议使用外部脚本,尤其是使用较旧版本的CMake
我只想添加一些简单的命令
变体,这些变体可以正常工作,不需要外壳,但我必须承认,它们仍然部分依赖于平台
- 一个例子是只将引用的部分放入变量中:
set(vars_as_string "-Ldir -Ldir2")
add_custom_target(
QuotedEnvVar
COMMAND env LD_FLAGS=${vars_as_string} | grep LD_FLAGS
)
这实际上是在逃避空间,而不是引用
- 另一个例子是将它与转义引号一起添加为“启动器”规则:
编辑:添加了多个引用参数的示例,无需转义引号
- 另一个示例是在函数中“隐藏一些复杂性”,如果要将其添加到所有自定义命令调用中,请使用global/directory属性:
function(set_env)
get_property(_env GLOBAL PROPERTY RULE_LAUNCH_CUSTOM)
if (NOT _env)
set_property(GLOBAL PROPERTY RULE_LAUNCH_CUSTOM "env")
endif()
foreach(_arg IN LISTS ARGN)
set_property(GLOBAL APPEND_STRING PROPERTY RULE_LAUNCH_CUSTOM " ${_arg}")
endforeach()
endfunction(set_env)
set_env(LDFLAGS="-Ldir1 -Ldir2" CFLAGS="-Idira -Idirb")
add_custom_target(
MultipleEnvVar
COMMAND env | grep -E 'LDFLAGS|CFLAGS'
)
备选方案(对于CMake>=3.0)
- 我认为我们在这里实际寻找的(除了
cmake-E env…
)是命名的,并且允许任何字符,而无需添加反斜杠:
set_property(
GLOBAL PROPERTY
RULE_LAUNCH_CUSTOM [=[env LDFLAGS="-Ldir1 -Ldir2" CFLAGS="-Idira -Idirb"]=]
)
add_custom_target(
MultipleEnvVarNew
COMMAND env | grep -E 'LDFLAGS|CFLAGS'
)
参考资料
您需要三个反斜杠。我最近需要这个从PKGCONFIG中定义预处理器,并将其应用到我的C++标志:
pkg_get_variable(SHADERDIR movit shaderdir)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSHADERDIR=\\\"${SHADERDIR}\\\"")
有些人建议使用${CMAKE_COMMAND}并将可执行文件作为参数传递,例如:
COMMAND ${CMAKE_COMMAND} -E env "$(WindowsSdkDir)/bin/x64/makecert.exe" ...
这对我很有用。弗洛里安的回答在几个方面是错误的:
- 将引用的部分放入变量中没有区别
- 你绝对应该一字不差地使用
。它修复了特定于平台的引用错误
- 您绝对不应该为此使用
规则\u启动\u自定义。它不适用于此,只适用于某些生成器
- 您不应该使用
env
作为命令。它在Windows上不可用
事实证明,OPs代码不起作用的真正原因是CMake总是完全引用命令
后的第一个单词,因为它应该是可执行文件的名称。你不应该把环境变量放在第一位
例如:
add_custom_command(
OUTPUT q1.txt
COMMAND ENV_VAR="a b" echo "hello" > q1.txt
VERBATIM
)
add_custom_target(q1 ALL DEPENDS q1.txt)
那么,如何用空格传递环境变量呢?简单
add_custom_command(
OUTPUT q1.txt
COMMAND ${CMAKE_COMMAND} -E env ENV_VAR="a b" echo "hello" > q1.txt
VERBATIM
)
您是否尝试过在变量中使用带有转义引号的字符串并将该变量传递给自定义_命令?@usr1234567 Yep。我已经做了各种各样的字符串、列表、带引号的字符串等。所有的结果要么是整个字符串被引用,要么是反斜杠一直延伸到shell。相关:。谢谢@Florian,我一直在寻找类似于规则\u启动\u自定义
的功能,但不知道该去哪里寻找。我已经编辑了我的答案,如果您有多个这样的ARG=“value”
样式参数,则需要添加一个额外的调整。如果我想在你的答案中添加这些调整,我很乐意完全删除我的答案。@DevinLane不客气。我已经添加了一些其他示例,但请保留您的示例。与使用脚本语言时一样,这里的可能性是无穷的。我过去也使用过“将列表转换为空格分隔字符串”部分,它完全有效。我只是想避免它,因为自私的原因,它需要向第一次看到它的人解释它。@usr1234567如果我理解正确,你的意思是做set(flags LDFLAGS=\“-Ldir1-Ldir2\”
然后添加自定义命令(command${flags}grep LDFLAGS逐字)
。对我来说,这会产生LDFLAGS=\“-Ldir;-Ldir2\”grep LDFLAGS
,即转义符会在命令中出现。如果您引用它,那么您将得到“LDFLAGS=\”-Ldir-Ldir2 \“grep LDFLAGS
Up投票,因为它可以工作,并且是目前为止最直接的方法。不过,你有推荐信吗?@spawn:没有,我只是把它弄乱了,直到它达到我的目的。
add_custom_command(
OUTPUT q1.txt
COMMAND ${CMAKE_COMMAND} -E env ENV_VAR="a b" echo "hello" > q1.txt
VERBATIM
)