Guide de style CMake
Nous nous attendons à ce que tous les scripts CMake soient les suivants :
- Dans le
scripts/
répertoire ou - Dans un
vcpkg-*
port
doit suivre les instructions présentées dans ce document. Les scripts existants peuvent ne pas encore suivre ces instructions ; on s’attend à ce que nous continuions à mettre à jour les anciens scripts pour qu’ils tombent en ligne avec ces instructions.
Ces instructions sont destinées à créer la stabilité dans nos scripts. Nous espérons qu’ils faciliteront la compatibilité avant et descendante.
Les instructions
À l’exception des paramètres sortants, nous utilisons
cmake_parse_arguments()
toujours plutôt que les paramètres de fonction ou en faisant référence à${ARG<N>}
.Cela n’a pas nécessairement besoin d’être suivi pour les « fonctions d’assistance locales de script »
- Dans ce cas, les paramètres positionnels doivent être placés dans la déclaration de fonction (au lieu d’utiliser
${ARG<N>}
) et doivent être nommés en fonction des règles locales (c’est-à-diresnake_case
). - Exception : les paramètres positionnels facultatifs doivent être attribués à un nom via
set(argument_name "${ARG<N>}")
, après vérificationARGC
.
- Dans ce cas, les paramètres positionnels doivent être placés dans la déclaration de fonction (au lieu d’utiliser
Les paramètres out doivent être le premier paramètre d’une fonction. Exemple :
function(format out_var) cmake_parse_arguments(PARSE_ARGV 1 "arg" ...) # ... set(buffer "output") set("${out_var}" "${buffer}" PARENT_SCOPE) endfunction()
Il n’existe aucun argument non utilisé ou non utilisé. Toujours vérifier
ARGN
ouarg_UNPARSED_ARGUMENTS
.FATAL_ERROR
si possible,WARNING
si nécessaire pour la compatibilité descendante.Tous
cmake_parse_arguments
doivent utiliserPARSE_ARGV
.Toutes les
foreach
boucles doivent utiliserIN LISTS
,IN ITEMS
ouRANGE
.Les variables
${ARGV}
et${ARGN}
ne sont pas référencées, sauf dans les messages utiles à l’utilisateur.- (c.-à-d.
message(FATAL_ERROR "blah was passed extra arguments: ${ARGN}")
)
- (c.-à-d.
Nous utilisons toujours des fonctions, et non des macros ou du code de niveau supérieur.
- Exception : « macros d’assistance locales de script ». Il est parfois utile de définir une petite macro. Cette opération doit être effectuée avec parcimonie, et les fonctions doivent être préférées.
- Exception :
vcpkg.cmake
'sfind_package
.
Les scripts de l’arborescence des scripts ne doivent pas être censés avoir besoin de modifications observables dans le cadre d’une opération normale.
- Exemple de violation :
vcpkg_acquire_msys()
contient des packages et des versions codés en dur qui ont besoin de se mettre à jour au fil du temps en raison de la suppression d’anciens packages par le projet MSYS. - Exemple d’exception :
vcpkg_from_sourceforge()
contient une liste de miroirs qui nécessitent une maintenance, mais n’a pas d’impact observable sur les appelants.
- Exemple de violation :
Règles de guillemets : il existe trois types d’arguments dans CMake - sans guillemets (), entre guillemets (
foo(BAR)
foo("BAR")
) et entre crochets (foo([[BAR]])
). Suivez ces règles pour citer correctement :Si un argument contient une extension
${...}
de variable, il doit être entre guillemets.Exception : extension de variable « splat », lorsqu’une variable est passée à une fonction en tant qu’arguments multiples. Dans ce cas, l’argument doit simplement être
${foo}
:vcpkg_list(SET working_directory) if(DEFINED "arg_WORKING_DIRECTORY") vcpkg_list(SET working_directory WORKING_DIRECTORY "${arg_WORKING_DIRECTORY}") endif() # calls do_the_thing() if NOT DEFINED arg_WORKING_DIRECTORY, # else calls do_the_thing(WORKING_DIRECTORY "${arg_WORKING_DIRECTORY}") do_the_thing(${working_directory})
Sinon, si l’argument contient des séquences d’échappement qui ne sont pas
\\
,\"
ou\$
si cet argument doit être un argument entre guillemets.- Par exemple :
"foo\nbar"
doit être entre guillemets.
- Par exemple :
Sinon, si l’argument contient un
\
argument , un"
ou un$
, cet argument doit être entre crochets.Exemple :
set(x [[foo\bar]]) set(y [=[foo([[bar\baz]])]=])
Sinon, si l’argument contient des caractères qui ne sont pas alphanumériques ou
_
, cet argument doit être entre guillemets.Sinon, l’argument doit être non cité.
Exception : les arguments de
if()
type<variable|string>
doivent toujours être entre guillemets :Les deux arguments des opérateurs de comparaison -
EQUAL
,STREQUAL
,VERSION_LESS
, etc.Premier argument vers
MATCHES
etIN_LIST
Exemple :
if("${FOO}" STREQUAL "BAR") # ... if("${BAZ}" EQUAL "0") # ... if("FOO" IN_LIST list_variable) # ... if("${bar}" MATCHES [[a[bcd]+\.[bcd]+]]) # ...
Pour les expressions uniques et pour d’autres types de prédicats qui ne prennent
<variable|string>
pas, utilisez les règles normales.
Il n’existe aucun paramètre « pointeur » ou « in-out » (où un utilisateur passe un nom de variable plutôt que le contenu), à l’exception des paramètres sortants simples.
Les variables ne sont pas supposées être vides. Si la variable est destinée à être utilisée localement, elle doit être initialisée explicitement pour être vide si
set(foo "")
elle est une variable de chaîne etvcpkg_list(SET foo)
s’il s’agit d’une variable de liste.set(var)
ne doit pas être utilisé. Permetunset(var)
de supprimer une variable,set(var "")
de la définir sur la chaîne vide etvcpkg_list(SET var)
de la définir sur la liste vide. Remarque : la chaîne vide et la liste vide sont la même valeur ;il s’agit d’une différence notationnelle plutôt que d’une différence dans le résultatToutes les variables censées être héritées de l’étendue parente sur une limite d’API (c’est-à-dire pas une fonction locale de fichier) doivent être documentées. Toutes les variables mentionnées dans les fichiers Triplet sont considérées comme documentées.
Les paramètres out sont définis uniquement et
PARENT_SCOPE
ne sont jamais lus. Consultez également l’assistancez_vcpkg_forward_output_variable()
pour transférer les paramètres via une étendue de fonction.CACHE
les variables sont utilisées uniquement pour les variables globales qui sont partagées en interne entre les fonctions fortement couplées et pour l’état interne au sein d’une fonction unique afin d’éviter de dupliquer le travail. Celles-ci doivent être utilisées de manière extrêmement éparse et doivent utiliser leZ_VCPKG_
préfixe pour éviter toute collision avec les variables locales qui seraient définies par tout autre code.- Exemples :
vcpkg_cmake_configure
EstZ_VCPKG_CMAKE_GENERATOR
z_vcpkg_get_cmake_vars
EstZ_VCPKG_GET_CMAKE_VARS_FILE
- Exemples :
include()
sont autorisés uniquement dansports.cmake
ouvcpkg-port-config.cmake
.foreach(RANGE)
les arguments de l’argument doivent toujours être des nombres naturels et<start>
doivent toujours être inférieurs ou égaux à .<stop>
Cela doit être vérifié par quelque chose comme :
if("${start}" LESS_EQUAL "${end}") foreach(RANGE "${start}" "${end}") ... endforeach() endif()
Tous les scripts basés sur les ports doivent être utilisés
include_guard(GLOBAL)
pour éviter d’être inclus plusieurs fois.
Versions CMake à exiger
- Tous les scripts CMake, à l’exception
vcpkg.cmake
deports.cmake
, peuvent supposer la version de CMake présente dans lecmake_minimum_required
fichier .- Cela
cmake_minimum_required
doit être heurté chaque fois qu’une nouvelle version de CMake est ajoutée àvcpkgTools.xml
, comme si danscmake_minimum_required
tous les fichiers d’assistanceCMakeLists.txt
.
- Cela
vcpkg.cmake
doit supposer une version de CMake de retour à la version 3.7.2 en général- Des fonctions et des options spécifiques peuvent supposer une version supérieure de CMake ; si c’est le cas, veillez à commenter cette fonction ou cette option avec la version CMake requise.
Modification des fonctions existantes
- Ne supprimez jamais d’arguments dans les fonctions non internes ; s’ils ne devraient plus rien faire, il suffit de les prendre comme normal et d’avertir sur l’utilisation.
- N’ajoutez jamais un nouvel argument obligatoire.
Nommage des variables
cmake_parse_arguments
: définir le préfixe sur"arg"
Les variables locales sont nommées avec
snake_case
Les noms de variables globales internes sont préfixés par
Z_VCPKG_
.Les noms de variables globales expérimentales externes sont préfixés par
X_VCPKG_
.Les fonctions internes sont préfixées avec
z_vcpkg_
- Les fonctions internes à une fonction unique (c’est-à-dire les fonctions d’assistance) sont nommées
[z_]<func>_<name>
, où<func>
est le nom de la fonction à laquelle elles sont un assistance et<name>
c’est ce que fait la fonction d’assistance.z_
doit être ajouté à l’avant s’il<func>
n’a pas dez_
fonction d’assistance, mais ne nomme pas de fonctionz_z_foo_bar
d’assistance.
- Les fonctions internes à une fonction unique (c’est-à-dire les fonctions d’assistance) sont nommées
Les variables globales publiques sont nommées
VCPKG_
.