不要扩展 CMake 列表变量
Do not expand CMake list variable
我有一个 CMake 脚本,它 运行 在 CMake 3.15 中通过 add_test()
、运行ning 在 Windows(Server 2008,不要问)下进行一些测试.当调用这些测试时,它们 运行 所在环境中的 PYTHONPATH 环境变量似乎被重置为环境默认值,并且不包含它需要的一些路径。
因此,当测试是 运行 CMake 运行s 时 $ENV{PYTHONPATH} 变量的值时,我需要设置 PYTHONPATH。这有许多以分号分隔的路径,因此 CMake 认为它是一个列表并试图将其扩展为多个 space 分隔的字符串,这显然结束得很糟糕。
我不知道如何阻止 CMake 这样做。从我所看到的一切来看,你应该可以用引号括起来:
add_test(
NAME mytest
COMMAND cmake -E env PYTHONPATH="$ENV{PYTHONPATH}"
run_test_here)
...但它总是进行扩展。我也尝试设置 set_tests_properties:
set_tests_properties(mytest PROPERTIES
ENVIRONMENT PYTHONPATH="$ENV{PYTHONPATH}")
...但这似乎根本没有做任何事情 - 测试时的 PYTHONPATH 没有改变。我认为这是因为它是一个环境变量,但是通过 set()
使用常规 CMake 变量没有任何区别,所以我做错了什么。请帮忙!
以下应该有效:
COMMAND cmake -E env "PYTHONPATH=$ENV{PYTHONPATH}"
您需要引用命令行的完整部分,以正确扩展消息。
测试:
set(tmp "C:\Python27\Scripts;E:\JenkinsMIDEBLD\workspace\...;...")
add_test(NAME MYtest1 COMMAND cmake -S . -E env "tmp=${tmp}")
add_test(NAME MYtest2 COMMAND cmake -S . -E env tmp="${tmp}")
在 运行 ctest
之后我得到:
1: Test command: /bin/cmake "-S" "." "-E" "env" "tmp=C:\Python27\Scripts;E:\JenkinsMIDEBLD\workspace\...;..."
2: Test command: /bin/cmake "-S" "." "-E" "env" "tmp="C:\Python27\Scripts" "E:\JenkinsMIDEBLD\workspace\..." "...""
第一个测试正确 ;
传递给 var
,而第二个测试通过 space 分隔列表。
这就是 cmake 解析的方式 quoted arguments。参数要么被完全引用,要么根本没有被引用 - 部分引号被解释为文字 "
。所以假设:
set(var a;b;c)
以下:
var="$var"
不是引号,"
是字面意思!它将$var
列表扩展为space分隔列表和"
保留,=
和a
之间有一个"
,并且有最后添加 "
。 var="$var"
等于:
var=\"a b c\"
^^ ^^ - the quotes stay!
^^^^^^^ ^ ^^^ - these are 3 arguments, the last one is `c"`
没有引号是:
var=$var
等于(注意遗漏的引号):
var=a c c
要引用参数,您必须将其全部引用,元素的第一个和最后一个字符为 "
:
"var=$var"
将扩展为:
"var=a;b;c"
您可以使用 ENVIRONMENT
测试 属性 完成这项工作,但有一个问题:
分号分隔不同的环境变量进行设置;您需要在环境变量中转义分号。例如代替
set_tests_properties(mytest PROPERTIES
ENVIRONMENT "PYTHONPATH=foo;bar")
你需要使用
set_tests_properties(mytest PROPERTIES
ENVIRONMENT "PYTHONPATH=foo\;bar")
环境变量可能包含分号这一事实使得一些转换成为必要:因为 ;
用于分隔列表元素,您可以简单地使用 list(JOIN)
将它们替换为 "\;"
。
以下示例适用于 PATH
,不适用于 PYTHONPATH
,因为我没有安装 python:
CMakeLists.txt
cmake_minimum_required(VERSION 3.12.4) # required for list(JOIN)
project(TestProject)
# get a version of the PATH environment var that can be used in the ENVIRONMENT test property
set(_PATH $ENV{PATH})
list(JOIN _PATH "\;" _PATH_CLEAN)
# just use a cmake script so we don't need to require any program able to retrieve environment vars
add_test(NAME Test1 COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_SOURCE_DIR}/test_script.cmake")
# we add another simpler var to test in the cmake script
set_tests_properties(Test1 PROPERTIES ENVIRONMENT "PATH=${_PATH_CLEAN};FOO=foo")
enable_testing()
test_script.cmake
message(STATUS "PATH=$ENV{PATH}")
if (NOT "$ENV{FOO}" STREQUAL "foo")
# the following command results in a non-0 exit code, if executed
message(FATAL_ERROR "FOO environment var should contain \"foo\" but contains \"$ENV{FOO}\"")
endif()
我有一个 CMake 脚本,它 运行 在 CMake 3.15 中通过 add_test()
、运行ning 在 Windows(Server 2008,不要问)下进行一些测试.当调用这些测试时,它们 运行 所在环境中的 PYTHONPATH 环境变量似乎被重置为环境默认值,并且不包含它需要的一些路径。
因此,当测试是 运行 CMake 运行s 时 $ENV{PYTHONPATH} 变量的值时,我需要设置 PYTHONPATH。这有许多以分号分隔的路径,因此 CMake 认为它是一个列表并试图将其扩展为多个 space 分隔的字符串,这显然结束得很糟糕。
我不知道如何阻止 CMake 这样做。从我所看到的一切来看,你应该可以用引号括起来:
add_test(
NAME mytest
COMMAND cmake -E env PYTHONPATH="$ENV{PYTHONPATH}"
run_test_here)
...但它总是进行扩展。我也尝试设置 set_tests_properties:
set_tests_properties(mytest PROPERTIES
ENVIRONMENT PYTHONPATH="$ENV{PYTHONPATH}")
...但这似乎根本没有做任何事情 - 测试时的 PYTHONPATH 没有改变。我认为这是因为它是一个环境变量,但是通过 set()
使用常规 CMake 变量没有任何区别,所以我做错了什么。请帮忙!
以下应该有效:
COMMAND cmake -E env "PYTHONPATH=$ENV{PYTHONPATH}"
您需要引用命令行的完整部分,以正确扩展消息。
测试:
set(tmp "C:\Python27\Scripts;E:\JenkinsMIDEBLD\workspace\...;...")
add_test(NAME MYtest1 COMMAND cmake -S . -E env "tmp=${tmp}")
add_test(NAME MYtest2 COMMAND cmake -S . -E env tmp="${tmp}")
在 运行 ctest
之后我得到:
1: Test command: /bin/cmake "-S" "." "-E" "env" "tmp=C:\Python27\Scripts;E:\JenkinsMIDEBLD\workspace\...;..."
2: Test command: /bin/cmake "-S" "." "-E" "env" "tmp="C:\Python27\Scripts" "E:\JenkinsMIDEBLD\workspace\..." "...""
第一个测试正确 ;
传递给 var
,而第二个测试通过 space 分隔列表。
这就是 cmake 解析的方式 quoted arguments。参数要么被完全引用,要么根本没有被引用 - 部分引号被解释为文字 "
。所以假设:
set(var a;b;c)
以下:
var="$var"
不是引号,"
是字面意思!它将$var
列表扩展为space分隔列表和"
保留,=
和a
之间有一个"
,并且有最后添加 "
。 var="$var"
等于:
var=\"a b c\"
^^ ^^ - the quotes stay!
^^^^^^^ ^ ^^^ - these are 3 arguments, the last one is `c"`
没有引号是:
var=$var
等于(注意遗漏的引号):
var=a c c
要引用参数,您必须将其全部引用,元素的第一个和最后一个字符为 "
:
"var=$var"
将扩展为:
"var=a;b;c"
您可以使用 ENVIRONMENT
测试 属性 完成这项工作,但有一个问题:
分号分隔不同的环境变量进行设置;您需要在环境变量中转义分号。例如代替
set_tests_properties(mytest PROPERTIES
ENVIRONMENT "PYTHONPATH=foo;bar")
你需要使用
set_tests_properties(mytest PROPERTIES
ENVIRONMENT "PYTHONPATH=foo\;bar")
环境变量可能包含分号这一事实使得一些转换成为必要:因为 ;
用于分隔列表元素,您可以简单地使用 list(JOIN)
将它们替换为 "\;"
。
以下示例适用于 PATH
,不适用于 PYTHONPATH
,因为我没有安装 python:
CMakeLists.txt
cmake_minimum_required(VERSION 3.12.4) # required for list(JOIN)
project(TestProject)
# get a version of the PATH environment var that can be used in the ENVIRONMENT test property
set(_PATH $ENV{PATH})
list(JOIN _PATH "\;" _PATH_CLEAN)
# just use a cmake script so we don't need to require any program able to retrieve environment vars
add_test(NAME Test1 COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_SOURCE_DIR}/test_script.cmake")
# we add another simpler var to test in the cmake script
set_tests_properties(Test1 PROPERTIES ENVIRONMENT "PATH=${_PATH_CLEAN};FOO=foo")
enable_testing()
test_script.cmake
message(STATUS "PATH=$ENV{PATH}")
if (NOT "$ENV{FOO}" STREQUAL "foo")
# the following command results in a non-0 exit code, if executed
message(FATAL_ERROR "FOO environment var should contain \"foo\" but contains \"$ENV{FOO}\"")
endif()