Tentukan preprocessor macro melalui CMake?

283

Bagaimana cara menetapkan variabel preprosesor melalui CMake?

Kode yang setara akan menjadi #define foo.

Mythli
sumber

Jawaban:

382

Untuk waktu yang lama, CMake memiliki add_definitionsperintah untuk tujuan ini. Namun, baru-baru ini perintah telah digantikan oleh pendekatan berbutir lebih halus (perintah terpisah untuk definisi kompilasi, termasuk direktori, dan opsi kompiler).

Contoh menggunakan add_compile_definitions baru :

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

Atau:

add_compile_definitions(OPENCV_VERSION=${OpenCV_VERSION} WITH_OPENCV2)

Bagian yang baik tentang ini adalah bahwa hal itu menghindari tipu daya kumuh CMake di tempat untuk add_definitions. CMake adalah sistem yang buruk, tetapi mereka akhirnya menemukan kewarasan.

Temukan penjelasan lebih lanjut tentang perintah mana yang digunakan untuk flag kompiler di sini: https://cmake.org/cmake/help/latest/command/add_definitions.html

Demikian juga, Anda dapat melakukan ini per-target seperti yang dijelaskan dalam jawaban Jim Hunziker.

ypnos
sumber
4
Dari halaman yang ditautkan: "Catatan Perintah ini telah digantikan oleh alternatif: Gunakan add_compile_definitions () untuk menambahkan definisi preprocessor." Mungkin jawaban ini perlu diedit?
M.Herzkamp
9
Dalam cmake 3.10.2, add_compile_definitionsmelempar CMake Error at CMakeLists.txt:6 (add_compile_definitions): Unknown CMake command "add_compile_definitions".. Harus digunakan add_compile_options(-D <your-def>)sebagai gantinya.
code_dredd
2
@mannyglover Saya tidak berpikir begitu, tetapi Anda dapat mengatur bendera kompiler dengan -D, sesuatu di sepanjang garis cmake -D CMAKE_CXXFLAGS='-DDEBUG_CHESSBOARD'(tidak diuji)
ypnos
1
Ini benar-benar baru ... sebenarnya ada di More Modern CMake (> 3.11). Menyakitkan sehingga sulit untuk mengetahui kapan suatu perintah diperkenalkan.
Sandburg
1
@Sandburg Anda dapat membuka tautan ke dokumentasi terakhir: https://cmake.org/cmake/help/v3.17/command/add_compile_definitions.html#command:add_compile_definitionsdan mulai mengubah nomor versi ke bawah hingga halaman hilang. Itu akan menjadi versi di mana itu belum ada. Pada langkah selanjutnya Anda dapat pergi ke Whats newbagian untuk menemukan perintah atau fitur baru. Jadi tidak begitu sulit.
Andry
245

Untuk melakukan ini untuk target tertentu, Anda dapat melakukan hal berikut:

target_compile_definitions(my_target PRIVATE FOO=1 BAR=1)

Anda harus melakukan ini jika Anda memiliki lebih dari satu target yang sedang Anda bangun dan Anda tidak ingin mereka semua menggunakan bendera yang sama. Lihat juga dokumentasi resmi tentang target_compile_definitions .

Jim Hunziker
sumber
1
@JimHunziker Apa target_compile_definitions(my_target PRIVATE FOO=1)bedanya set_source_files_properties(foo.cpp PROPERTIES COMPILE_DEFINITIONS -DFOO=1)?
John Strood
1
@ JohnStrood Perbedaannya adalah pada tingkat ruang lingkup. target_compile_definitionsset nilai untuk WHOLE executable / library, di mana 'set_source_files_properties` menetapkan nilai hanya untuk file yang ditentukan. Perintah terakhir memungkinkan file dikompilasi menggunakan bahasa yang berbeda; yaitu: set_source_files_properties(compile_me_as_objc.c PROPERTIES -x objective-c. Perhatikan bahwa -x objective-cini adalah flag khusus untuk GCC / Dentang.
Julian Kirsch
20

Solusi lain yang diusulkan pada halaman ini berguna beberapa versi Cmake <3.3.2 . Di sini solusi untuk versi yang saya gunakan (yaitu, 3.3.2). Periksa versi Cmake Anda dengan menggunakan $ cmake --versiondan memilih solusi yang sesuai dengan kebutuhan Anda. The dokumentasi cmake dapat ditemukan di halaman resmi.

Dengan CMake versi 3.3.2, untuk membuat

#define foo

Saya perlu menggunakan:

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

dan, untuk memiliki definisi makro preprosesor seperti yang lain ini:

#define foo=5

garis sangat dimodifikasi:

add_definitions(-Dfoo=5)   # <--------HERE THE NEW CMAKE LINE inside CMakeLists.txt
add_executable( ....)
target_link_libraries(....)
Leos313
sumber
4
Per dokumentasi , solusi ini sebenarnya lebih tua, pendekatan yang lebih kuno. Jawaban lain menawarkan solusi yang lebih modern.
squareskittles
2
Ketika saya menulis jawabannya, saya memang mencoba solusi yang lain tetapi tidak ada yang berhasil.
Leos313
@ Squareskittles, tahu mengapa solusi dari jawaban lain tidak bekerja dengan benar? CMake memberikan kesalahan jika saya mencobanya
Leos313
1
Jika Anda menggunakan CMake 3.3.2, seperti yang Anda tunjukkan dalam jawaban Anda, Anda harus menggunakan add_definitions()atau target_compile_definitions(). Perintah yang lebih modern add_compile_definitions(),, tidak ditambahkan sampai CMake 3.12. @ Leos313
squareskittles
1
@ Squareskittles, saya memperbarui jawabannya, menulis ulang apa yang saya tulis beberapa mounths lalu. Terima kasih telah menunjukkan ini
Leos313