Guide CMake complet. Première partie: syntaxe


Présentation


CMake est un ensemble d'utilitaires ouvert et multiplateforme conçu pour automatiser les tests, la compilation et la création de packages de projet en C / C ++. En écrivant une fois un petit script que tout le monde comprend, vous assurerez la même construction de votre projet sur n'importe quelle plateforme où CMake est disponible.


Le langage CMake , en cours de traduction dans un fichier d'assemblage natif (par exemple, Makefile ou Ninja), définit le processus de toute gestion de projet. A votre disposition, côté fonctionnel, il n'y a que des équipes qui peuvent se constituer en structures assez complexes. Nous allons commencer par eux.


Lancement de CMake


Voici des exemples d'utilisation du langage CMake que vous devez pratiquer. Expérimentez avec le code source en modifiant les commandes existantes et en en ajoutant de nouvelles. Pour exécuter ces exemples, installez CMake à partir du site Web officiel .


Équipes


Les commandes de CMake sont similaires aux fonctions de nombreux langages de programmation. Pour appeler une commande, vous devez écrire son nom, puis lui passer des arguments entre parenthèses, séparés par des espaces. Dans l'exemple ci-dessus, six arguments sont passés à la commande message pour sortie vers la console:


 #    "CMake is the most powerful buildsystem!" message("CMake " "is " "the " "most " "powerful " "buildsystem!") 

Arguments


Les arguments encadrés de guillemets doubles permettent le blindage et la substitution de variables à l'intérieur. Les arguments sans cadre ne permettent pas la production de telles choses et ne peuvent pas inclure les caractères ()#"\ et les espaces, mais sont plus pratiques à utiliser. Exemple:


 #  "Hello, my lovely CMake",    "!": message("Hello, my lovely CMake\t!") #  "Hello,_my_lovely_CMake!"  : message(Hello,_my_lovely_CMake!) 

Il convient de noter que l'argument Walk;around;the;forest s'étendra à la liste Walk around the forest , car tout argument non encadré se développe automatiquement en une liste de valeurs (à condition que les valeurs de l'argument d'origine soient séparées par des points-virgules), mais encadrées en double entre guillemets comme argument, une telle transformation ne se produit pas (les points-virgules disparaissent simplement). Cette fonctionnalité a été mentionnée dans les commentaires.


Commentaires


Les commentaires commencent par un signe dièse et se terminent à la fin de la ligne où ils ont été imprimés. Le texte contenu dans les commentaires est ignoré par le système de génération et n'a aucun effet sur son fonctionnement. Les exemples ci-dessus montrent également l'utilisation de commentaires.


Variables


Les variables peuvent être définies en appelant la commande set et supprimées en appelant unset . Vous pouvez obtenir la valeur d'une variable en construisant ${VARIABLE} . Si la variable n'a pas encore été définie et quelque part où il était nécessaire d'obtenir sa valeur, cette variable se transformera en une chaîne vide. Un exemple:


 #   VARIABLE   "Mr. Thomas": set(VARIABLE "Mr. Thomas") #  "His name is: Mr. Thomas": message("His name is: " ${VARIABLE}) #  "'BINGO' is equal to: []",   "BINGO"  : message("'BINGO' is equal to: [${BINGO}]") #   VARIABLE: unset(VARIABLE) 

Les options


CMake prend en charge les options de configuration qui sont sujettes aux modifications de l'utilisateur. Les options sont similaires aux variables et sont définies par la commande option , qui ne prend que trois arguments: le nom de la variable, la description de la chaîne de la variable et la valeur par défaut de la variable ( ON ou OFF ):


 #   `USE_ANOTHER_LIBRARY`   # "Do you want to use an another library?"   "OFF": option(USE_ANOTHER_LIBRARY "Do you want to use an another library?" OFF) 

Expressions logiques


Avant de procéder à l'étude des opérateurs conditionnels et des constructions cycliques, il est nécessaire de comprendre le travail des expressions logiques. Les expressions logiques sont utilisées lors de la vérification des conditions et peuvent prendre l'une des deux valeurs: vrai ou faux. Par exemple, l'expression 52 LESS 58 sera vraie, puisque 52 <58. L'expression 88 EQUAL 88 sera vraie, 63 GREATER 104 sera fausse. Vous pouvez comparer non seulement des nombres, mais également des chaînes, des versions, des fichiers, l'appartenance à une liste et des expressions régulières. Une liste complète des expressions logiques peut être trouvée ici .


Déclarations conditionnelles


Les opérateurs conditionnels dans CMake fonctionnent exactement comme dans d'autres langages de programmation. Dans cet exemple, seul le premier opérateur conditionnel fonctionnera, ce qui vérifie que 5> 1. Les deuxième et troisième conditions sont fausses, car 5 ne peut pas être inférieur ou égal à un. Les blocs de commande elseif et else sont facultatifs, et endif requis et signale la fin des vérifications précédentes.


 #  "Of course, 5 > 1!": if(5 GREATER 1) message("Of course, 5 > 1!") elseif(5 LESS 1) message("Oh no, 5 < 1!") else() message("Oh my god, 5 == 1!") endif() 

Cycles


Les boucles dans CMake sont similaires aux boucles dans d'autres langages de programmation. Dans l'exemple ci-dessus, la valeur de la variable VARIABLE est définie sur Airport , puis quatre commandes imbriquées sont exécutées séquentiellement jusqu'à ce que la valeur de la variable VARIABLE soit égale à Airport . La dernière commande du quatrième set(VARIABLE "Police station") définit la valeur de la variable vérifiée dans le Police station , de sorte que la boucle s'arrêtera immédiatement avant d'atteindre la deuxième itération. La commande endwhile signale l'achèvement de la liste des commandes imbriquées dans la boucle.


 #      "VARIABLE is still 'Airport'": set(VARIABLE Airport) while(${VARIABLE} STREQUAL Airport) message("VARIABLE is still '${VARIABLE}'") message("VARIABLE is still '${VARIABLE}'") message("VARIABLE is still '${VARIABLE}'") set(VARIABLE "Police station") endwhile() 

Cet exemple pour chaque foreach fonctionne comme suit: à chaque itération de cette boucle, la variable VARIABLE se voit attribuer la valeur suivante dans la liste Give me the sugar please! puis la commande message(${VARIABLE}) est exécutée, qui affiche la valeur actuelle de la variable VARIABLE . Lorsqu'il n'y a aucune valeur dans la liste, la boucle termine son exécution. La commande endforeach signale l'achèvement de la liste des commandes imbriquées dans la boucle.


 #  "Give me the sugar please!"   : foreach(VARIABLE Give me the sugar please!) message(${VARIABLE}) endforeach() 

Il existe 3 autres formes d'écriture d'une foreach . Le premier cycle dans cet exemple génère des entiers de 0 à 10 à la place de la liste, le deuxième cycle génère dans la plage de 3 à 15, et le troisième cycle fonctionne dans le segment de 50 à 90, mais avec un pas de 10.


 #  "0 1 2 3 4 5 6 7 8 9 10"   : foreach(VARIABLE RANGE 10) message(${VARIABLE}) endforeach() #  "3 4 5 6 7 8 9 10 11 12 13 14 15"   : foreach(VARIABLE RANGE 3 15) message(${VARIABLE}) endforeach() #  "50 60 70 80 90"   : foreach(VARIABLE RANGE 50 90 10) message(${VARIABLE}) endforeach() 

Fonctions et macros


La syntaxe CMake vous permet de définir vos propres commandes qui peuvent être appelées exactement comme intégrées. L'exemple suivant montre l'utilisation des fonctions et des macros: tout d'abord, une fonction et une macro sont définies avec leurs propres commandes, et lorsqu'elles sont appelées, leurs commandes sont exécutées séquentiellement.


 #   "print_numbers": function(print_numbers NUM1 NUM2 NUM3) message(${NUM1} " " ${NUM2} " " ${NUM3}) endfunction() #   "print_words": macro(print_words WORD1 WORD2 WORD3) message(${WORD1} " " ${WORD2} " " ${WORD3}) endmacro() #   "print_numbers",   "12 89 225": print_numbers(12 89 225) #   "print_words",   "Hey Hello Goodbye": print_words(Hey Hello Goodbye) 

La commande de function prend le nom de la future fonction comme premier argument, et le reste des arguments sont les noms des paramètres qui peuvent être utilisés comme variables normales. Les paramètres ne sont visibles que par la fonction en cours de définition, ce qui signifie que nous ne pouvons pas accéder à ses paramètres en dehors de la fonction. De plus, toutes les autres variables définies et redéfinies dans la fonction ne sont visibles que par elle-même.


Les macros sont similaires aux fonctions à l'exception qu'elles n'ont pas leur propre portée: toutes les variables à l'intérieur des macros sont considérées comme globales. Vous pouvez en savoir plus sur les différences entre les macros et les fonctions ici .


Comme indiqué dans les commentaires, les macros dans CMake sont similaires aux macros du préprocesseur C: si vous placez la commande return dans le corps de la macro, vous quitterez la fonction appelante (ou le script entier), comme le montre cet exemple:


 #  ,   : macro(demonstrate_macro) return() endmacro() #  ,   : function(demonstrate_func) demonstrate_macro() message("The function was invoked!") endfunction() #  "Something happened with the function!" demonstrate_func() message("Something happened with the function!") 

Dans l'exemple ci-dessus, la fonction de demonstrate_func n'aura pas le temps d'imprimer le message The function was invoked! , comme précédemment, le lieu d'appel de la macro demonstrate_macro sera remplacé et la commande exit sera exécutée.


Analyse des arguments


Comme indiqué dans les commentaires, le puissant mécanisme cmake_parse_arguments permet d'analyser les arguments passés à une fonction ou à une macro.


Cette commande accepte le préfixe utilisé dans la définition des variables (voir le paragraphe suivant), une liste d'options utilisées sans valeurs ultérieures, une liste de mots clés suivie d'une seule valeur, une liste de mots clés suivie d'ensembles de valeurs et une liste de toutes les valeurs passées à la fonction ou macro.


Le travail du mécanisme d'analyse des arguments consiste à convertir les arguments reçus en valeurs variables. Ainsi, la commande considérée pour chaque option et mot clé définit sa propre variable de la forme <Prefix>_<OptionOrKeyword> , qui encapsule une certaine valeur. Pour les options, ce sont des valeurs booléennes (true - l'option est indiquée; sinon, false), et pour les mots clés, toutes les valeurs transférées situées après elles.


La fonction custom_function contient un appel à cmake_parse_arguments , puis cmake_parse_arguments les valeurs de certaines variables. Ensuite, la fonction est appelée avec les arguments LOW NUMBER 30 COLORS red green blue , après quoi elle est imprimée à l'écran:


 function(custom_function) #       : cmake_parse_arguments(CUSTOM_FUNCTION "LOW;HIGH" "NUMBER" "COLORS" ${ARGV}) #  "'LOW' = [TRUE]": message("'LOW' = [${CUSTOM_FUNCTION_LOW}]") # "'HIGH' = [FALSE]": message("'HIGH' = [${CUSTOM_FUNCTION_HIGH}]") #  "'NUMBER' = [30]": message("'NUMBER' = [${CUSTOM_FUNCTION_NUMBER}]") #  "'COLORS' = [red;green;blue]": message("'COLORS' = [${CUSTOM_FUNCTION_COLORS}]") endfunction() #   "custom_function"   : custom_function(LOW NUMBER 30 COLORS red green blue) 

Portées


Dans la section précédente, vous avez appris que certaines constructions dans CMake peuvent définir leur propre portée. En fait, toutes les variables sont considérées comme globales par défaut (leur accès est partout), à l'exception de celles qui ont été définies et redéfinies dans les fonctions. Il existe également des variables de cache qui ont leur propre étendue, mais elles ne sont pas utilisées aussi souvent.


Comme mentionné dans les commentaires, les variables peuvent être définies dans la portée "parent" à l'aide de la commande set(VARIABLE ... PARENT_SCOPE) . Cet exemple illustre cette fonctionnalité:


 # ,   "VARIABLE"   # "In the parent scope..."    : function(demonstrate_variable) set(VARIABLE "In the parent scope..." PARENT_SCOPE) endfunction() #   "VARIABLE"    : demonstrate_variable() #      "VARIABLE" : message("'VARIABLE' is equal to: ${VARIABLE}") 

Si PARENT_SCOPE supprimé de la définition de la variable VARIABLE , alors la variable sera accessible uniquement à la fonction demonstrate_variable , et dans la portée globale, elle prendra une valeur vide.


Conclusion


Ceci conclut la syntaxe CMake. Le prochain article sera publié dans environ deux jours et présentera l'utilisation du système de construction CMake. A très bientôt!

Source: https://habr.com/ru/post/fr431428/


All Articles