Zdefiniować makro preprocesora poprzez CMake?

283

Jak zdefiniować zmienną preprocesora za pomocą CMake?

Równoważny kod to #define foo.

Mythli
źródło

Odpowiedzi:

382

Przez długi czas CMake miał add_definitionsdo tego polecenie. Jednak ostatnio polecenie to zostało zastąpione bardziej szczegółowym podejściem (osobne polecenia dla definicji kompilacji, obejmują katalogi i opcje kompilatora).

Przykład użycia nowych definicji add_compile_definitions :

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

Lub:

add_compile_definitions(OPENCV_VERSION=${OpenCV_VERSION} WITH_OPENCV2)

Zaletą tego jest to, że omija odrapane sztuczki, dla których przygotował CMake add_definitions. CMake to taki obskurny system, ale w końcu zaczynają szukać zdrowia psychicznego.

Znajdź więcej wyjaśnień na temat poleceń używanych w flagach kompilatora tutaj: https://cmake.org/cmake/help/latest/command/add_definitions.html

Podobnie możesz zrobić to dla każdego celu, jak wyjaśniono w odpowiedzi Jima Hunzikera.

Ypnos
źródło
4
Z połączonej strony: „Uwaga To polecenie zostało zastąpione przez alternatywy: użyj add_compile_definitions (), aby dodać definicje preprocesora”. Może ta odpowiedź wymaga edycji?
M.Herzkamp
9
W cmake 3.10.2, add_compile_definitionsrzuty CMake Error at CMakeLists.txt:6 (add_compile_definitions): Unknown CMake command "add_compile_definitions".. add_compile_options(-D <your-def>)Zamiast tego musiałem użyć .
code_dredd
2
@mannyglover Nie wydaje mi się, ale możesz ustawić flagi kompilatora za pomocą -D, coś w stylu cmake -D CMAKE_CXXFLAGS='-DDEBUG_CHESSBOARD'(nie testowane)
ypnos
1
Jest naprawdę nowy ... w rzeczywistości jest w bardziej nowoczesnym CMake (> 3.11). Ból, który tak trudno jest poznać, kiedy wprowadzono polecenie.
Sandburg,
1
@ Sandburg Możesz otworzyć link do ostatniej dokumentacji: https://cmake.org/cmake/help/v3.17/command/add_compile_definitions.html#command:add_compile_definitionsi zacznij zmieniać numer wersji, aż strona zniknie. To byłaby wersja, w której jeszcze nie istnieje. W następnym ruchu możesz przejść do Whats newsekcji, aby znaleźć nowe polecenie lub funkcję. Więc to nie takie trudne.
Andry
245

Aby to zrobić dla określonego celu, możesz wykonać następujące czynności:

target_compile_definitions(my_target PRIVATE FOO=1 BAR=1)

Powinieneś to zrobić, jeśli budujesz więcej niż jeden cel i nie chcesz, aby wszystkie używały tych samych flag. Zobacz także oficjalną dokumentację na temat definicji_pliku_docelowego .

Jim Hunziker
źródło
1
@JimHunziker Czym się target_compile_definitions(my_target PRIVATE FOO=1)różni set_source_files_properties(foo.cpp PROPERTIES COMPILE_DEFINITIONS -DFOO=1)?
John Strood,
1
@JohnStrood Różnica jest na poziomie zakresu. target_compile_definitionsustawia wartość dla CAŁEGO pliku wykonywalnego / biblioteki, gdzie jako „set_source_files_properties” ustawia wartość tylko dla określonego pliku. Polecenie Później pozwala na kompilację plików w innym języku; tj set_source_files_properties(compile_me_as_objc.c PROPERTIES -x objective-c. : Pamiętaj, że -x objective-ctutaj jest flaga specyficzna dla GCC / Clang.
Julian Kirsch
20

Inne rozwiązania proponowane na tej stronie są przydatne w niektórych wersjach Cmake <3.3.2 . Tutaj rozwiązanie dla wersji, której używam (tj 3.3.2.). Sprawdź wersję swojego Cmake za pomocą $ cmake --versioni wybierz rozwiązanie, które odpowiada Twoim potrzebom. Dokumentację cmake można znaleźć na oficjalnej stronie.

Z CMake w wersji 3.3.2, w celu utworzenia

#define foo

Musiałem użyć:

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

i, aby mieć definicję makra preprocesora, taką jak ta inna:

#define foo=5

linia jest tak zmodyfikowana:

add_definitions(-Dfoo=5)   # <--------HERE THE NEW CMAKE LINE inside CMakeLists.txt
add_executable( ....)
target_link_libraries(....)
Leos313
źródło
4
Według dokumentacji to rozwiązanie jest w rzeczywistości starszym, bardziej przestarzałym podejściem. Pozostałe odpowiedzi oferują bardziej nowoczesne rozwiązania.
squareskittles,
2
Kiedy napisałem odpowiedź, wypróbowałem inne rozwiązanie, ale żadne z nich nie działało.
Leos313,
@squareskittles, jakiś pomysł, dlaczego rozwiązanie drugiej odpowiedzi nie działało poprawnie? CMake daj błędy, jeśli spróbuję
Leos313
1
Jeśli korzystasz z CMake 3.3.2, jak wskazałeś w odpowiedzi, musisz użyć add_definitions()lub target_compile_definitions(). Bardziej nowoczesne polecenie add_compile_definitions()zostało dodane dopiero w CMake 3.12. @ Leos313
squareskittles
1
@squareskittles, aktualizuję odpowiedź, ponownie pisząc to, co napisałem kilka miesięcy temu. Dziękujemy za zwrócenie na to uwagi
Leos313