首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用CMake,如何在gtest_discover_tests -gtest_list_tests调用上设置环境属性?

使用CMake,如何在gtest_discover_tests -gtest_list_tests调用上设置环境属性?
EN

Stack Overflow用户
提问于 2019-08-18 04:52:45
回答 1查看 2.7K关注 0票数 9

我目前正在将当前的构建环境从MSBuild迁移到CMake。在这种情况下,我需要更新PATH变量,以便单元测试可以执行。这对于gtest_add_tests来说不是问题,因为它使用源代码来识别测试。但是,使用gtest_discover_tests标志执行单元测试的--gtest_list_tests无法识别任何测试,因为在构建过程中遇到了STATUS_DLL_NOT_FOUND错误。

例如:

代码语言:javascript
复制
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}")

这样做是可行的:

代码语言:javascript
复制
gtest_add_tests(TARGET gTestExe TEST_LIST allTests)
set_tests_properties(${all_tests} PROPERTIES ENVIRONMENT "PATH=${NEWPATH}")

但这并不意味着:

代码语言:javascript
复制
#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中。

EN

回答 1

Stack Overflow用户

发布于 2020-05-14 13:00:38

今天早上我遇到了同样的问题,我发现了一个(肮脏的?)解决办法。它不能工作的原因有点复杂,但解决办法很简单。

为什么它不能工作

代码语言:javascript
复制
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将生成以下行:

代码语言:javascript
复制
set_tests_properties( mytest PROPERTIES ENVIRONMENT PATH=mypath mypath2)

转义;不起作用,因为列表是在add_custom_command()中自动使用的(cmake3.17.1中的1.420),忽略了任何形式的转义。

要防止cmake将路径中的每个值作为列表处理,可以使用括号参数如下:

代码语言:javascript
复制
gtest_discover_tests(gTestExe PROPERTIES ENVIRONMENT "[==[PATH=${NEWPATH}]==]")

然后,cmake将把您的论点作为一个整体来处理。不幸的是,CMake还将在生成的代码中放置一个括号,因为它包含[=和可能的空格:

代码语言:javascript
复制
# This line 
if(_arg MATCHES "[^-./:a-zA-Z0-9_]")
  set(_args "${_args} [==[${_arg}]==]")
else()
  set(_args "${_args} ${_arg}")
endif()  

结果生成以下脚本:

代码语言:javascript
复制
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替换为下面一个:

代码语言:javascript
复制
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的路径:

代码语言:javascript
复制
# 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文件的旁边。

然后简单的调用

代码语言:javascript
复制
 gtest_discover_tests(my_target
   PROPERTIES ENVIRONMENT "[==[PATH=${my_path};$ENV{PATH}]==]"
 )

应该行得通。

票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57541741

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档