web-dev-qa-db-fra.com

Faire une boucle sur une liste de chaînes

Je voudrais parcourir la liste des éléments, donnés dans une chaîne. Comme l'exige CMake, les éléments sont séparés par des points-virgules. Le suivant

cmake_minimum_required(VERSION 2.8)

FOREACH(LETTER "a;b;c")
  MESSAGE("<<${LETTER}>>")
ENDFOREACH()

interprète la chaîne "a;b;c" comme chaîne littérale. En revanche, lors de l'attribution de "a;b;c" à une variable d'abord, tout fonctionne comme prévu.

cmake_minimum_required(VERSION 2.8)

SET(MYLIST "a;b;c")
FOREACH(LETTER ${MYLIST})
  MESSAGE("<<${LETTER}>>")
ENDFOREACH()

Est-ce la méthode recommandée pour parcourir une liste ou existe-t-il une solution plus élégante?

20
Nico Schlömer

La source de votre confusion est probablement l'interprétation particulière de CMake des chaînes citées.

Par exemple, les éléments suivants parcourent tous correctement la liste des chaînes:

(1) foreach(LETTER a b c) [...]
(2) foreach(LETTER a;b;c) [...]
(3) set(MYLIST "a;b;c")
    foreach(LETTER ${MYLIST}) [...]

Le seul cas où cela ne fonctionne pas est

(4) foreach(LETTER "a;b;c") [...]

La raison pour laquelle (1) et (2) le travail se trouve dans le manuel de langage de CMake pour les arguments non cotés :

Le contenu d'argument non guidé se compose de tout le texte dans un bloc contigu de caractères autorisés ou échappés. Les séquences d'échappement et les références variables sont évaluées. La valeur résultante est divisée de la même manière Les listes se divisent en éléments . Chaque élément non vide est donné à l'invocation de commande comme argument. Par conséquent, un argument non cité peut être donné à une invocation de commande en tant que zéro ou plusieurs arguments.

Notez que ceci est différent de arguments cités , qui évaluent également les séquences d'échappement et les références de variable, mais ne font pas l'expansion de la liste. Cela explique pourquoi (4) échoue.

La question intéressante est maintenant de savoir pourquoi (3) réussit toujours. set accepte les arguments de valeur unique et de valeur de liste. En fait, tout avant la fermeture ) ou l'un des mots clés CACHE ou PARENT_SCOPE est considéré comme faisant partie de la valeur. À ce titre, les deux commandes suivantes sont équivalentes:

set(MYLIST "a;b;c")
set(MYLIST a;b;c)

Dans les deux cas, la valeur de MYLIST sera a;b;c (sans les guillemets).

Lorsque nous développons maintenant ${MYLIST} dans une autre commande, vous pouvez penser qu'elle effectue un simple remplacement de chaîne avec la valeur de MYLIST, qui est a;b;c. La commande résultante sera ensuite développée via les règles d'arguments entre guillemets ou non. Autrement dit, les éléments suivants fonctionneront:

foreach(LETTER ${MYLIST}) [...]

alors que cela ne:

foreach(LETTER "${MYLIST}") [...]
36
ComicSansMS