Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way to use platform specific separators in cmake

I wonder if there is a better solution to my problem. I am working on a platform independent software project and want to add python-based unittests to cmake. The issue that I encountered now is that when configuring the ctest tests and setting up the correct PYTHONPATH environment variable for running my test, I end up with a lot of boilerplate code for each test:

add_test(my_awesome_test ${PYTHON_EXECUTABLE} my_awesome_test.py)

if("${CMAKE_HOST_SYSTEM}" MATCHES ".*Windows.*")
  set_tests_properties(my_awesome_test PROPERTIES ENVIRONMENT "PYTHONPATH=somepath\;anotherpath")
else() # e.g. Linux
  set_tests_properties(my_awesome_test PROPERTIES ENVIRONMENT "PYTHONPATH=somepath:anotherpath")
endif()

# more tests like this after this...

The problem here is the branching, that is required only because of the platform dependent list separators.

Is there some neater way to accomplish this?

Is there a constant which specifies the platform separator or a function that allows me to construct these lists?


If there is no "proper" answer, I also wanted to share my obvious, but not-so-nice solution:

if("${CMAKE_HOST_SYSTEM}" MATCHES ".*Windows.*")
  set(SEP "\\;")
else() # e.g. Linux
  set(SEP ":")
endif()

add_test(my_awesome_test ${PYTHON_EXECUTABLE} my_awesome_test.py)
set_tests_properties(my_awesome_test PROPERTIES ENVIRONMENT "PYTHONPATH=somepath${SEP}anotherpath")

# more tests like this after this...

On Windows the ";" must be double escaped because otherwise it it is substituted later in the add_test line as a single ";" again, which is then in turn interpreted as the cmake-list separator leading to wrong results. However, having cmake report which character should be used as list separator would still be nicer...

like image 542
PK Cakeout Avatar asked Sep 15 '15 12:09

PK Cakeout


2 Answers

Unfortunately file(TO_NATIVE_PATH ... does not convert ; to : on Unix platforms. I think the easiest way is therefore something like this:

set(PATH "/usr/bin" "/bin")

if (UNIX)
  string(REPLACE ";" ":" PATH "${PATH}")
endif()

This works because CMake lists are really ;-separated strings, so on Windows you can use them for path lists as-is. It won't work for paths containing ; or : but that will trip up 99% of Unix software anyway so I wouldn't worry about it.

like image 105
Timmmm Avatar answered Sep 28 '22 20:09

Timmmm


You can use the file function as follow:

file(TO_CMAKE_PATH "<path>" <variable>)
file(TO_NATIVE_PATH "<path>" <variable>)

https://cmake.org/cmake/help/v3.9/command/file.html

like image 24
IceBerg0 Avatar answered Sep 28 '22 22:09

IceBerg0