Guía de estilo de CMake
Esperamos que todos los scripts de CMake sean:
- En el
scripts/
directorio o - En un
vcpkg-*
puerto
debe seguir las directrices que se describen en este documento. Es posible que los scripts existentes aún no sigan estas directrices; se espera que sigamos actualizando los scripts antiguos para que se alinee con estas directrices.
Estas directrices están pensadas para crear estabilidad en nuestros scripts. Esperamos que hagan más fácil la compatibilidad con versiones anteriores y hacia delante.
Las directrices
Excepto para los parámetros out, siempre usamos
cmake_parse_arguments()
en lugar de parámetros de función o hacemos referencia a${ARG<N>}
.Esto no tiene que seguirse necesariamente para "funciones auxiliares locales de script"
- En este caso, los parámetros posicionales deben colocarse en la declaración de función (en lugar de usar
${ARG<N>}
) y deben asignarse nombres según las reglas locales (es decir,snake_case
). - Excepción: los parámetros posicionales que son opcionales deben asignarse un nombre a través
set(argument_name "${ARG<N>}")
de , después de comprobarARGC
.
- En este caso, los parámetros posicionales deben colocarse en la declaración de función (en lugar de usar
Los parámetros out deben ser el primer parámetro de una función. Ejemplo:
function(format out_var) cmake_parse_arguments(PARSE_ARGV 1 "arg" ...) # ... set(buffer "output") set("${out_var}" "${buffer}" PARENT_SCOPE) endfunction()
No hay argumentos no preparados ni no se usan. Compruebe siempre para
ARGN
oarg_UNPARSED_ARGUMENTS
.FATAL_ERROR
siempre que sea posible,WARNING
si es necesario para la compatibilidad con versiones anteriores.Todo
cmake_parse_arguments
debe usarPARSE_ARGV
.Todos los
foreach
bucles deben usarIN LISTS
,IN ITEMS
oRANGE
.Las variables
${ARGV}
y${ARGN}
no tienen referencia, excepto en mensajes útiles para el usuario.- (es decir,
message(FATAL_ERROR "blah was passed extra arguments: ${ARGN}")
)
- (es decir,
Siempre usamos funciones, no macros ni código de nivel superior.
- Excepción: "macros auxiliares locales de script". A veces resulta útil definir una macro pequeña. Esto debe hacerse con moderación y se deben preferir las funciones.
- Excepción:
vcpkg.cmake
esfind_package
.
No se debe esperar que los scripts del árbol de scripts necesiten cambios observables como parte de la operación normal.
- Infracción de ejemplo:
vcpkg_acquire_msys()
tiene paquetes y versiones codificados de forma rígida que necesitan actualizar con el tiempo debido a que el proyecto MSYS quita paquetes antiguos. - Excepción de ejemplo:
vcpkg_from_sourceforge()
tiene una lista de reflejos que necesita mantenimiento, pero no tiene un impacto observable en el comportamiento de los autores de la llamada.
- Infracción de ejemplo:
Reglas para comillas: hay tres tipos de argumentos en CMake: sin comillas (
foo(BAR)
), entre comillas (foo("BAR")
) y entre corchetes (foo([[BAR]])
). Siga estas reglas para citar correctamente:Si un argumento contiene una expansión
${...}
de variable, debe estar entre comillas.Excepción: una expansión de variable "splat", cuando una variable se pasará a una función como varios argumentos. En este caso, el argumento simplemente debe ser
${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})
De lo contrario, si el argumento contiene secuencias de escape que no
\\
sean ,\"
o\$
, ese argumento debe ser un argumento entre comillas.- Por ejemplo:
"foo\nbar"
debe estar entrecomillado.
- Por ejemplo:
De lo contrario, si el argumento contiene un
\
, o"
,$
ese argumento debe estar entre corchetes.Ejemplo:
set(x [[foo\bar]]) set(y [=[foo([[bar\baz]])]=])
De lo contrario, si el argumento contiene caracteres que no son alfanuméricos o
_
, ese argumento debe estar entre comillas.De lo contrario, el argumento debe estar sin comprimido.
Excepción: los argumentos al
if()
tipo<variable|string>
siempre deben estar entrecomillados:Ambos argumentos para los operadores de comparación:
EQUAL
,STREQUAL
,VERSION_LESS
, etcetera.Primer argumento para
MATCHES
yIN_LIST
Ejemplo:
if("${FOO}" STREQUAL "BAR") # ... if("${BAZ}" EQUAL "0") # ... if("FOO" IN_LIST list_variable) # ... if("${bar}" MATCHES [[a[bcd]+\.[bcd]+]]) # ...
Para expresiones únicas y para otros tipos de predicados que no toman
<variable|string>
, use las reglas normales.
No hay parámetros "puntero" ni "in-out" (donde un usuario pasa un nombre de variable en lugar del contenido), excepto para parámetros out simples.
No se supone que las variables están vacías. Si la variable está pensada para usarse localmente, debe inicializarse explícitamente para estar vacía con
set(foo "")
si es una variable de cadena yvcpkg_list(SET foo)
si es una variable de lista.set(var)
no debe usarse. Useunset(var)
para desencadenar una variable,set(var "")
para establecerla en la cadena vacía yvcpkg_list(SET var)
para establecerla en la lista vacía. Nota: la cadena vacía y la lista vacía son el mismo valor;se trata de una diferencia notational en lugar de una diferencia en el resultadoTodas las variables esperadas se heredan del ámbito primario a través de un límite de API (es decir, no una función local de archivo) se deben documentar. Todas las variables mencionadas en los archivos Triplet se consideran documentadas.
Los parámetros out solo se establecen en
PARENT_SCOPE
y nunca se leen. Consulte también el asistentez_vcpkg_forward_output_variable()
para reenviar parámetros a través de un ámbito de función.CACHE
Las variables solo se usan para variables globales que se comparten internamente entre funciones fuertemente acopladas y para el estado interno dentro de una sola función para evitar duplicar el trabajo. Estos deben usarse con moderación y deben usar elZ_VCPKG_
prefijo para evitar la colisión con las variables locales definidas por cualquier otro código.- Ejemplos:
vcpkg_cmake_configure
'sZ_VCPKG_CMAKE_GENERATOR
z_vcpkg_get_cmake_vars
'sZ_VCPKG_GET_CMAKE_VARS_FILE
- Ejemplos:
include()
solo se permiten enports.cmake
ovcpkg-port-config.cmake
.foreach(RANGE)
Los argumentos de siempre deben ser números naturales y<start>
siempre deben ser menores o iguales que<stop>
.Esto debe comprobarse con algo parecido a:
if("${start}" LESS_EQUAL "${end}") foreach(RANGE "${start}" "${end}") ... endforeach() endif()
Todos los scripts basados en puertos deben usarse
include_guard(GLOBAL)
para evitar incluirse varias veces.
Versiones de CMake que requieren
- Todos los scripts de CMake, excepto para
vcpkg.cmake
, pueden suponer la versión de CMake que está presente en decmake_minimum_required
ports.cmake
.- Esto
cmake_minimum_required
se debe aumentar cada vez que se agrega una nueva versión de CMake avcpkgTools.xml
, como debería encmake_minimum_required
todos los archivos auxiliaresCMakeLists.txt
.
- Esto
vcpkg.cmake
debe asumir una versión de CMake de nuevo a la versión 3.7.2 en general.- Las funciones y opciones específicas pueden suponer una versión de CMake mayor; Si lo hacen, asegúrese de comentar esa función o opción con la versión de CMake necesaria.
Cambio de funciones existentes
- Nunca quite argumentos en funciones no internas; si ya no deben hacer nada, simplemente tómelos como normales y avisan sobre el uso.
- Nunca agregue un nuevo argumento obligatorio.
Asignación de nombres a variables
cmake_parse_arguments
: establezca el prefijo en ."arg"
Las variables locales se denominan con
snake_case
Los nombres de variables globales internos tienen el
Z_VCPKG_
prefijo .Los nombres de variables globales experimentales externos tienen el
X_VCPKG_
prefijo .Las funciones internas tienen el prefijo
z_vcpkg_
- Las funciones que son internas para una sola función (es decir, las funciones auxiliares) se denominan
[z_]<func>_<name>
, donde<func>
es el nombre de la función a la que son auxiliares y<name>
es lo que hace la función auxiliar.z_
debe agregarse al frente si<func>
no tiene unz_
, pero no asigne un nombre a una funciónz_z_foo_bar
auxiliar .
- Las funciones que son internas para una sola función (es decir, las funciones auxiliares) se denominan
Las variables globales públicas se denominan
VCPKG_
.