Definir macro de pré-processador através do CMake?

283

Como defino uma variável de pré-processador através do CMake?

O código equivalente seria #define foo.

Mythli
fonte

Respostas:

382

Durante muito tempo, o CMake teve o add_definitionscomando para esse fim. No entanto, recentemente o comando foi substituído por uma abordagem mais refinada (comandos separados para definições de compilação, incluem diretórios e opções do compilador).

Um exemplo usando as novas add_compile_definitions :

add_compile_definitions(OPENCV_VERSION=${OpenCV_VERSION})
add_compile_definitions(WITH_OPENCV2)

Ou:

add_compile_definitions(OPENCV_VERSION=${OpenCV_VERSION} WITH_OPENCV2)

A parte boa disso é que ele contorna as artimanhas surradas que o CMake possui para add_definitions . O CMake é um sistema tão surrado, mas eles finalmente estão encontrando alguma sanidade.

Encontre mais explicações sobre quais comandos usar para sinalizadores de compilador aqui: https://cmake.org/cmake/help/latest/command/add_definitions.html

Da mesma forma, você pode fazer isso por alvo, conforme explicado na resposta de Jim Hunziker.

ypnos
fonte
4
Na página vinculada: "Nota Este comando foi substituído por alternativas: Use add_compile_definitions () para adicionar definições de pré-processador." Talvez esta resposta precise de uma edição?
M.Herzkamp 10/07
9
No cmake 3.10.2, add_compile_definitionslança CMake Error at CMakeLists.txt:6 (add_compile_definitions): Unknown CMake command "add_compile_definitions".. Teve que usar em seu add_compile_options(-D <your-def>)lugar.
code_dredd
2
@mannyglover Eu não penso assim, mas você pode definir os sinalizadores de compilador com -D, algo ao longo das linhas de cmake -D CMAKE_CXXFLAGS='-DDEBUG_CHESSBOARD'(não testado)
ypnos
1
É realmente novo ... na verdade, está no More Modern CMake (> 3.11). Uma dor que é tão difícil saber quando um comando foi introduzido.
Sandburg
1
@ Sandburg Você pode abrir o link para a última documentação: https://cmake.org/cmake/help/v3.17/command/add_compile_definitions.html#command:add_compile_definitionse começar a alterar o número da versão para baixo até a página desaparecer. Essa seria a versão em que ainda não existe. Na próxima jogada, você pode ir para a Whats newseção para encontrar um novo comando ou recurso. Então não é tão difícil.
Andry
245

Para fazer isso para um destino específico, você pode fazer o seguinte:

target_compile_definitions(my_target PRIVATE FOO=1 BAR=1)

Você deve fazer isso se tiver mais de um alvo que está construindo e não quiser que todos usem os mesmos sinalizadores. Consulte também a documentação oficial em target_compile_definitions .

Jim Hunziker
fonte
1
@JimHunziker Qual é a target_compile_definitions(my_target PRIVATE FOO=1)diferença set_source_files_properties(foo.cpp PROPERTIES COMPILE_DEFINITIONS -DFOO=1)?
John Strood
1
@ JohnStrood A diferença está no nível do escopo. target_compile_definitionsdefine o valor para WHOLE executable / library, onde como 'set_source_files_properties` define o valor apenas para o arquivo especificado. O último comando permite que os arquivos sejam compilados usando um idioma diferente; isto é: set_source_files_properties(compile_me_as_objc.c PROPERTIES -x objective-c. Observe que -x objective-caqui está um sinalizador específico para GCC / Clang.
Julian Kirsch
20

A outra solução proposta nesta página é útil em algumas versões do Cmake <3.3.2 . Aqui a solução para a versão que estou usando (ou seja, 3.3.2). Verifique a versão do seu Cmake usando $ cmake --versione escolha a solução mais adequada às suas necessidades. A documentação do cmake pode ser encontrada na página oficial.

Com o CMake versão 3.3.2, para criar

#define foo

Eu precisava usar:

add_definitions(-Dfoo)   # <--------HERE THE NEW CMAKE LINE inside CMakeLists.txt
add_executable( ....)
target_link_libraries(....)

e, para ter uma definição de macro de pré-processador como esta:

#define foo=5

a linha é assim modificada:

add_definitions(-Dfoo=5)   # <--------HERE THE NEW CMAKE LINE inside CMakeLists.txt
add_executable( ....)
target_link_libraries(....)
Leos313
fonte
4
De acordo com a documentação , esta solução é realmente a abordagem mais antiga e antiquada. As outras respostas oferecem as soluções mais modernas.
Squareskittles
2
Quando escrevi a resposta, tentei a outra solução, mas nenhuma delas estava funcionando.
Leos313
@quareskittles, alguma ideia de por que a solução da outra resposta não funcionou corretamente? CMake dar erros se eu experimentá-los
Leos313
1
Se você estiver usando o CMake 3.3.2, conforme indicado em sua resposta, precisará usar add_definitions()ou target_compile_definitions(). O comando mais moderno add_compile_definitions(),, não foi adicionado até o CMake 3.12. @ Leos313
squareskittles
1
@quareskittles, estou atualizando a resposta, reescrevendo o que escrevi há alguns meses. Obrigado por apontar isso
Leos313