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 comprobar ARGC.
    • 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 o arg_UNPARSED_ARGUMENTS. FATAL_ERROR siempre que sea posible, WARNING si es necesario para la compatibilidad con versiones anteriores.

  • Todo cmake_parse_arguments debe usar PARSE_ARGV.

  • Todos los foreach bucles deben usar IN LISTS, IN ITEMSo RANGE.

  • 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}"))
  • 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.cmakees find_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.
  • 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.
    • 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 y IN_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 y vcpkg_list(SET foo) si es una variable de lista.

  • set(var) no debe usarse. Use unset(var) para desencadenar una variable, set(var "") para establecerla en la cadena vacía y vcpkg_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 resultado

  • Todas 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 asistente z_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 el Z_VCPKG_ prefijo para evitar la colisión con las variables locales definidas por cualquier otro código.

    • Ejemplos:
      • vcpkg_cmake_configure's Z_VCPKG_CMAKE_GENERATOR
      • z_vcpkg_get_cmake_vars's Z_VCPKG_GET_CMAKE_VARS_FILE
  • include()solo se permiten en ports.cmake o vcpkg-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 de cmake_minimum_required ports.cmake.
    • Esto cmake_minimum_required se debe aumentar cada vez que se agrega una nueva versión de CMake a vcpkgTools.xml, como debería en cmake_minimum_required todos los archivos auxiliares CMakeLists.txt .
  • 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 un z_, pero no asigne un nombre a una función z_z_foo_barauxiliar .
  • Las variables globales públicas se denominan VCPKG_.