我正在尝试创建一个与某些环境变量一起运行的自定义命令,例如LDFLAGS,如果它包含空格,则需要引用它的值:
LDFLAGS="-Lmydir -Lmyotherdir"
由于CMake的转义规则,我无法找到将此参数包含在CMake自定义命令中的方法。这是我到目前为止所尝试的内容:
COMMAND LDFLAGS="-Ldir -Ldir2" echo blah VERBATIM)
收益"LDFLAGS=\"-Ldir -Ldir2\"" echo blah
COMMAND LDFLAGS=\"-Ldir -Ldir2\" echo blah VERBATIM)
收益LDFLAGS=\"-Ldir -Ldir2\" echo blah
似乎我要么引用整个字符串,要么在用作命令的一部分时,转义的引号不会解析。
我希望既可以包含文字双引号,也可以作为为命令设置环境变量的更好方法。请注意,我仍然使用CMake 2.8,因此我没有在3.2中使用新的“env”命令。
请注意,这不是 When to quote variables? 的副本,因为这些引用方法都不适用于此特定情况。
答案 0 :(得分:5)
显而易见的选择 - 通常在使用COMMAND
的边界时建议使用外部脚本,而不是使用旧版本的CMake。
我只是想添加一些简单的COMMAND
变种,它们确实有用并且不需要shell,但是 - 我必须承认 - 仍然部分依赖于平台。
一个例子是只将引用的部分放入变量中:
set(vars_as_string "-Ldir -Ldir2")
add_custom_target(
QuotedEnvVar
COMMAND env LD_FLAGS=${vars_as_string} | grep LD_FLAGS
)
实际上它逃脱了空间而不是引号。
另一个例子是使用转义引号添加它作为"启动器"规则:
add_custom_target(
LauncherEnvVar
COMMAND env | grep LD_FLAGS
)
set_target_properties(
LauncherEnvVar
PROPERTIES RULE_LAUNCH_CUSTOM "env LD_FLAGS=\"-Ldir -Ldir2\""
)
编辑:添加多个引用参数的示例,而无需转义引号
另一个例子是"隐藏一些复杂性"在函数中 - 如果要将其添加到所有自定义命令调用中 - 请使用global / directory RULE_LAUNCH_CUSTOM
属性:
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 ...
除外)被命名为Bracket Argument并且允许任何字符而不需要添加反斜杠:
set_property(
GLOBAL PROPERTY
RULE_LAUNCH_CUSTOM [=[env LDFLAGS="-Ldir1 -Ldir2" CFLAGS="-Idira -Idirb"]=]
)
add_custom_target(
MultipleEnvVarNew
COMMAND env | grep -E 'LDFLAGS|CFLAGS'
)
<强>参考强>
答案 1 :(得分:1)
好的,我删除了原来的答案,因为@Florian提出的答案更好。多个引用的args需要另外一个调整。考虑一下环境变量列表:
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}")
这当然取决于你的shell。
第二个想法,我的原始答案如下,因为我还有一个案例,我无法访问目标名称。
set(my_env LDFLAGS=\"-Ldir -Ldir2" CFLAGS=\"-Idira -Idirb\")
add_custom_command(COMMAND sh -c "${my_env} grep LDFLAGS" VERBATIM)
此技术仍然需要替换list-&gt;字符串转换中的分号。
答案 2 :(得分:1)
您需要三个反斜杠。我最近需要这个来从PkgConfig获取预处理器定义,并将其应用于我的C ++标志:
pkg_get_variable(SHADERDIR movit shaderdir)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSHADERDIR=\\\"${SHADERDIR}\\\"")
答案 3 :(得分:0)
有些folks建议使用$ {CMAKE_COMMAND}并将可执行文件作为参数传递,例如:
COMMAND ${CMAKE_COMMAND} -E env "$(WindowsSdkDir)/bin/x64/makecert.exe" ...
对我有用。
答案 4 :(得分:0)
弗洛里安的回答在几个方面是错误的:
VERBATIM
。它修复了特定于平台的引用错误。RULE_LAUNCH_CUSTOM
。它不适用于此目的,仅适用于某些生成器。env
作为命令。它在 Windows 上不可用。事实证明 OPs 代码不起作用的真正原因是 CMake 总是完全引用 COMMAND
之后的第一个单词,因为它应该是可执行文件的名称。你根本不应该把环境变量放在第一位。
例如:
add_custom_command(
OUTPUT q1.txt
COMMAND ENV_VAR="a b" echo "hello" > q1.txt
VERBATIM
)
add_custom_target(q1 ALL DEPENDS q1.txt)
$ VERBOSE=1 make
...
"ENV_VAR=\"a b\"" echo hello > q1.txt
/bin/sh: ENV_VAR="a b": command not found
那么如何传递带空格的环境变量呢?简单。
add_custom_command(
OUTPUT q1.txt
COMMAND ${CMAKE_COMMAND} -E env ENV_VAR="a b" echo "hello" > q1.txt
VERBATIM
)