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çãoARGC
.
- Nesse caso, os parâmetros posicionais devem ser colocados na declaração da função (em vez de usar
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
ouarg_UNPARSED_ARGUMENTS
.FATAL_ERROR
quando possível,WARNING
se necessário para compatibilidade com versões anteriores.Todos
cmake_parse_arguments
devem usarPARSE_ARGV
.Todos os
foreach
loops devem usarIN LISTS
,IN ITEMS
, ouRANGE
.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}")
)
- (ou seja,
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.
- Exemplo de violação:
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.
- Por exemplo:
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
eIN_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 evcpkg_list(SET foo)
se for uma variável de lista.set(var)
não deve ser usado. Useunset(var)
para desconfigurar uma variável,set(var "")
defini-la para a string vazia evcpkg_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 resultadoTodas 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 auxiliarz_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 prefixoZ_VCPKG_
para evitar colidir com quaisquer variáveis locais que seriam definidas por qualquer outro código.- Exemplos:
vcpkg_cmake_configure
'sZ_VCPKG_CMAKE_GENERATOR
z_vcpkg_get_cmake_vars
'sZ_VCPKG_GET_CMAKE_VARS_FILE
- Exemplos:
include()
s só são permitidos emports.cmake
ouvcpkg-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.cmake
o , podem assumir a versão do CMake que está presente nocmake_minimum_required
.ports.cmake
- Isso
cmake_minimum_required
deve ser aumentado toda vez que uma nova versão do CMake for adicionada aovcpkgTools.xml
, assim como emcmake_minimum_required
todos os arquivos auxiliaresCMakeLists.txt
.
- Isso
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 umz_
, mas não nomeie uma funçãoz_z_foo_bar
auxiliar .
- As funções que são internas a uma única função (ou seja, funções auxiliares) são nomeadas
As variáveis globais públicas são denominadas
VCPKG_
.