Compartilhar via


Guia de estilo do CMake

Esperamos que todos os scripts do CMake que sejam:

  • scripts/ No diretório ou
  • Em uma vcpkg-* porta

devem seguir as diretrizes estabelecidas neste documento. Os scripts existentes podem não seguir essas diretrizes ainda; Espera-se que continuemos a atualizar scripts antigos para se alinharem a essas diretrizes.

Essas diretrizes têm como objetivo criar estabilidade em nossos scripts. Esperamos que eles facilitem a compatibilidade com versões anteriores e posteriores.

As diretrizes

  • Exceto para parâmetros externos, sempre usamos cmake_parse_arguments() parâmetros em vez de função ou nos referindo a ${ARG<N>}.

    • Isso não precisa necessariamente ser seguido para "funções auxiliares locais de script"

      • Nesse caso, os parâmetros posicionais devem ser colocados na declaração da função (em vez de usar ${ARG<N>}) e devem ser nomeados de acordo com as regras locais (ou seja, snake_case).
      • Exceção: os parâmetros posicionais que são opcionais devem receber um nome via set(argument_name "${ARG<N>}"), após a verificação ARGC.
    • Out-parameters deve ser o primeiro parâmetro de uma função. Exemplo:

      function(format out_var)
        cmake_parse_arguments(PARSE_ARGV 1 "arg" ...)
        # ... set(buffer "output")
        set("${out_var}" "${buffer}" PARENT_SCOPE)
      endfunction()
      
  • Não há argumentos não analisados ou não utilizados. Sempre verifique se há ARGN ou arg_UNPARSED_ARGUMENTS. FATAL_ERROR quando possível, WARNING se necessário para compatibilidade com versões anteriores.

  • Todos cmake_parse_arguments devem usar PARSE_ARGV.

  • Todos os foreach loops devem usar IN LISTS, IN ITEMS, ou RANGE.

  • As variáveis ${ARGV} e ${ARGN} não são referenciadas, exceto em mensagens úteis para o usuário.

    • (ou seja, message(FATAL_ERROR "blah was passed extra arguments: ${ARGN}"))
  • Sempre usamos funções, não macros ou código de nível superior.

    • Exceção: "macros auxiliares locais de script". Às vezes, é útil definir uma macro pequena. Isso deve ser feito com moderação e as funções devem ser preferidas.
    • Exceção: vcpkg.cmake.find_package
  • Não se deve esperar que os scripts na árvore de scripts precisem de alterações observáveis como parte da operação normal.

    • Exemplo de violação: vcpkg_acquire_msys() tem pacotes codificados e versões que precisam ser atualizadas ao longo do tempo devido ao projeto MSYS descartar pacotes antigos.
    • Exemplo de exceção: vcpkg_from_sourceforge() tem uma lista de espelhos que precisa de manutenção, mas não tem um impacto de comportamento observável nos chamadores.
  • Regras para citar: existem três tipos de argumentos no CMake - sem aspas (foo(BAR)), entre aspas (foo("BAR")) e entre colchetes (foo([[BAR]])). Siga estas regras para citar corretamente:

    • Se um argumento contiver uma expansão ${...}de variável , ele deve ser colocado entre aspas.

      • Exceção: uma expansão de variável "splat", quando uma variável será passada para uma função como vários argumentos. Neste caso, o argumento deve ser ${foo}simplesmente :

        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})
        
    • Caso contrário, se o argumento contiver sequências de escape que não \\sejam , \", ou \$, esse argumento deverá ser um argumento entre aspas.

      • Por exemplo: "foo\nbar" deve ser citado.
    • Caso contrário, se o argumento contiver um \, um ", ou um $, esse argumento deverá ser colocado entre colchetes.

      • Exemplo:

        set(x [[foo\bar]])
        set(y [=[foo([[bar\baz]])]=])
        
    • Caso contrário, se o argumento contiver caracteres que não sejam alfanuméricos ou _, esse argumento deverá ser colocado entre aspas.

    • Caso contrário, o argumento não deve ser citado.

    • Exceção: os argumentos para if() do tipo <variable|string> devem sempre ser citados:

      • Ambos os argumentos para os operadores de comparação - EQUAL, STREQUAL, VERSION_LESS, etc.

      • O primeiro argumento para MATCHES e IN_LIST

      • Exemplo:

        if("${FOO}" STREQUAL "BAR") # ...
        if("${BAZ}" EQUAL "0") # ...
        if("FOO" IN_LIST list_variable) # ...
        if("${bar}" MATCHES [[a[bcd]+\.[bcd]+]]) # ...
        
      • Para expressões únicas e para outros tipos de predicados que não usam <variable|string>, use as regras normais.

  • Não há parâmetros de "ponteiro" ou "entrada-saída" (em que um usuário passa um nome de variável em vez do conteúdo), exceto para parâmetros de saída simples.

  • As variáveis não são consideradas vazias. Se a variável for destinada a ser usada localmente, ela deverá ser inicializada explicitamente para esvaziar se set(foo "") for uma variável de cadeia de caracteres e vcpkg_list(SET foo) se for uma variável de lista.

  • set(var) não deve ser usado. Use unset(var) para desconfigurar uma variável, set(var "") defini-la para a string vazia e vcpkg_list(SET var) defini-la para a lista vazia. Nota: a string vazia e a lista vazia têm o mesmo valor;Esta é uma diferença de notação e não uma diferença de resultado

  • Todas as variáveis que devem ser herdadas do escopo pai em um limite de API (ou seja, não uma função local de arquivo) devem ser documentadas. Todas as variáveis mencionadas nos arquivos Triplet são consideradas documentadas.

  • Os parâmetros de saída são apenas definidos e PARENT_SCOPE nunca são lidos. Consulte também o auxiliar z_vcpkg_forward_output_variable() para encaminhar parâmetros por meio de um escopo de função.

  • CACHE As variáveis são usadas apenas para variáveis globais que são compartilhadas internamente entre funções fortemente acopladas e para o estado interno dentro de uma única função para evitar a duplicação de trabalho. Eles devem ser usados com extrema moderação e devem usar o prefixo Z_VCPKG_ para evitar colidir com quaisquer variáveis locais que seriam definidas por qualquer outro código.

    • Exemplos:
      • vcpkg_cmake_configure's Z_VCPKG_CMAKE_GENERATOR
      • z_vcpkg_get_cmake_vars's Z_VCPKG_GET_CMAKE_VARS_FILE
  • include()s só são permitidos em ports.cmake ou vcpkg-port-config.cmake.

  • foreach(RANGE)Os argumentos de 's devem ser sempre números naturais e <start> devem ser sempre menores ou iguais a <stop>.

    • Isso deve ser verificado por algo como:

      if("${start}" LESS_EQUAL "${end}")
        foreach(RANGE "${start}" "${end}")
          ...
        endforeach()
      endif()
      
  • Todos os scripts baseados em porta devem ser usados include_guard(GLOBAL) para evitar serem incluídos várias vezes.

Versões do CMake a serem exigidas

  • Todos os scripts do CMake, exceto vcpkg.cmakeo , podem assumir a versão do CMake que está presente no cmake_minimum_required .ports.cmake
    • Isso cmake_minimum_required deve ser aumentado toda vez que uma nova versão do CMake for adicionada ao vcpkgTools.xml, assim como em cmake_minimum_required todos os arquivos auxiliares CMakeLists.txt .
  • vcpkg.cmake deve assumir uma versão do CMake de volta para 3.7.2 em geral
    • Funções e opções específicas podem assumir uma versão superior do CMake; se o fizerem, certifique-se de comentar essa função ou opção com a versão necessária do CMake.

Alterando funções existentes

  • Nunca remova argumentos em funções não internas; Se eles não devem mais fazer nada, basta tomá-los normalmente e avisar sobre o uso.
  • Nunca adicione um novo argumento obrigatório.

Nomenclatura das variáveis

  • cmake_parse_arguments: defina o prefixo como "arg"

  • As variáveis locais são nomeadas com snake_case

  • Os nomes de variáveis globais internas são prefixados com Z_VCPKG_.

  • Os nomes de variáveis globais experimentais externas são prefixados com X_VCPKG_.

  • As funções internas são prefixadas com z_vcpkg_

    • As funções que são internas a uma única função (ou seja, funções auxiliares) são nomeadas [z_]<func>_<name>, onde <func> é o nome da função para a qual elas são auxiliares e <name> é o que a função auxiliar faz.
      • z_ deve ser adicionado à frente se <func> não tiver um z_, mas não nomeie uma função z_z_foo_barauxiliar .
  • As variáveis globais públicas são denominadas VCPKG_.