Réponses:
Lorsque vous écrivez des scripts CMake, vous devez connaître beaucoup de choses sur la syntaxe et comment utiliser les variables dans CMake.
Chaînes utilisant set()
:
set(MyString "Some Text")
set(MyStringWithVar "Some other Text: ${MyString}")
set(MyStringWithQuot "Some quote: \"${MyStringWithVar}\"")
Ou avec string()
:
string(APPEND MyStringWithContent " ${MyString}")
Listes utilisant set()
:
set(MyList "a" "b" "c")
set(MyList ${MyList} "d")
Ou mieux avec list()
:
list(APPEND MyList "a" "b" "c")
list(APPEND MyList "d")
Listes de noms de fichiers:
set(MySourcesList "File.name" "File with Space.name")
list(APPEND MySourcesList "File.name" "File with Space.name")
add_excutable(MyExeTarget ${MySourcesList})
set()
Commande CMakestring()
Commande CMakelist()
Commande CMakeIl y a d'abord les «variables normales» et les choses que vous devez savoir sur leur portée:
CMakeLists.txt
ils sont fixés et tout appelé à partir de là ( add_subdirectory()
, include()
, macro()
et function()
).add_subdirectory()
et function()
sont spéciales, car elles ouvrent leur propre portée.
set(...)
là-bas ne sont visibles que là-bas et font une copie de toutes les variables normales du niveau de portée à partir duquel elles sont appelées (appelée portée parente).set(... PARENT_SCOPE)
function(xyz _resultVar)
réglageset(${_resultVar} 1 PARENT_SCOPE)
include()
ou les macro()
scripts modifieront les variables directement dans la portée d'où elles sont appelées.Deuxièmement, il y a le "cache de variables globales". Ce que vous devez savoir sur le cache:
CMakeCache.txt
fichier de votre répertoire de sortie binaire.Les valeurs du cache peuvent être modifiées dans l' application GUI de CMake avant d'être générées. Par conséquent, ils ont - par rapport aux variables normales - a type
et a docstring
. Je n'utilise normalement pas l'interface graphique, donc je l'utilise set(... CACHE INTERNAL "")
pour définir mes valeurs globales et persistantes.
Veuillez noter que le INTERNAL
type de variable de cache impliqueFORCE
Dans un script CMake, vous ne pouvez modifier les entrées de cache existantes que si vous utilisez la set(... CACHE ... FORCE)
syntaxe. Ce comportement est utilisé par exemple par CMake lui-même, car il ne force normalement pas les entrées du cache lui-même et vous pouvez donc le prédéfinir avec une autre valeur.
cmake -D var:type=value
, juste cmake -D var=value
ou avec cmake -C CMakeInitialCache.cmake
.unset(... CACHE)
.Le cache est global et vous pouvez les définir pratiquement n'importe où dans vos scripts CMake. Mais je vous recommanderais de réfléchir à deux fois pour savoir où utiliser les variables de cache (elles sont globales et persistantes). Je préfère normalement la syntaxe set_property(GLOBAL PROPERTY ...)
et set_property(GLOBAL APPEND PROPERTY ...)
pour définir mes propres variables globales non persistantes.
Pour éviter les pièges, vous devez connaître les éléments suivants concernant les variables:
find_...
commandes - en cas de succès - écrivent leurs résultats sous forme de variables mises en cache "afin qu'aucun appel ne recherche à nouveau"set(MyVar a b c)
est "a;b;c"
et set(MyVar "a b c")
est"a b c"
list()
commande pour gérer les listesfunctions()
place de macros()
parce que vous ne voulez pas que vos variables locales apparaissent dans la portée parent.project()
et enable_language()
. Il pourrait donc être important de définir certaines variables avant d'utiliser ces commandes.Parfois, seules les variables de débogage sont utiles. Les éléments suivants peuvent vous aider:
printf
style de débogage en utilisant la message()
commande. Il existe également des modules prêts à l'emploi livrés avec CMake lui-même: CMakePrintHelpers.cmake , CMakePrintSystemInformation.cmakeCMakeCache.txt
fichier dans votre répertoire de sortie binaire. Ce fichier est même généré si la génération réelle de votre environnement make échoue.cmake --trace ...
pour voir le processus d'analyse complet de CMake. C'est en quelque sorte la dernière réserve, car cela génère beaucoup de sortie.$ENV{...}
et écrire set(ENV{...} ...)
des variables d'environnement$<...>
ne sont évaluées que lorsque le générateur de CMake écrit l'environnement de création (il est comparé aux variables normales qui sont remplacées "en place" par l'analyseur)${${...}}
vous pouvez donner des noms de variables dans une variable et référencer son contenu.if()
commande)
if(MyVariable)
vous pouvez directement vérifier une variable pour vrai / faux (pas besoin ici pour l'enfermement ${...}
)1
, ON
, YES
, TRUE
, Y
ou un nombre non nul.0
, OFF
, NO
, FALSE
, N
, IGNORE
, NOTFOUND
, la chaîne vide, ou se termine par le suffixe -NOTFOUND
.if(MSVC)
, mais elle peut être déroutante pour quelqu'un qui ne connaît pas ce raccourci de syntaxe.set(CMAKE_${lang}_COMPILER ...)
if()
commandes. Voici un exemple où CMAKE_CXX_COMPILER_ID
est "MSVC"
et MSVC
est "1"
:
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
est vrai, car il évalue if("1" STREQUAL "1")
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
est faux, car il évalue à if("MSVC" STREQUAL "1")
if(MSVC)
cmake_policy(SET CMP0054 NEW)
"n'interpréter les if()
arguments que comme des variables ou des mots clés lorsqu'ils ne sont pas entre guillemets".option()
commande
ON
ou OFF
et elles permettent une gestion spéciale comme par exemple les dépendancesoption
avec la set
commande. La valeur donnée à option
n'est en réalité que la "valeur initiale" (transférée une fois dans le cache lors de la première étape de configuration) et est ensuite destinée à être modifiée par l'utilisateur via l'interface graphique de CMake .${MyString}
conduit à un tas d'erreurs pour "si des arguments donnés ..." comme CMake erreur près de si: "si des arguments donnés" suivis de parantheses, "NOT", "EQUALS" et similaire .
MyString
contient un nom de variable qui sera à nouveau dé-référencé. Je crois que personne ne veut vraiment de ce OLD
comportement. Donc , de mon point de vue de son tout à fait sûr et rétrocompatible à la politique qui se trouve juste CMP0054
à NEW
(voir la discussion ici ).
if (MyString ...)
(si c'est votre code qui donne l'avertissement).
${MyString}
et l' avons remplacé par MyString
(ou je pense que nous les avons toutes supprimées). Toujours pas de joie: Build 372 . La merde ne vient même pas de notre code. Il semble venir de CMake. La ligne 283 est if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
.
Voici quelques exemples de base pour démarrer rapidement et sans problèmes.
Définir la variable:
SET(INSTALL_ETC_DIR "etc")
Utiliser la variable:
SET(INSTALL_ETC_CROND_DIR "${INSTALL_ETC_DIR}/cron.d")
Définir la variable:
SET(PROGRAM_SRCS
program.c
program_utils.c
a_lib.c
b_lib.c
config.c
)
Utiliser la variable:
add_executable(program "${PROGRAM_SRCS}")
if ("${MyString}" ...)
je vois les avertissements:Policy CMP0054 is not set: Only interpret if() arguments as variables or keywords when unquoted
. Voir, par exemple, Build 367 . Des idées?