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.txt
mereka 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.txt
file 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 type
dan a docstring
. Saya biasanya tidak menggunakan GUI jadi saya gunakan set(... CACHE INTERNAL "")
untuk mengatur nilai global dan persisten saya.
Harap perhatikan bahwa INTERNAL
jenis 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=value
atau 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:
printf
gaya 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_ID
ada "MSVC"
dan MSVC
tidak "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
ON
atau OFF
dan mereka memungkinkan penanganan khusus seperti ketergantungan misalnyaoption
dengan set
perintah. Nilai yang diberikan option
adalah 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 .
MyString
memang berisi nama variabel yang kemudian akan di-referensikan lagi. Saya percaya bahwa tidak ada yang benar-benar menginginkan OLD
perilaku itu. Jadi dari sudut pandang saya ini benar-benar aman dan kompatibel untuk hanya mengatur kebijakan CMP0054
untuk 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?