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

时间:2019-08-18 04:52:45

标签: cmake googletest

我目前正在将当前的构建环境从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注册的构建后步骤期间,发现测试的调用失败,因为所需的库不在PATH中。

1 个答案:

答案 0 :(得分:-1)

今天早上,我遇到了同样的问题,并且发现了(肮脏的?)解决方法。它不起作用的原因有些复杂,但是解决方法非常简单。

为什么不起作用

gtest_discover_tests(gTestExe  PROPERTIES ENVIRONMENT "PATH=${NEWPATH}")

不起作用是因为PATH内容用分号分隔,因此被CMake视为列表值。

如果您查看GoogleTestAddTests.cmake文件(位于C:\Program Files\CMake\share\cmake-3.17\Modules中),它将使用foreach处理PROPERTIES参数。

在脚本PROPERTIES中,此时的ENVIRONMENT;PATH=mypath;mypath2值对于CMake如下所示,并将mypath2视为第三个参数,而不是PATH环境变量的值。 / p>

CMake然后将生成以下行:

set_tests_properties( mytest PROPERTIES ENVIRONMENT PATH=mypath mypath2)

转义;无效,因为列表在add_custom_command()中的GoogleTest.cmake中自动扩展了(cmake 3.17.1中的420)任何形式的转义。

要防止cmake foreach将路径中的每个值都视为列表,可以使用bracket argument

gtest_discover_tests(gTestExe PROPERTIES ENVIRONMENT "[==[PATH=${NEWPATH}]==]")

cmake foreach将把您的论点视为一个实体。不幸的是,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将尝试读取值,仅删除第一个bracket argument,因为它们不嵌套。

可能的解决方法

因此,我们需要CMake不要在我们自己的方括号参数上使用方括号参数。

首先在自己的存储库(位于GoogleTestAddTests.cmake中)C:\Program Files\CMake\share\cmake-3.17\Modules文件的本地副本。

GoogleTestAddTests.cmake的本地副本的开头(l。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}]==]"
 )

应该工作。