ฉันขอสิ่งนี้เป็นเครื่องเตือนใจตัวเองในครั้งต่อไปที่ฉันใช้ CMake มันไม่ติดและผลลัพธ์ของ Google ก็ไม่ได้ยอดเยี่ยม
ไวยากรณ์ในการตั้งค่าและใช้ตัวแปรใน CMake คืออะไร
ฉันขอสิ่งนี้เป็นเครื่องเตือนใจตัวเองในครั้งต่อไปที่ฉันใช้ CMake มันไม่ติดและผลลัพธ์ของ Google ก็ไม่ได้ยอดเยี่ยม
ไวยากรณ์ในการตั้งค่าและใช้ตัวแปรใน CMake คืออะไร
คำตอบ:
เมื่อเขียนสคริปต์ของ CMake มีจำนวนมากที่คุณต้องรู้เกี่ยวกับไวยากรณ์และวิธีการใช้ตัวแปรใน CMake
เงื่อนไขการใช้set()
:
set(MyString "Some Text")
set(MyStringWithVar "Some other Text: ${MyString}")
set(MyStringWithQuot "Some quote: \"${MyStringWithVar}\"")
หรือด้วยstring()
:
string(APPEND MyStringWithContent " ${MyString}")
รายการที่ใช้set()
:
set(MyList "a" "b" "c")
set(MyList ${MyList} "d")
หรือดีกว่าด้วยlist()
:
list(APPEND MyList "a" "b" "c")
list(APPEND MyList "d")
รายการชื่อไฟล์:
set(MySourcesList "File.name" "File with Space.name")
list(APPEND MySourcesList "File.name" "File with Space.name")
add_excutable(MyExeTarget ${MySourcesList})
set()
คำสั่งCMakestring()
คำสั่งCMakelist()
คำสั่งCMakeอันดับแรกมี "ตัวแปรปกติ" และสิ่งที่คุณต้องรู้เกี่ยวกับขอบเขต:
CMakeLists.txt
พวกเขาจะตั้งอยู่ในและทุกอย่างที่เรียกว่าจากที่นั่น ( add_subdirectory()
, include()
, macro()
และfunction()
)add_subdirectory()
และfunction()
คำสั่งเป็นพิเศษเพราะพวกเขาเปิดขึ้นขอบเขตของตัวเอง
set(...)
มีให้เห็นได้เฉพาะที่นั่นและทำสำเนาของตัวแปรปกติทั้งหมดของระดับขอบเขตที่ถูกเรียกจาก (เรียกว่าขอบเขตหลัก)set(... PARENT_SCOPE)
function(xyz _resultVar)
เป็นการตั้งค่าset(${_resultVar} 1 PARENT_SCOPE)
include()
หรือmacro()
สคริปต์จะปรับเปลี่ยนตัวแปรโดยตรงในขอบเขตที่พวกเขาจะถูกเรียกจากประการที่สองคือ "แคชตัวแปรส่วนกลาง" สิ่งที่คุณต้องรู้เกี่ยวกับแคช:
CMakeCache.txt
ไฟล์ในไดเรกทอรีเอาต์พุตไบนารีของคุณค่าใน Cache สามารถแก้ไขได้ในแอปพลิเคชันGUI ของ CMakeก่อนที่จะถูกสร้างขึ้น ดังนั้นพวกเขาจึง - เมื่อเทียบกับตัวแปรปกติ - มีและtype
docstring
ปกติแล้วฉันจะไม่ใช้ GUI ดังนั้นฉันจึงใช้set(... CACHE INTERNAL "")
เพื่อตั้งค่าโกลบอลและค่าที่ทนได้ของฉัน
โปรดทราบว่าINTERNAL
ประเภทตัวแปรแคชนั้นแปลว่าFORCE
ในสคริปต์ CMake คุณสามารถเปลี่ยนรายการแคชที่มีอยู่หากคุณใช้set(... CACHE ... FORCE)
ไวยากรณ์ พฤติกรรมนี้มีการใช้งานเช่นโดย CMake เองเพราะปกติแล้วจะไม่บังคับให้รายการแคชเองดังนั้นคุณจึงสามารถกำหนดค่าล่วงหน้าด้วยค่าอื่นได้
cmake -D var:type=value
เพียงหรือcmake -D var=value
cmake -C CMakeInitialCache.cmake
unset(... CACHE)
รายการในแคชด้วยCache นั้นเป็นสากลและคุณสามารถตั้งค่าได้แทบทุกที่ในสคริปต์ CMake ของคุณ แต่ฉันขอแนะนำให้คุณคิดสองครั้งเกี่ยวกับตำแหน่งที่จะใช้ตัวแปร Cache (เป็นแบบโกลบอลและแบบถาวร) ปกติแล้วฉันชอบset_property(GLOBAL PROPERTY ...)
และset_property(GLOBAL APPEND PROPERTY ...)
ไวยากรณ์เพื่อกำหนดตัวแปรทั่วโลกของฉันเองไม่ทน
เพื่อหลีกเลี่ยงข้อผิดพลาดคุณควรทราบข้อมูลเกี่ยวกับตัวแปรดังต่อไปนี้:
find_...
คำสั่ง - ถ้าประสบความสำเร็จ - อย่าเขียนผลของพวกเขาเป็นตัวแปรที่เก็บไว้ชั่วคราว "เพื่อให้ไม่มีการโทรจะค้นหาอีกครั้ง"set(MyVar a b c)
เป็น"a;b;c"
และset(MyVar "a b c")
เป็น"a b c"
list()
คำสั่งสำหรับการจัดการรายการfunctions()
แทนmacros()
เพราะคุณไม่ต้องการให้ตัวแปรในเครื่องของคุณปรากฏในขอบเขตพาเรนต์project()
และการenable_language()
เรียก ดังนั้นการตั้งค่าตัวแปรให้สำคัญก่อนที่จะใช้คำสั่งเหล่านั้นบางครั้งการดีบักตัวแปรช่วยเท่านั้น ต่อไปนี้อาจช่วยคุณได้:
printf
รูปแบบการดีบักแบบเก่าโดยใช้message()
คำสั่ง นอกจากนี้ยังมีบางส่วนที่พร้อมใช้งานโมดูลที่มาพร้อมกับ CMake เอง: CMakePrintHelpers.cmake , CMakePrintSystemInformation.cmakeCMakeCache.txt
ไฟล์ในไดเรกทอรีเอาต์พุตไบนารีของคุณ ไฟล์นี้จะถูกสร้างขึ้นหากการสร้างสภาพแวดล้อมการสร้างของคุณล้มเหลวcmake --trace ...
เพื่อดูกระบวนการแยกวิเคราะห์ที่สมบูรณ์ของ CMake นั่นคือการสำรองครั้งสุดท้ายเพราะมันสร้างผลผลิตจำนวนมาก$ENV{...}
และเขียนset(ENV{...} ...)
ตัวแปรสภาพแวดล้อมได้$<...>
จะได้รับการประเมินก็ต่อเมื่อตัวสร้างของ CMake เขียนสภาพแวดล้อมที่สร้าง (เปรียบเทียบกับตัวแปรปกติที่ถูกแทนที่ "in-place" โดยตัวแยกวิเคราะห์)${${...}}
คุณสามารถให้ชื่อตัวแปรในตัวแปรและอ้างอิงเนื้อหาif()
คำสั่ง)
if(MyVariable)
คุณโดยตรงสามารถตรวจสอบตัวแปรสำหรับ / เท็จจริง (ไม่จำเป็นต้องที่นี่สำหรับการปิดล้อม${...}
)1
, ON
, YES
, TRUE
, Y
หรือจำนวนไม่เป็นศูนย์0
, OFF
, NO
, FALSE
, N
, IGNORE
, NOTFOUND
, -NOTFOUND
สตริงที่ว่างเปล่าหรือปลายในคำต่อท้ายif(MSVC)
แต่อาจทำให้สับสนสำหรับคนที่ไม่รู้จักทางลัดไวยากรณ์นี้set(CMAKE_${lang}_COMPILER ...)
if()
คำสั่ง นี่คือตัวอย่างในกรณีที่CMAKE_CXX_COMPILER_ID
เป็น"MSVC"
และMSVC
เป็น"1"
:
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
เป็นจริงเพราะมันประเมิน if("1" STREQUAL "1")
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
เป็นเท็จเพราะมันประเมิน if("MSVC" STREQUAL "1")
if(MSVC)
cmake_policy(SET CMP0054 NEW)
เป็น "ตีความif()
อาร์กิวเมนต์เท่านั้นเป็นตัวแปรหรือคำหลักเมื่อไม่ได้อ้างอิง"option()
คำสั่ง
ON
หรือหรือOFF
พวกเขาให้การจัดการพิเศษบางอย่างเช่นการอ้างอิงoption
กับset
คำสั่ง คุ้มค่าให้กับoption
มันเพียง "ค่าเริ่มต้น" (โอนครั้งเดียวไปยังแคชในระหว่างขั้นตอนการตั้งค่าครั้งแรก) และมีความหมายหลังจากนั้นก็จะมีการเปลี่ยนแปลงโดยผู้ใช้ผ่านCMake ของ GUI${MyString}
นำไปสู่พวงของข้อผิดพลาดสำหรับ"ถ้าข้อโต้แย้งให้ ..."เหมือนCMake ข้อผิดพลาดถ้าอยู่ใกล้กับ:“ถ้าข้อโต้แย้งให้” ตามด้วยวงเล็บ“ไม่”,“เท่ากับ” และที่คล้ายกัน
if (MyString ...)
(ถ้ารหัสของคุณเป็นคำเตือน)
ต่อไปนี้เป็นตัวอย่างพื้นฐานในการเริ่มต้นอย่างรวดเร็วและสกปรก
ตั้งค่าตัวแปร:
SET(INSTALL_ETC_DIR "etc")
ใช้ตัวแปร:
SET(INSTALL_ETC_CROND_DIR "${INSTALL_ETC_DIR}/cron.d")
ตั้งค่าตัวแปร:
SET(PROGRAM_SRCS
program.c
program_utils.c
a_lib.c
b_lib.c
config.c
)
ใช้ตัวแปร:
add_executable(program "${PROGRAM_SRCS}")
$ENV{FOO}
สำหรับการใช้งานที่FOO
มีการรับจากตัวแปรสภาพแวดล้อม มิฉะนั้นจะใช้เป็น${FOO}
, ซึ่งFOO
เป็นตัวแปรอื่น ๆ สำหรับการตั้งค่าSET(FOO "foo")
จะใช้ใน CMake
if ("${MyString}" ...)
ฉันเห็นคำเตือน:Policy CMP0054 is not set: Only interpret if() arguments as variables or keywords when unquoted
. ดูตัวอย่างเช่นสร้าง 367 ความคิดใด ๆ