我目前正在将当前的构建环境从MSBuild迁移到CMake。在这种情况下,我需要更新PATH变量,以便单元测试可以执行。这对于gtest_add_tests来说不是问题,因为它使用源代码来识别测试。但是,使用gtest_discover_tests标志执行单元测试的--gtest_list_tests无法识别任何测试,因为在构建过程中遇到了STATUS_DLL_NOT_FOUND错误。
例如:
add_executable(gTestExe ...)
target_include_directories(gTestExe ...)
target_compile_definitions(gTestExe ...)
target_link_libraries(gTestExe ...)
set (NEWPATH "/path/to/bin;$ENV{PATH}")
STRING(REPLACE ";" "\\;" NEWPATH "${NEWPATH}")这样做是可行的:
gtest_add_tests(TARGET gTestExe TEST_LIST allTests)
set_tests_properties(${all_tests} PROPERTIES ENVIRONMENT "PATH=${NEWPATH}")但这并不意味着:
#set_target_properties(gTestExe PROPERTIES ENVIRONMENT "PATH=${NEWPATH}")
#set_property(DIRECTORY PROPERTY ENVIRONMENT "PATH=${NEWPATH}")
gtest_discover_tests(gTestExe PROPERTIES ENVIRONMENT "PATH=${NEWPATH}")编辑:当使用gtest_add_tests添加测试时,测试本身也能工作。问题是在gtest_discover_tests注册的post构建步骤中,调用发现测试失败,因为所需的库不在PATH中。
发布于 2020-05-14 13:00:38
今天早上我遇到了同样的问题,我发现了一个(肮脏的?)解决办法。它不能工作的原因有点复杂,但解决办法很简单。
为什么它不能工作
gtest_discover_tests(gTestExe PROPERTIES ENVIRONMENT "PATH=${NEWPATH}")因为路径内容由分号分隔,因此CMake将其视为列表值。
如果您查看GoogleTestAddTests.cmake文件(位于C:\Program Files\CMake\share\cmake-3.17\Modules中),它将使用前程处理PROPERTIES参数。
在这个脚本中,PROPERTIES值对于CMake来说是这样的:ENVIRONMENT;PATH=mypath;mypath2,它将把mypath2当作第三个参数,而不是PATH环境变量的值。
然后,CMake将生成以下行:
set_tests_properties( mytest PROPERTIES ENVIRONMENT PATH=mypath mypath2)转义;不起作用,因为列表是在add_custom_command()中自动使用的(cmake3.17.1中的1.420),忽略了任何形式的转义。
要防止cmake将路径中的每个值作为列表处理,可以使用括号参数如下:
gtest_discover_tests(gTestExe PROPERTIES ENVIRONMENT "[==[PATH=${NEWPATH}]==]")然后,cmake将把您的论点作为一个整体来处理。不幸的是,CMake还将在生成的代码中放置一个括号,因为它包含[、=和可能的空格:
# This line
if(_arg MATCHES "[^-./:a-zA-Z0-9_]")
set(_args "${_args} [==[${_arg}]==]")
else()
set(_args "${_args} ${_arg}")
endif() 结果生成以下脚本:
set_tests_properties( mytest PROPERTIES ENVIRONMENT [==[ [==[PATH=mypath;mypath2] ]==])在执行测试时,cmake将尝试读取值,只删除第一个括号参数,因为它们不嵌套。
可能的解决办法
因此,要做到这一点,我们需要CMake不对我们自己的括号参数使用括号参数。
首先,在您自己的存储库中创建一个GoogleTestAddTests.cmake文件的本地副本(位于C:\Program Files\CMake\share\cmake-3.17\Modules中)。
在GoogleTestAddTests.cmake (1.12)的本地副本开始时,将函数add_command替换为下面一个:
function(add_command NAME)
set(_args "")
foreach(_arg ${ARGN})
# Patch : allow us to pass a bracket arguments and escape the containing list.
if (_arg MATCHES "^\\[==\\[.*\\]==\\]$")
string(REPLACE ";" "\;" _arg "${_arg}")
set(_args "${_args} ${_arg}")
# end of patch
elseif(_arg MATCHES "[^-./:a-zA-Z0-9_]")
set(_args "${_args} [==[${_arg}]==]")
else()
set(_args "${_args} ${_arg}")
endif()
endforeach()
set(script "${script}${NAME}(${_args})\n" PARENT_SCOPE)
endfunction()这将使cmake不使用括号列表中的括号列表,并自动转义;,因为set_tests_properties也将;视为列表。
最后,我们需要CMake来使用我们的自定义GoogleTestAddTests.cmake而不是CMake中的那个。
调用include(GoogleTest)之后,将变量_GOOGLETEST_DISCOVER_TESTS_SCRIPT设置为本地GoogleTestAddTests.cmake的路径:
# Need google test
include(GoogleTest)
# Use our own version of GoogleTestAddTests.cmake
set(_GOOGLETEST_DISCOVER_TESTS_SCRIPT
${CMAKE_CURRENT_LIST_DIR}/GoogleTestAddTests.cmake
)注意:在我的示例中,GoogleTestAddTests.cmake就在处理cmake文件的旁边。
然后简单的调用
gtest_discover_tests(my_target
PROPERTIES ENVIRONMENT "[==[PATH=${my_path};$ENV{PATH}]==]"
)应该行得通。
https://stackoverflow.com/questions/57541741
复制相似问题