0

I have a Jenkins pipeline which runs tests on a Windows VM using ctest.exe in a bat script, like this:

// Run all tests in parallel, timeout after 1 hour, exclude any tests needing opengl
bat ''' "C:/Program Files/CMake/bin/ctest.exe" --timeout 3600 --verbose -C Release -j4 -E "(_gl)|(GL)" '''

In my CTest setup, I'm setting the environment using the code below. I have already been looking around and found that I need to escape the backslashes in the PATH to avoid CMake interpreting it as a list, but that doesn't seem to make it all the way through to the end:

set(test_dll_path)
set(PATH_STRING "")

# Add the paths I want to a list
list(APPEND test_dll_path "${PROJECT_SOURCE_DIR}/../bin64")
list(APPEND test_dll_path "${PROJECT_SOURCE_DIR}/../bin64/plugins")

# Concatenate that list and convert it to a string
cmake_path(APPEND_STRING test_dll_path ";$ENV{PATH}")
cmake_path(CONVERT "${test_dll_path}" TO_NATIVE_PATH_LIST test_dll_path NORMALIZE)

# Escape the backslashes to avoid CTest interpreting it as a list
string(REPLACE ";" "\\;" test_dll_path "${test_dll_path}")

# Join it to the existing path using more escaped backslashes
list(JOIN test_dll_path "\\;" PATH_STRING)

# Assign the environment to blank first ("append_string" only works if the property existed already)
set_property( TEST ${TEST_TARGET} PROPERTY ENVIRONMENT "" )
set_property( TEST ${TEST_TARGET} APPEND_STRING PROPERTY ENVIRONMENT "PATH=${PATH_STRING}" )
    
# This comes through as one full string when printed as a message, but still interpreted as a list when CTest uses it later :(
message(DEBUG "Test ${TEST_TARGET} PATH = \"${PATH_STRING}\"")

Then, when I run the jenkins pipeline, the --verbose setting prints the environment for the test. When this happens, the PATH is split on each semicolon and the tests act as though only the first item is in the PATH:

1: Test command: C:\jenkins\workspace\ows-IncrementalBuild-Test_PR-856\source\Tests\tut.exe "-cppunitreport"
1: Environment variables: 
1:  PATH=C:\jenkins\workspace\ows-IncrementalBuild-Test_PR-856\source\bin64
1:  C:\jenkins\workspace\ows-IncrementalBuild-Test_PR-856\source\bin64\plugins
1:  C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow
1:  C:\Program Files (x86)\MSBuild\14.0\bin\amd64
1:  C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\amd64
1:  C:\Windows\Microsoft.NET\Framework64\v4.0.30319

...etc

1 Answers1

0

From a week of searching I hadn't seen this, but a colleague just sent me this answer: How do I make a list in CMake with the semicolon value?

So the answer is, if in doubt, keep adding more backslashes. I needed three when joining the path up, like so:

# Escape the backslashes to avoid CTest interpreting it as a list
string(REPLACE ";" "\\\;" test_dll_path "${test_dll_path}")

# Join it to the existing path using more escaped backslashes
list(JOIN test_dll_path "\\\;" PATH_STRING)