Jawaban:
Saat menulis skrip CMake ada banyak yang perlu Anda ketahui tentang sintaks dan cara menggunakan variabel di CMake.
String menggunakan set():
set(MyString "Some Text")set(MyStringWithVar "Some other Text: ${MyString}")set(MyStringWithQuot "Some quote: \"${MyStringWithVar}\"")Atau dengan string():
string(APPEND MyStringWithContent " ${MyString}")Daftar menggunakan set():
set(MyList "a" "b" "c")set(MyList ${MyList} "d")Atau lebih baik dengan list():
list(APPEND MyList "a" "b" "c")list(APPEND MyList "d")Daftar Nama File:
set(MySourcesList "File.name" "File with Space.name")list(APPEND MySourcesList "File.name" "File with Space.name")add_excutable(MyExeTarget ${MySourcesList})set()Perintah CMakestring()Perintah CMakelist()Perintah CMakePertama ada "Variabel Normal" dan hal-hal yang perlu Anda ketahui tentang ruang lingkup mereka:
CMakeLists.txtmereka ditetapkan dalam dan segala sesuatu yang disebut dari sana ( add_subdirectory(), include(), macro()dan function()).add_subdirectory()dan function()perintah yang khusus, karena mereka membuka-up lingkup mereka sendiri.
set(...)hanya ada yang terlihat di sana dan mereka membuat salinan dari semua variabel normal dari tingkat lingkup tempat mereka dipanggil (disebut lingkup orangtua).set(... PARENT_SCOPE)function(xyz _resultVar)adalah pengaturanset(${_resultVar} 1 PARENT_SCOPE)include()atau macro()skrip akan mengubah variabel langsung dalam lingkup tempat mereka dipanggil.Yang kedua adalah "Global Variables Cache". Hal-hal yang perlu Anda ketahui tentang Cache:
CMakeCache.txtfile di direktori output biner Anda.Nilai-nilai di Cache dapat dimodifikasi dalam aplikasi GUI CMake sebelum dihasilkan. Oleh karena itu mereka - dibandingkan dengan variabel normal - memiliki a typedan a docstring. Saya biasanya tidak menggunakan GUI jadi saya gunakan set(... CACHE INTERNAL "")untuk mengatur nilai global dan persisten saya.
Harap perhatikan bahwa INTERNALjenis variabel cache tidak menyiratkanFORCE
Dalam skrip CMake Anda hanya dapat mengubah entri Cache yang ada jika Anda menggunakan set(... CACHE ... FORCE)sintaks. Perilaku ini digunakan misalnya oleh CMake itu sendiri, karena biasanya tidak memaksa entri Cache itu sendiri dan oleh karena itu Anda dapat menentukan sebelumnya dengan nilai lain.
cmake -D var:type=value, hanya cmake -D var=valueatau dengan cmake -C CMakeInitialCache.cmake.unset(... CACHE) .Cache bersifat global dan Anda dapat mengaturnya di mana saja di skrip CMake Anda. Tapi saya akan merekomendasikan Anda berpikir dua kali tentang di mana menggunakan variabel Cache (mereka bersifat global dan mereka tahan). Saya biasanya lebih suka set_property(GLOBAL PROPERTY ...)danset_property(GLOBAL APPEND PROPERTY ...) sintaks untuk mendefinisikan variabel global non-persisten saya sendiri.
Untuk menghindari jebakan Anda harus tahu yang berikut tentang variabel:
find_... perintah - jika berhasil - melakukan menulis hasil mereka sebagai variabel cache "sehingga tidak ada panggilan akan mencari lagi"set(MyVar a b c)adalah "a;b;c"dan set(MyVar "a b c")sekarang"a b c"list()perintah untuk menangani daftarfunctions()daripada macros()karena Anda tidak ingin variabel lokal Anda muncul di lingkup induk.project()dan enable_language()panggilan. Jadi bisa jadi penting untuk mengatur beberapa variabel sebelum perintah itu digunakan.Terkadang hanya variabel debug yang membantu. Berikut ini dapat membantu Anda:
printfgaya debugging lama dengan menggunakan message()perintah. Ada juga beberapa modul siap pakai yang dikirimkan bersama CMake: CMakePrintHelpers.cmake , CMakePrintSystemInformation.cmakeCMakeCache.txt file di direktori output biner Anda. File ini bahkan dihasilkan jika generasi aktual dari lingkungan make Anda gagal.cmake --trace ...untuk melihat proses parsing lengkap CMake. Itu semacam cadangan terakhir, karena menghasilkan banyak output.$ENV{...}dan menulis set(ENV{...} ...)variabel lingkungan$<...>hanya dievaluasi ketika generator CMake menulis lingkungan make (perbandingannya dengan variabel normal yang diganti "di tempat" oleh parser)${${...}}Anda dapat memberikan nama variabel dalam variabel dan referensi kontennya.if()perintah)
if(MyVariable)Anda dapat langsung memeriksa variabel benar / salah (tidak perlu di sini untuk melampirkan ${...})1, ON, YES, TRUE, Y, atau nomor non-nol.0, OFF, NO, FALSE, N, IGNORE, NOTFOUND, string kosong, atau berakhir di akhiran -NOTFOUND.if(MSVC), tetapi dapat membingungkan bagi seseorang yang tidak mengetahui pintasan sintaksis ini.set(CMAKE_${lang}_COMPILER ...)if()perintah. Berikut adalah contoh di mana CMAKE_CXX_COMPILER_IDada "MSVC"dan MSVCtidak "1":
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") itu benar, karena mengevaluasi if("1" STREQUAL "1")if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") salah, karena mengevaluasi ke if("MSVC" STREQUAL "1")if(MSVC)cmake_policy(SET CMP0054 NEW)"hanya menafsirkan if()argumen sebagai variabel atau kata kunci ketika tidak dikutip."option()perintah
ONatau OFFdan mereka memungkinkan penanganan khusus seperti ketergantungan misalnyaoptiondengan setperintah. Nilai yang diberikan optionadalah benar-benar hanya "nilai awal" (ditransfer satu kali ke cache selama langkah konfigurasi pertama) dan kemudian dimaksudkan untuk diubah oleh pengguna melalui GUI CMake .${MyString}mengarah ke sekelompok kesalahan untuk "jika diberikan argumen ..." seperti kesalahan CMake dekat jika: "jika diberikan argumen" diikuti oleh paranthes, "TIDAK", "EQUALS" dan sejenisnya .
MyStringmemang berisi nama variabel yang kemudian akan di-referensikan lagi. Saya percaya bahwa tidak ada yang benar-benar menginginkan OLDperilaku itu. Jadi dari sudut pandang saya ini benar-benar aman dan kompatibel untuk hanya mengatur kebijakan CMP0054untuk NEW(lihat pembahasan di sini ).
if (MyString ...)(jika kode Anda yang memberi peringatan).
${MyString}dan menggantinya dengan MyString(atau saya percaya kami menghapus semuanya). Masih tidak ada sukacita: Bangun 372 . Omong kosong itu bahkan tidak berasal dari kode kita. Tampaknya berasal dari CMake. Jalur 283 adalah if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC").
Berikut adalah beberapa contoh dasar untuk memulai dengan cepat dan kotor.
Setel variabel:
SET(INSTALL_ETC_DIR "etc")
Gunakan variabel:
SET(INSTALL_ETC_CROND_DIR "${INSTALL_ETC_DIR}/cron.d")
Setel variabel:
SET(PROGRAM_SRCS
program.c
program_utils.c
a_lib.c
b_lib.c
config.c
)
Gunakan variabel:
add_executable(program "${PROGRAM_SRCS}")
if ("${MyString}" ...)saya peringatan melihat:Policy CMP0054 is not set: Only interpret if() arguments as variables or keywords when unquoted. Lihat, misalnya, Bangun 367 . Ada ide?