3 votes

Ne pas étendre la variable de la liste CMake

J'ai un CMake script qui exécute des tests par l'intermédiaire de add_test() qui fonctionne sous Windows (Server 2008, ne demandez pas) dans CMake 3.15. Lorsque ces tests sont appelés, la variable d'environnement PYTHONPATH dans l'environnement dans lequel ils sont exécutés semble être réinitialisée à la valeur par défaut de l'environnement, et ne contient pas certains chemins dont elle a besoin.

J'ai donc besoin de définir PYTHONPATH lorsque les tests sont exécutés à la valeur de la variable $ENV{PYTHONPATH} lorsque CMake s'exécute. Celle-ci contient un certain nombre de chemins séparés par des points-virgules, CMake pense donc qu'il s'agit d'une liste et essaie de l'étendre en un certain nombre de chaînes de caractères séparées par des espaces, ce qui se termine évidemment mal.

Je n'arrive pas à trouver comment empêcher CMake de faire ça. D'après tout ce que je peux voir, vous devriez être en mesure de faire juste entourer avec des guillemets :

add_test(
  NAME mytest
  COMMAND cmake -E env PYTHONPATH="$ENV{PYTHONPATH}"
  run_test_here)

...mais il fait toujours l'expansion. J'ai aussi essayé de régler avec set_tests_properties :

set_tests_properties(mytest PROPERTIES
    ENVIRONMENT PYTHONPATH="$ENV{PYTHONPATH}")

...mais cela ne semble rien faire du tout - PYTHONPATH au moment du test n'a pas été modifié. Je pensais que c'était parce qu'il s'agissait d'une variable d'environnement, mais en utilisant une variable CMake normale via la commande set() ne fait aucune différence, donc je fais quelque chose de mal. Aidez-moi, s'il vous plaît !

3voto

Kamil Cuk Points 11578

Ce qui suit devrait fonctionner :

COMMAND cmake -E env "PYTHONPATH=$ENV{PYTHONPATH}"

Vous devez citer la partie complète de la ligne de commande, pour que le message soit correctement développé.

Testé avec :

set(tmp "C:\\Python27\\Scripts;E:\\JenkinsMIDEBLD\\workspace\\...;...")
add_test(NAME MYtest1 COMMAND cmake -S . -E env "tmp=${tmp}") 
add_test(NAME MYtest2 COMMAND cmake -S . -E env tmp="${tmp}") 

Après avoir exécuté ctest J'ai compris :

1: Test command: /bin/cmake "-S" "." "-E" "env" "tmp=C:\Python27\Scripts;E:\JenkinsMIDEBLD\workspace\...;..."
2: Test command: /bin/cmake "-S" "." "-E" "env" "tmp="C:\Python27\Scripts" "E:\JenkinsMIDEBLD\workspace\..." "...""

Le premier test est correct ; transmis à var tandis que la seconde passe une liste séparée par des espaces.

C'est ainsi que cmake analyse arguments cités . Un argument est soit entièrement cité, soit pas du tout - les citations partielles sont interprétées comme une citation littérale. " . Donc assumnig cela :

set(var a;b;c)

Les suivantes :

var="$var"

n'est pas un argument cité et " sont prises au pied de la lettre ! Il élargit le $var dans une liste séparée par des espaces et le " reste, il y a un " entre = y a et il y a en outre " sur la fin. Le site var="$var" est égal à :

var=\"a b c\"
    ^^     ^^    - the quotes stay!
^^^^^^^ ^ ^^^    - these are 3 arguments, the last one is `c"`

Sans guillemets, c'est :

var=$var

est égal à (remarquez les guillemets manquants) :

var=a c c

Pour citer un argument, il faut le citer en entier, avec le premier et le dernier caractère de l'élément. " :

"var=$var"

s'étendra à :

"var=a;b;c"

0voto

fabian Points 3742

Vous pouvez faire en sorte que cela fonctionne avec le ENVIRONMENT la propriété du test, mais il y a un hic :

Le point-virgule sépare les différentes variables d'environnement à définir ; vous devez échapper aux points-virgules dans votre variable d'environnement. Par exemple, au lieu de

set_tests_properties(mytest PROPERTIES
    ENVIRONMENT "PYTHONPATH=foo;bar")

vous devez utiliser

set_tests_properties(mytest PROPERTIES
    ENVIRONMENT "PYTHONPATH=foo\\;bar")

Le fait qu'une variable d'environnement puisse contenir des points-virgules rend nécessaire une certaine transformation : puisque ; est utilisé pour séparer les éléments de la liste, vous pouvez simplement utiliser list(JOIN) pour les remplacer par "\\;" .

L'exemple suivant fonctionne avec PATH pas PYTHONPATH puisque je n'ai pas installé Python :

CMakeLists.txt

cmake_minimum_required(VERSION 3.12.4) # required for list(JOIN)

project(TestProject)

# get a version of the PATH environment var that can be used in the ENVIRONMENT test property
set(_PATH $ENV{PATH})
list(JOIN _PATH "\\;" _PATH_CLEAN)

# just use a cmake script so we don't need to require any program able to retrieve environment vars
add_test(NAME Test1 COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_SOURCE_DIR}/test_script.cmake")

# we add another simpler var to test in the cmake script
set_tests_properties(Test1 PROPERTIES ENVIRONMENT "PATH=${_PATH_CLEAN};FOO=foo")

enable_testing()

test_script.cmake

message(STATUS "PATH=$ENV{PATH}")

if (NOT "$ENV{FOO}" STREQUAL "foo")
    # the following command results in a non-0 exit code, if executed
    message(FATAL_ERROR "FOO environment var should contain \"foo\" but contains \"$ENV{FOO}\"")
endif()

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X