Guida di stile di CMake
Ci aspettiamo che tutti gli script CMake siano i seguenti:
scripts/
Nella directory o- In una
vcpkg-*
porta
deve seguire le linee guida disposte in questo documento. Gli script esistenti potrebbero non seguire ancora queste linee guida; è previsto che si continuerà ad aggiornare gli script precedenti in modo che siano conformi a queste linee guida.
Queste linee guida sono concepite per creare stabilità negli script. Speriamo che faciliteranno la compatibilità sia in avanti che con le versioni precedenti.
Linee guida
Ad eccezione dei parametri out, si usano
cmake_parse_arguments()
sempre anziché parametri di funzione o si fa riferimento a${ARG<N>}
.Questo non deve necessariamente essere seguito per le "funzioni helper locali script"
- In questo caso, i parametri posizionali devono essere inseriti nella dichiarazione di funzione (anziché usare
${ARG<N>}
) e devono essere denominati in base alle regole locali (ad esempiosnake_case
). - Eccezione: ai parametri posizionali facoltativi deve essere assegnato un nome tramite
set(argument_name "${ARG<N>}")
, dopo aver controllatoARGC
.
- In questo caso, i parametri posizionali devono essere inseriti nella dichiarazione di funzione (anziché usare
I parametri out devono essere il primo parametro di una funzione. Esempio:
function(format out_var) cmake_parse_arguments(PARSE_ARGV 1 "arg" ...) # ... set(buffer "output") set("${out_var}" "${buffer}" PARENT_SCOPE) endfunction()
Non sono presenti argomenti non verificati o inutilizzati. Verificare sempre la presenza
ARGN
di oarg_UNPARSED_ARGUMENTS
.FATAL_ERROR
se possibile,WARNING
se necessario per la compatibilità con le versioni precedenti.Tutti
cmake_parse_arguments
devono usarePARSE_ARGV
.Tutti i
foreach
cicli devono usareIN LISTS
,IN ITEMS
oRANGE
.Le variabili
${ARGV}
e${ARGN}
non vengono referenziate, ad eccezione dei messaggi utili per l'utente.- (ad esempio,
message(FATAL_ERROR "blah was passed extra arguments: ${ARGN}")
)
- (ad esempio,
Usiamo sempre funzioni, non macro o codice di primo livello.
- Eccezione: "macro helper locali script". A volte è utile definire una piccola macro. Questa operazione deve essere eseguita con moderazione e le funzioni devono essere preferite.
- Eccezione:
vcpkg.cmake
'sfind_package
.
Gli script nell'albero degli script non devono essere necessari modifiche osservabili come parte del normale funzionamento.
- Violazione di esempio:
vcpkg_acquire_msys()
include pacchetti hardcoded e versioni che richiedono l'aggiornamento nel tempo a causa del progetto MSYS che elimina i pacchetti precedenti. - Eccezione di esempio:
vcpkg_from_sourceforge()
include un elenco di mirror che richiede la manutenzione, ma non ha un impatto sul comportamento osservabile sui chiamanti.
- Violazione di esempio:
Regole per le virgolette: in CMake sono disponibili tre tipi di argomenti, tra virgolette (
foo(BAR)
), tra virgolette (foo("BAR")
) e tra parentesi quadre (foo([[BAR]])
). Seguire queste regole per citare correttamente:Se un argomento contiene un'espansione
${...}
variabile , deve essere racchiuso tra virgolette.Eccezione: espansione di una variabile "splat", quando una variabile verrà passata a una funzione come più argomenti. In questo caso, l'argomento deve essere
${foo}
semplicemente :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})
In caso contrario, se l'argomento contiene sequenze di escape che non
\\
sono ,\"
o\$
, tale argomento deve essere un argomento tra virgolette.- Ad esempio:
"foo\nbar"
deve essere racchiuso tra virgolette.
- Ad esempio:
In caso contrario, se l'argomento contiene un
\
oggetto , o"
,$
tale argomento deve essere racchiuso tra parentesi quadre.Esempio:
set(x [[foo\bar]]) set(y [=[foo([[bar\baz]])]=])
In caso contrario, se l'argomento contiene caratteri non alfanumerici o
_
, l'argomento deve essere racchiuso tra virgolette.In caso contrario, l'argomento deve essere unquotato.
Eccezione: gli argomenti di
if()
tipo<variable|string>
devono sempre essere racchiusi tra virgolette:Entrambi gli argomenti degli operatori di confronto -
EQUAL
,STREQUAL
, eVERSION_LESS
così via.Primo argomento a
MATCHES
eIN_LIST
Esempio:
if("${FOO}" STREQUAL "BAR") # ... if("${BAZ}" EQUAL "0") # ... if("FOO" IN_LIST list_variable) # ... if("${bar}" MATCHES [[a[bcd]+\.[bcd]+]]) # ...
Per le singole espressioni e per altri tipi di predicati che non accettano
<variable|string>
, usare le regole normali.
Non sono presenti parametri "puntatore" o "in uscita" (in cui un utente passa un nome di variabile anziché il contenuto), ad eccezione dei semplici parametri out.
Le variabili non vengono considerate vuote. Se la variabile deve essere usata localmente, deve essere inizializzata in modo esplicito con vuoto se
set(foo "")
si tratta di una variabile stringa evcpkg_list(SET foo)
, se si tratta di una variabile di elenco.set(var)
non deve essere utilizzato. Utilizzareunset(var)
per annullare l'impostazione di una variabile,set(var "")
per impostarla sulla stringa vuota evcpkg_list(SET var)
impostarla sull'elenco vuoto. Nota: la stringa vuota e l'elenco vuoto sono lo stesso valore;questa è una differenza notazione piuttosto che una differenza nel risultatoTutte le variabili che devono essere ereditate dall'ambito padre attraverso un limite API (ovvero non una funzione locale di file) devono essere documentate. Tutte le variabili indicate nei file Triplet vengono considerate documentate.
I parametri out vengono impostati solo in
PARENT_SCOPE
e non vengono mai letti. Vedere anche l'helperz_vcpkg_forward_output_variable()
per inoltrare i parametri tramite un ambito di funzione.CACHE
le variabili vengono usate solo per le variabili globali condivise internamente tra le funzioni fortemente associate e per lo stato interno all'interno di una singola funzione per evitare la duplicazione del lavoro. Questi devono essere usati con estrema moderazione e devono usare ilZ_VCPKG_
prefisso per evitare conflitti con qualsiasi variabile locale che verrebbe definita da qualsiasi altro codice.- Esempi:
vcpkg_cmake_configure
'sZ_VCPKG_CMAKE_GENERATOR
z_vcpkg_get_cmake_vars
'sZ_VCPKG_GET_CMAKE_VARS_FILE
- Esempi:
include()
s è consentito solo inports.cmake
ovcpkg-port-config.cmake
.foreach(RANGE)
Gli argomenti di devono essere sempre numeri naturali e<start>
devono essere sempre minori o uguali a<stop>
.Questa operazione deve essere verificata in base a un aspetto simile al seguente:
if("${start}" LESS_EQUAL "${end}") foreach(RANGE "${start}" "${end}") ... endforeach() endif()
Tutti gli script basati su porta devono essere usati
include_guard(GLOBAL)
per evitare di essere inclusi più volte.
Versioni di CMake da richiedere
- Tutti gli script CMake, ad eccezione
vcpkg.cmake
di , possono presupporre la versione di CMake presente incmake_minimum_required
diports.cmake
.- Questa
cmake_minimum_required
operazione deve essere aggiornata ogni volta che viene aggiunta una nuova versione di CMake avcpkgTools.xml
, come dovrebbecmake_minimum_required
in tutti i file helperCMakeLists.txt
.
- Questa
vcpkg.cmake
deve presupporre una versione di CMake alla versione 3.7.2 in generale- Funzioni e opzioni specifiche possono presupporre una versione CMake maggiore; in caso affermativo, assicurarsi di impostare come commento la funzione o l'opzione con la versione di CMake richiesta.
Modifica delle funzioni esistenti
- Non rimuovere mai argomenti in funzioni non interne; se non dovrebbero più fare nulla, basta prenderli come di consueto e avvisare sull'uso.
- Non aggiungere mai un nuovo argomento obbligatorio.
Assegnazione di nomi alle variabili
cmake_parse_arguments
: impostare il prefisso su"arg"
Le variabili locali sono denominate con
snake_case
I nomi delle variabili globali interni sono preceduti da
Z_VCPKG_
.I nomi di variabili globali sperimentali esterni sono preceduti da
X_VCPKG_
.Le funzioni interne sono precedute da un prefisso
z_vcpkg_
- Le funzioni interne a una singola funzione (ad esempio, le funzioni helper) sono denominate
[z_]<func>_<name>
, dove<func>
è il nome della funzione a cui sono un helper ed<name>
è ciò che fa la funzione helper.z_
deve essere aggiunto al front se<func>
non ha unz_
oggetto , ma non denominare una funzionez_z_foo_bar
helper .
- Le funzioni interne a una singola funzione (ad esempio, le funzioni helper) sono denominate
Le variabili globali pubbliche sono denominate
VCPKG_
.