चर सेट और उपयोग करने के लिए CMake सिंटैक्स क्या है?


168

अगली बार जब मैं CMake का उपयोग करता हूं तो मैं इसे अपने लिए एक अनुस्मारक के रूप में पूछ रहा हूं। यह कभी नहीं चिपकता है, और Google परिणाम महान नहीं होते हैं।

CMake में वेरिएबल्स को सेट और उपयोग करने के लिए सिंटैक्स क्या है?

जवाबों:


281

सीएमके स्क्रिप्ट लिखते समय सिंटैक्स के बारे में आपको बहुत कुछ जानने की जरूरत है और सीएमके में चर का उपयोग कैसे करें।

सिंटेक्स

स्ट्रिंग्स का उपयोग 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})

दस्तावेज़ीकरण

स्कोप या "मेरे चर का क्या मूल्य है?"

पहले "सामान्य चर" और चीजें हैं जो आपको उनके दायरे के बारे में जानने की जरूरत है:

  • सामान्य चर के दिखाई दे रहे हैं CMakeLists.txtवे में और सब कुछ कहा जाता है सेट कर रहे हैं वहाँ से ( add_subdirectory(), include(), macro()और function())।
  • add_subdirectory()और function()आदेश, विशेष कर रहे हैं, क्योंकि वे खोलने-अप अपने स्वयं के दायरे।
    • मतलब चर set(...)वहां केवल दिखाई देते हैं और वे उस स्तर के सभी सामान्य चर की एक प्रति बनाते हैं, जिन्हें वे कहा जाता है (जिन्हें मूल गुंजाइश कहा जाता है)।
    • इसलिए यदि आप एक उप-निर्देशिका या फ़ंक्शन में हैं, तो आप पेरेंट स्कोप में पहले से मौजूद वैरिएबल को संशोधित कर सकते हैं set(... PARENT_SCOPE)
    • आप फ़ंक्शन पैरामीटर के रूप में चर नाम को पारित करके कार्यों में इसका उपयोग कर सकते हैं। एक उदाहरण function(xyz _resultVar)स्थापित करना होगाset(${_resultVar} 1 PARENT_SCOPE)
  • दूसरी ओर आप include()या macro()स्क्रिप्ट में जो कुछ भी सेट करते हैं, वे चर को सीधे उस दायरे में संशोधित करेंगे जहां से उन्हें बुलाया जाता है।

दूसरा "ग्लोबल वैरिएबल कैश" है। कैश के बारे में जानने के लिए आपको जिन चीजों की आवश्यकता है:

  • यदि दिए गए नाम के साथ कोई सामान्य चर वर्तमान दायरे में परिभाषित नहीं किया गया है, तो CMake एक मिलान कैश प्रविष्टि के लिए दिखेगा।
  • कैश मान CMakeCache.txtआपके बाइनरी आउटपुट डायरेक्टरी में फ़ाइल में संग्रहीत हैं ।
  • Cache के मान उत्पन्न होने से पहले CMake के GUI एप्लिकेशन में संशोधित किए जा सकते हैं। इसलिए वे - सामान्य चर की तुलना में - ए typeऔर ए हैं docstring। मैं आमतौर पर GUI का उपयोग नहीं करता हूं इसलिए मैं set(... CACHE INTERNAL "")अपने वैश्विक और निरंतर मूल्यों को निर्धारित करने के लिए उपयोग करता हूं।

    कृपया ध्यान दें कि INTERNALकैश वेरिएबल टाइप इंप्लीमेंट करता हैFORCE

  • यदि आप set(... CACHE ... FORCE)सिंटैक्स का उपयोग करते हैं तो एक CMake स्क्रिप्ट में आप केवल मौजूदा कैश प्रविष्टियों को बदल सकते हैं । यह व्यवहार उदाहरण के लिए CMake द्वारा ही किया जाता है, क्योंकि यह आम तौर पर Cache प्रविष्टियों को स्वयं बाध्य नहीं करता है और इसलिए आप इसे दूसरे मान से पूर्व-परिभाषित कर सकते हैं।

  • आप सिंटैक्स के साथ कैशे में प्रविष्टियाँ सेट करने के लिए कमांड लाइन का उपयोग कर सकते हैं cmake -D var:type=value, बस cmake -D var=valueया साथ cmake -C CMakeInitialCache.cmake
  • आप Cache में प्रविष्टियों को अनसेट कर सकते हैं unset(... CACHE)

कैश वैश्विक है और आप उन्हें अपने CMake स्क्रिप्ट में कहीं भी सेट कर सकते हैं। लेकिन मैं आपको दो बार सोचने की सलाह दूंगा कि कैश वैरिएबल का उपयोग कहां किया जाए (वे वैश्विक हैं और वे लगातार हैं)। मैं आमतौर पर अपने स्वयं के गैर-निरंतर वैश्विक चर को परिभाषित करने के लिए set_property(GLOBAL PROPERTY ...)और set_property(GLOBAL APPEND PROPERTY ...)वाक्यविन्यास पसंद करता हूं।

परिवर्तनीय नुकसान और "चर परिवर्तनों को डीबग कैसे करें?"

नुकसान से बचने के लिए आपको निम्नलिखित चर के बारे में जानना चाहिए:

  • स्थानीय चर कैश्ड वैरिएबल छिपाते हैं यदि दोनों का नाम समान है
  • find_...आदेशों - सफल अगर - कैश्ड चर के रूप में उनके परिणाम लिख सकता हूं "इसलिए कोई कॉल फिर से खोज करेंगे कि"
  • CMake में सूचियाँ अर्धविराम सीमांकक के साथ केवल तार हैं और इसलिए उद्धरण-चिह्न महत्वपूर्ण हैं
    • set(MyVar a b c)है "a;b;c"और set(MyVar "a b c")है"a b c"
    • सिफारिश यह है कि जब आप सूची के रूप में सूची देना चाहते हैं तो आप हमेशा एक अपवाद के साथ उद्धरण चिह्नों का उपयोग करते हैं
    • आम तौर पर list()सूचियों को संभालने के लिए कमांड पसंद करते हैं
  • ऊपर वर्णित पूरी गुंजाइश मुद्दा। विशेष रूप से इसके functions()बजाय इसका उपयोग करने की अनुशंसा की जाती है macros()क्योंकि आप अपने स्थानीय चर को मूल दायरे में नहीं दिखाना चाहते हैं।
  • CMake द्वारा उपयोग किए जाने वाले बहुत सारे चर कॉल project()और enable_language()कॉल के साथ सेट किए गए हैं । इसलिए उन आदेशों का उपयोग करने से पहले कुछ चर निर्धारित करना महत्वपूर्ण हो सकता है।
  • पर्यावरण चर भिन्न हो सकते हैं जहां सीएमके ने वातावरण बनाया और जब उपयोग करने के लिए मेक फाइलें डाली जाती हैं।
    • एक पर्यावरण चर में परिवर्तन पीढ़ी प्रक्रिया को फिर से ट्रिगर नहीं करता है।
    • विशेष रूप से एक उत्पन्न आईडीई वातावरण आपकी कमांड लाइन से भिन्न हो सकता है, इसलिए यह आपके पर्यावरण चर को किसी चीज़ में स्थानांतरित करने की सिफारिश की जाती है।

कभी-कभी केवल डीबगिंग चर मदद करता है। निम्नलिखित आपकी मदद कर सकते हैं:

  • बस कमांड printfका उपयोग करके पुरानी डिबगिंग शैली का उपयोग करें message()सीएमके के साथ भेजे गए मॉड्यूल का उपयोग करने के लिए भी कुछ तैयार हैं: CMakePrintHelpers.cmake , CMakePrintSystemInformation.cmake
  • CMakeCache.txtअपने बाइनरी आउटपुट डायरेक्टरी में फ़ाइल में देखें। यह फ़ाइल तब भी जेनरेट होती है जब आपके मेक इनवायरमेंट की वास्तविक पीढ़ी विफल हो जाती है।
  • चर / घड़ी () का उपयोग करके देखें कि आपके चर कहाँ पढ़े / लिखे / निकाले गए हैं।
  • निर्देशिका गुण CACHE_VARIABLES और VARIABLES में देखें
  • cmake --trace ...सीएमके की पूर्ण पार्सिंग प्रक्रिया को देखने के लिए कॉल करें। यह अंतिम रिज़र्व की तरह है, क्योंकि यह बहुत अधिक आउटपुट उत्पन्न करता है।

विशेष सिंटेक्स

  • पर्यावरण चर
    • आप पर्यावरण चर पढ़ $ENV{...}और लिख सकते हैंset(ENV{...} ...)
  • जेनरेटर एक्सप्रेशंस
    • जनरेटर के भावों $<...>का मूल्यांकन केवल तब किया जाता है जब सीएमके का जनरेटर मेक एनवायरनमेंट लिखता है (यह सामान्य वेरिएबल्स की तुलना करता है जो "पार्सर द्वारा" इन-प्लेस "प्रतिस्थापित किए जाते हैं)
    • संकलक / लिंकर कमांड लाइनों में और बहु-विन्यास वातावरण में बहुत आसान उदाहरण
  • संदर्भ
    • साथ ${${...}}आप एक चर में चर नाम देना और उसकी सामग्री को संदर्भित कर सकते।
    • अक्सर फ़ंक्शन / मैक्रो पैरामीटर के रूप में एक चर नाम देते समय उपयोग किया जाता है।
  • लगातार मान ( if()आदेश देखें )
    • साथ if(MyVariable)आप सीधे सही / गलत के लिए एक चर (संलग्न की कोई आवश्यकता नहीं यहाँ जाँच कर सकते हैं ${...})
    • यह सच है निरंतर है अगर 1, ON, YES, TRUE, Y, या एक गैर शून्य संख्या।
    • झूठी निरंतर है अगर 0, OFF, NO, FALSE, N, IGNORE, NOTFOUND, खाली स्ट्रिंग, या प्रत्यय में समाप्त हो जाती है -NOTFOUND
    • इस सिंटैक्स का उपयोग अक्सर किसी चीज़ के लिए किया जाता है if(MSVC), लेकिन यह किसी ऐसे व्यक्ति के लिए भ्रमित हो सकता है जो इस सिंटैक्स शॉर्टकट को नहीं जानता है।
  • पुनरावर्ती प्रतिस्थापन
    • आप चर का उपयोग करके चर नामों का निर्माण कर सकते हैं। सीएमके द्वारा चर को प्रतिस्थापित करने के बाद, यह फिर से जाँच करेगा कि क्या परिणाम स्वयं एक चर है। यह बहुत ही शक्तिशाली विशेषता है जिसका उपयोग CMake में ही किया जाता है। जैसे टेम्पलेट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)
    • अच्छी खबर यह है कि यह सीएमके 3.1 में नीति सीएमपी 0054 की शुरुआत के साथ तय किया गया था । मैं हमेशा cmake_policy(SET CMP0054 NEW)"केवल if()तर्क या व्याख्या के रूप में तर्क की व्याख्या करते समय निर्धारित करने के लिए सेट करूंगा ।"
  • option()आदेश
    • मुख्य रूप से सिर्फ कैश्ड स्ट्रिंग्स जो केवल हो सकती हैं ONया OFFवे कुछ विशेष हैंडलिंग जैसे उदाहरण पर निर्भरता की अनुमति देते हैं
    • लेकिन जागरूक रहें , कमांड के optionसाथ गलती न करें set। दिए गए मूल्य optionवास्तव में केवल "प्रारंभिक मूल्य" है (पहले कॉन्फ़िगरेशन चरण के दौरान कैश में एक बार स्थानांतरित) और बाद में सीएमके के जीयूआई के माध्यम से उपयोगकर्ता द्वारा बदला जाना है ।

संदर्भ


जब मैं उपयोग कर if ("${MyString}" ...)रहा हूँ तो मैं चेतावनी देख रहा हूँ Policy CMP0054 is not set: Only interpret if() arguments as variables or keywords when unquoted:। उदाहरण के लिए, 367 बनाएँ देखें । कोई विचार?
jww

और अयोग्य ठहराए ${MyString}जाने पर "यदि तर्क दिए गए ..." के लिए त्रुटियों का एक समूह होता है , जैसे कि सीमेक त्रुटि यदि: "यदि दिए गए तर्कों" के बाद परांठे, "नहीं", "समानताएं" और इसी तरह
jww

@jww चेतावनी का मतलब है कि MyStringएक चर नाम है जिसमें फिर से डी- रेफर किया जाएगा। मेरा मानना ​​है कि कोई भी वास्तव में उस OLDव्यवहार को नहीं चाहता है । तो मेरे दृष्टिकोण से इसकी पूरी तरह से सुरक्षित और पिछड़ी संगत सिर्फ नीति निर्धारित करने के CMP0054लिए NEW( यहाँ चर्चा देखें )।
फ्लोरियन

@jww और उन समस्याओं / चेतावनियों से बचने का सबसे सुरक्षित तरीका सिर्फ if (MyString ...)यह करना है (यदि यह आपका कोड चेतावनी दे रहा है)।
फ्लोरियन

धन्यवाद। हमने सभी घटनाओं को हटा दिया ${MyString}और इसे बदल दिया MyString(या मेरा मानना ​​है कि हमने उन सभी को हटा दिया)। अभी भी कोई खुशी नहीं: 372 बनाएँ । बकवास हमारे कोड से भी नहीं आ रहा है। यह सीएमके से आता हुआ प्रतीत होता है। लाइन 283 है if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
12

18

जल्दी और गंदे होने के लिए यहां कुछ बुनियादी उदाहरण हैं।

एक आइटम चर

चर सेट करें:

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}")

चरों पर सीएमके डॉक्स


1

$ENV{FOO}उपयोग के लिए, जहां FOOपर्यावरण चर से उठाया जा रहा है। अन्यथा के रूप में उपयोग करें ${FOO}, जहां FOOकुछ अन्य चर है। सेटिंग के लिए, SET(FOO "foo")CMake में उपयोग किया जाएगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.