Respostas:
Ao escrever scripts do CMake, você precisa saber muito sobre a sintaxe e como usar variáveis no CMake.
Strings usando set():
set(MyString "Some Text")set(MyStringWithVar "Some other Text: ${MyString}")set(MyStringWithQuot "Some quote: \"${MyStringWithVar}\"")Ou com string():
string(APPEND MyStringWithContent " ${MyString}")Lista usando set():
set(MyList "a" "b" "c")set(MyList ${MyList} "d")Ou melhor com list():
list(APPEND MyList "a" "b" "c")list(APPEND MyList "d")Listas de nomes de arquivos:
set(MySourcesList "File.name" "File with Space.name")list(APPEND MySourcesList "File.name" "File with Space.name")add_excutable(MyExeTarget ${MySourcesList})set()Comando CMakestring()Comando CMakelist()Comando CMakePrimeiro, existem as "Variáveis normais" e o que você precisa saber sobre seu escopo:
CMakeLists.txteles são definidos em e tudo chamado de lá ( add_subdirectory(), include(), macro()e function()).add_subdirectory()e function()são especiais, porque abrem seu próprio escopo.
set(...)lá são visíveis apenas e elas fazem uma cópia de todas as variáveis normais do nível de escopo de onde são chamadas (chamadas de escopo pai).set(... PARENT_SCOPE)function(xyz _resultVar)configuraçãoset(${_resultVar} 1 PARENT_SCOPE)include()ou macro()scripts modificará variáveis diretamente no escopo de onde elas são chamadas.Segundo, existe o "Cache de Variáveis Globais". O que você precisa saber sobre o cache:
CMakeCache.txtarquivo no diretório de saída binária.Os valores no cache podem ser modificados no aplicativo GUI do CMake antes de serem gerados. Portanto, eles - em comparação com variáveis normais - têm a typee a docstring. Normalmente, não uso a GUI, portanto, set(... CACHE INTERNAL "")defino meus valores globais e persistentes.
Observe que o INTERNALtipo de variável de cache implicaFORCE
Em um script do CMake, você só pode alterar as entradas de cache existentes se usar a set(... CACHE ... FORCE)sintaxe. Esse comportamento é utilizado, por exemplo, pelo próprio CMake, porque normalmente não força as entradas de cache e, portanto, você pode predefini-lo com outro valor.
cmake -D var:type=value, just cmake -D var=valueou with cmake -C CMakeInitialCache.cmake.unset(... CACHE).O cache é global e você pode configurá-los praticamente em qualquer lugar nos scripts do CMake. Mas eu recomendo que você pense duas vezes sobre onde usar as variáveis de cache (são globais e persistentes). Normalmente, prefiro a sintaxe set_property(GLOBAL PROPERTY ...)e set_property(GLOBAL APPEND PROPERTY ...)para definir minhas próprias variáveis globais não persistentes.
Para evitar armadilhas, você deve saber o seguinte sobre variáveis:
find_...comandos - se bem-sucedidos - gravam seus resultados como variáveis em cache "para que nenhuma chamada procure novamente"set(MyVar a b c)é "a;b;c"e set(MyVar "a b c")é"a b c"list()comando para lidar com listasfunctions()vez de, macros()porque você não deseja que suas variáveis locais apareçam no escopo pai.project()e enable_language(). Portanto, pode ser importante definir algumas variáveis antes que esses comandos sejam usados.Às vezes, apenas variáveis de depuração ajudam. O seguinte pode ajudá-lo:
printfestilo antigo de depuração usando o message()comando Existem também alguns módulos prontos para uso fornecidos com o próprio CMake: CMakePrintHelpers.cmake , CMakePrintSystemInformation.cmakeCMakeCache.txtarquivo no diretório de saída binário. Esse arquivo é gerado mesmo se a geração real do seu ambiente de criação falhar.cmake --trace ...para ver o processo completo de análise do CMake. Essa é a última reserva, porque gera muita produção.$ENV{...}e escrever set(ENV{...} ...)variáveis de ambiente$<...>são avaliadas apenas quando o gerador do CMake grava o ambiente make (é comparado com variáveis normais que são substituídas "no local" pelo analisador)${${...}}você pode dar nomes de variáveis em uma variável e referenciar seu conteúdo.if()comando)
if(MyVariable)você pode verificar diretamente uma variável para true / false (não é necessário aqui para o anexo ${...})1, ON, YES, TRUE, Y, ou um número diferente de zero.0, OFF, NO, FALSE, N, IGNORE, NOTFOUND, a cadeia vazia, ou termina no sufixo -NOTFOUND.if(MSVC), mas pode ser confusa para alguém que não conhece esse atalho de sintaxe.set(CMAKE_${lang}_COMPILER ...)if()comandos. Aqui está um exemplo onde CMAKE_CXX_COMPILER_IDé "MSVC"e MSVCé "1":
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") é verdade, porque avalia como if("1" STREQUAL "1")if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") é falso, porque avalia como if("MSVC" STREQUAL "1")if(MSVC)cmake_policy(SET CMP0054 NEW)como "apenas interpretar if()argumentos como variáveis ou palavras-chave quando não estiver entre aspas".option()comando
ONou OFFpermitem uma manipulação especial, como por exemplo, dependênciasoptiono setcomando. O valor atribuído optioné realmente apenas o "valor inicial" (transferido uma vez para o cache durante a primeira etapa da configuração) e posteriormente deve ser alterado pelo usuário através da interface gráfica do usuário do CMake .${MyString}leva a um monte de erros para "se houver argumentos ...", como o erro CMake perto de se: "se houver argumentos" seguidos de parênteses, "NÃO", "IGUAIS" e similares .
if (MyString ...)lo (se for o seu código dando o aviso).
${MyString}e substituímos por MyString(ou acredito que removemos todas). Ainda sem alegria: Build 372 . A porcaria nem vem do nosso código. Parece vir do CMake. A linha 283 é if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC").
Aqui estão alguns exemplos básicos para começar rápido e sujo.
Definir variável:
SET(INSTALL_ETC_DIR "etc")
Usar variável:
SET(INSTALL_ETC_CROND_DIR "${INSTALL_ETC_DIR}/cron.d")
Definir variável:
SET(PROGRAM_SRCS
program.c
program_utils.c
a_lib.c
b_lib.c
config.c
)
Usar variável:
add_executable(program "${PROGRAM_SRCS}")
if ("${MyString}" ...)Eu sou avisos vendo:Policy CMP0054 is not set: Only interpret if() arguments as variables or keywords when unquoted. Consulte, por exemplo, Build 367 . Alguma ideia?