1

I think it should be super trivial, but seems like it's not supported... Is it even possible in CMake to have one value of a list contain a semicolon?

The reason is super simple - because I'm running on Windows, and on Windows the semicolon is the separator between two or more folders in one environment variable (i.e. PATH).

    list(
      APPEND
      MY_TEST_ENVIRONMENT
      "MY_FLAG=1"
    )

    # <...>

    list(
      APPEND
      MY_TEST_ENVIRONMENT
      "PATH=first_folder_path;second_folder_path"
    #                        ^--- here is the problem
    )

    # <...>


   set_property(TEST MyTests PROPERTY ENVIRONMENT ${MY_TEST_ENVIRONMENT})

I tried removing and adding double quotes, I tried escaping \;, I tried to add same env variable two times - but none of those work!

squareskittles
  • 11,997
  • 7
  • 31
  • 48
The Godfather
  • 3,138
  • 2
  • 33
  • 49
  • Can you also show how you intend to *use* the list? What commands are you performing on the list? How are you using this to set environment variables? – squareskittles Jan 22 '20 at 16:00
  • @squareskittles added, but I was expecting this is quite obvious from the names of my variables. This is the environment variables setup – The Godfather Jan 22 '20 at 17:58

2 Answers2

3

You are on the right track by escaping the semicolon with a backslash. However, when setting the list in the ENVIRONMENT test property, this is not the last place the list will be used (and interpreted by CMake). The MY_TEST_ENVIRONMENT list is then used to populate CTestTestfile.cmake, which is later read by CTest to setup your test environment.

In short, you need more escape characters to propagate the semicolons through to the test environment. Specifically, use a double backslash \\ to escape an extra backslash into the list, along with the \; escaped semicolon. Here is CMake's escape characters documentation for reference. In total, three backslashes should work:

list(
  APPEND
  MY_TEST_ENVIRONMENT
  "MY_FLAG=1"
)

# <...>

list(
  APPEND
  MY_TEST_ENVIRONMENT
  "PATH=first_folder_path\\\;second_folder_path"
#                         ^--- Use three backslashes here
)

# <...>

set_property(TEST MyTests PROPERTY ENVIRONMENT ${MY_TEST_ENVIRONMENT})
squareskittles
  • 11,997
  • 7
  • 31
  • 48
0

Unfortunately lists in CMake internally are just strings separated with semicolons. If you do:

set(MyList
    ABC
    DEF;GHI
)

You're defining a list with three elements. If you peek the contents:

message(${MyList})
message("${MyList}")

You'll get ABCDEFGHI and ABC;DEF;GHI respectively, so no way to know how many elements you actually wanted to have in either case. Most of CMake commands, like add_executable or target_compile_definitions interpret passed arguments this way and you will not be able to pass them lists with elements containing semicolons.

Note, that semicolons are not removed when you put your variable in quotes (see example above), so if you're invoking some external command, like a powershell script, then the PATH variable should be passed correctly. But then you wouldn't use a list for your arguments list (because elements are semicolon-separater), but rather build your own space-separated string.

Maciej Dziuban
  • 386
  • 2
  • 17
  • I know that semicolons are list separators in CMake. So this is not really an answer but rather a statement "Unfortunately it's impossible". That's sad :( – The Godfather Jan 22 '20 at 17:59