CMake में कई लाइनों में स्ट्रिंग्स को कैसे विभाजित करें?


96

मेरे पास आमतौर पर मेरी परियोजना में एक नीति है, कभी भी टेक्स्ट फ़ाइलों में रेखाएं नहीं बनती हैं जो कि रेखा की लंबाई 80 से अधिक हो, इसलिए वे सभी प्रकार के संपादकों (आप सौदा जानते हैं) में आसानी से संपादन योग्य हैं। लेकिन CMake के साथ मुझे यह समस्या आती है कि मुझे नहीं पता कि एक बड़ी लाइन से बचने के लिए एक साधारण स्ट्रिंग को कई लाइनों में कैसे विभाजित किया जाए। इस मूल कोड पर विचार करें:

set(MYPROJ_VERSION_MAJOR "1")
set(MYPROJ_VERSION_MINOR "0")
set(MYPROJ_VERSION_PATCH "0")
set(MYPROJ_VERSION_EXTRA "rc1")
set(MYPROJ_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-${VERSION_EXTRA}")

यह पहले से ही 80 लाइन की सीमा को समाप्त करता है। तो मैं वर्बोज़ (एकाधिक list(APPEND ...)या इस तरह) के बिना सीएमके में एक लाइन को कई लाइनों में कैसे तोड़ूँ ?

जवाबों:


89

CMake 3.0 और नए के लिए अद्यतन :

लाइन निरंतरता संभव है \। देख cmake-3.0-डॉक

message("\
This is the first line of a quoted argument. \
In fact it is the only line but since it is long \
the source code uses line continuation.\
")

CMake संस्करणों की उपलब्धता:

डेबियन व्हीज़ी (2013): 2.8.9
डेबियन व्हीज़ी -बैकपोर्ट: 2.8.11
डेबियन जेसी (2015): 3.0.2
उबंटू 14.04 (एलटीएस): 2.8.12
उबंटू 15.04: 3.0.2
मैक ओएसएक्स: सेमीके-थ्री होमब्रे , macports और फिंक
विंडोज: cmake -3 के माध्यम से उपलब्ध Chocolatey


20
CMake 3.0 दृष्टिकोण के साथ समस्या यह है कि यह इंडेंटेशन की अनदेखी नहीं करता है। जिसका मतलब है कि मल्टी-लाइन स्ट्रिंग्स को बाकी कोड के साथ इंडेंट नहीं किया जा सकता है।
void.pointer

@ void.pointer मैं एक ही समस्या में भाग गया, क्या आपने पता लगाया कि मल्टी-लाइन के साथ कैसे इंडेंट करें?
user3667089

इसके अलावा अगर इंडेंटेशन का उपयोग करना चाहते हैं और 80 char की सीमा है तो दूसरा तरीका इस तरह से है: <code> संदेश ("यह चर का मूल्य है:" <br> "$ {varValue}") </ code>
मुनसिंह

54

3.0 और नए सीएमके

string(CONCAT)कमांड का उपयोग करें :

set(MYPROJ_VERSION_MAJOR "1")
set(MYPROJ_VERSION_MINOR "0")
set(MYPROJ_VERSION_PATCH "0")
set(MYPROJ_VERSION_EXTRA "rc1")
string(CONCAT MYPROJ_VERSION "${MYPROJ_VERSION_MAJOR}"
                             ".${MYPROJ_VERSION_MINOR}"
                             ".${MYPROJ_VERSION_PATCH}"
                             "-${MYPROJ_VERSION_EXTRA}")

हालांकि सीएमके 3.0 और उद्धृत तर्कों की नई समर्थन लाइन जारी है , आप इंडेंटेशन व्हाट्सएप को अपनी स्ट्रिंग में शामिल किए बिना दूसरी या बाद की लाइनों को इंडेंट नहीं कर सकते।

2.8 और पुराने सीएमके

आप एक सूची का उपयोग कर सकते हैं। सूची के प्रत्येक तत्व को एक नई पंक्ति में रखा जा सकता है:

set(MYPROJ_VERSION_MAJOR "1")
set(MYPROJ_VERSION_MINOR "0")
set(MYPROJ_VERSION_PATCH "0")
set(MYPROJ_VERSION_EXTRA "rc1")
set(MYPROJ_VERSION_LIST "${MYPROJ_VERSION_MAJOR}"
                        ".${MYPROJ_VERSION_MINOR}"
                        ".${MYPROJ_VERSION_PATCH}"
                        "-${MYPROJ_VERSION_EXTRA}")

उद्धरणों के बिना उपयोग की जाने वाली सूची को सफेद-स्थान के बिना संक्षिप्त किया जाता है:

message(STATUS "Version: " ${MYPROJ_VERSION_LIST})
-- Version: 1.0.0-rc1

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

string(REPLACE ";" "" MYPROJ_VERSION "${MYPROJ_VERSION_LIST}")
message(STATUS "Version: ${MYPROJ_VERSION}")
-- Version: 1.0.0-rc1

आपके मूल स्ट्रिंग्स में किसी भी अर्धविराम को सूची तत्व विभाजक के रूप में देखा जाएगा, और हटा दिया जाएगा। उन्हें बच जाना चाहिए:

set(MY_LIST "Hello World "
            "with a \;semicolon")

1
बहुत लंबी लाइनों के लिए, चर नाम के बाद एक नई पंक्ति इस पैटर्न को और भी बेहतर बनाती है (इस उदाहरण में अनावश्यक)।
ऋषि

जिज्ञासा से बाहर , क्या यह अनुमान लगाना सही होगा कि स्ट्रिंग में दोहरे उद्धरण-चिह्नों को भी बैकस्लैश के साथ भाग जाने की आवश्यकता है, और इसलिए किसी भी बैकस्लैश को स्ट्रिंग में एक चरित्र के रूप में प्रकट होने की आवश्यकता है?
जोनाथन लेफ्लर

@JonathanLeffler हाँ, उन्हें भागने की आवश्यकता होगी। भाषा नियम यहां हैं: cmake.org/cmake/help/latest/manual/… लेकिन यह भ्रमित करने वाला है। इसे भी देखें: stackoverflow.com/a/40728463
डगलस रॉयस

9

यह अभी भी थोड़ी सी क्रिया है, लेकिन अगर 80 चर सीमा वास्तव में आपको परेशान करती है तो आप बार-बार एक ही चर में भाग ले सकते हैं:

set(MYPROJ_VERSION_MAJOR "1")
set(MYPROJ_VERSION_MINOR "0")
set(MYPROJ_VERSION_PATCH "0")
set(MYPROJ_VERSION_EXTRA "rc1")
set(MYPROJ_VERSION "${MYPROJ_VERSION_MAJOR}.")
set(MYPROJ_VERSION "${MYPROJ_VERSION}${MYPROJ_VERSION_MINOR}.")
set(MYPROJ_VERSION "${MYPROJ_VERSION}${MYPROJ_VERSION_PATCH}-")
set(MYPROJ_VERSION "${MYPROJ_VERSION}${MYPROJ_VERSION_EXTRA}")
message(STATUS "version: ${MYPROJ_VERSION}")

आउटपुट देता है:

$ cmake  ~/project/tmp
-- version: 1.0.0-rc1
-- Configuring done
-- Generating done
-- Build files have been written to: /home/rsanderson/build/temp

7

CMakeLists.txt फ़ाइलों या CMake लिपियों में कई लाइनों में एक स्ट्रिंग शाब्दिक विभाजन करने का कोई तरीका नहीं है। यदि आप एक स्ट्रिंग के भीतर एक नई रेखा शामिल करते हैं, तो स्ट्रिंग में ही एक शाब्दिक नई पंक्ति होगी।

# Don't do this, it won't work, MYPROJ_VERSION will contain newline characters:
set(MYPROJ_VERSION "${VERSION_MAJOR}.
  ${VERSION_MINOR}.${VERSION_PATCH}-
  ${VERSION_EXTRA}")

हालाँकि, सीमेक व्हाट्सएप का उपयोग अलग-अलग तर्कों के लिए करता है, इसलिए आप एक ऐसे स्थान को बदल सकते हैं जो एक तर्क विभाजक है जो व्यवहार को बदलने के बिना आपको कहीं भी एक नई रेखा में बदल सकता है।

आप इस लंबी लाइन को फिर से वाक्यांश कर सकते हैं:

set(MYPROJ_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-${VERSION_EXTRA}")

इन दो छोटी रेखाओं के रूप में:

set(MYPROJ_VERSION
  "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-${VERSION_EXTRA}")

वे पूरी तरह से समकक्ष हैं।


5

मूल प्रश्न में उदाहरण केवल अपेक्षाकृत कम स्ट्रिंग के बारे में है। लंबे समय तक तार (अन्य उत्तरों में दिए गए उदाहरणों सहित) के लिए, एक ब्रैकेट तर्क बेहतर हो सकता है। प्रलेखन से:

एक उद्घाटन ब्रैकेट [शून्य या उससे अधिक के =बाद लिखा जाता है [। तत्संबंधी समापन कोष्ठक ]उसी संख्या के =बाद लिखा जाता है जिसके बाद यह संख्या आती है ]। कोष्ठक घोंसला नहीं बनाते हैं। उद्घाटन और समापन ब्रैकेट के लिए एक अद्वितीय लंबाई हमेशा चुनी जा सकती है जिसमें अन्य लंबाई के समापन कोष्ठक शामिल होते हैं।

[...]

उदाहरण के लिए:

message([=[
This is the first line in a bracket argument with bracket length 1.
No \-escape sequences or ${variable} references are evaluated.
This is always one argument even though it contains a ; character.
The text does not end on a closing bracket of length 0 like ]].
It does end in a closing bracket of length 1.
]=])```

यदि मैं इसे सही ढंग से समझता हूं, तो स्रोत में एक लाइनब्रेक भी स्ट्रिंग में एक लाइनब्रेक पेश करेगा। उदाहरण के लिए, "लंबाई 1." के बाद एक \ n होगा। किसी भी तरह से बचने के लिए?
लुकास श्मलेज़ेसेन

यह सही है, वहाँ होगा \n। यदि आप ऐसा नहीं चाहते हैं, तो मुझे नहीं लगता कि ब्रैकेट तर्क आपके समाधान हैं।
ingomueller.net 9

BTW, यह संस्करण 3.x के लिए मान्य है, न कि 2.x
मैक्सिम सुसलोव

4

जिन लोगों को यहां से लाया गया था, उनके लिए मैं सीएमके जनरेटर की अभिव्यक्ति को कई लाइनों में कैसे विभाजित करूं?मैं कुछ नोट्स जोड़ना चाहूंगा।

लाइन निरंतरता विधि काम नहीं करेगी, CMake व्हॉट्सएप (इंडेंटेशन) और लाइन निरंतरता के साथ बनाई गई जनरेटर सूची को पार्स नहीं कर सकता है।

जबकि स्ट्रिंग (CONCAT) समाधान एक जनरेटर अभिव्यक्ति प्रदान करेगा जिसका मूल्यांकन किया जा सकता है, मूल्यांकन की गई अभिव्यक्ति को उद्धरण से घेर लिया जाएगा यदि परिणाम में कोई स्थान होता है।

प्रत्येक अलग-अलग विकल्प को जोड़ने के लिए एक अलग जनरेटर सूची का निर्माण किया जाना चाहिए, इसलिए मैंने जो निम्न में किया है, जैसे स्टैकिंग विकल्प निर्माण का कारण बनेंगे:

string(CONCAT WARNING_OPTIONS "$<"
    "$<OR:"
        "$<CXX_COMPILER_ID:MSVC>,"
        "$<STREQUAL:${CMAKE_CXX_SIMULATE_ID},MSVC>"
    ">:"
    "/D_CRT_SECURE_NO_WARNINGS "
">$<"
    "$<AND:"
        "$<CXX_COMPILER_ID:Clang,GNU>,"
        "$<NOT:$<STREQUAL:${CMAKE_CXX_SIMULATE_ID},MSVC>>"
    ">:"
    "-Wall -Werror "
">$<"
    "$<CXX_COMPILER_ID:GNU>:"
    "-Wno-multichar -Wno-sign-compare "
">")
add_compile_options(${WARNING_OPTIONS})

इसका कारण यह है कि परिणामी विकल्प कंपाइलर को उद्धरणों में दिए जाते हैं

/usr/lib64/ccache/c++  -DGTEST_CREATE_SHARED_LIBRARY=1 -Dgtest_EXPORTS -I../ThirdParty/googletest/googletest/include -I../ThirdParty/googletest/googletest -std=c++11 -fno-rtti -fno-exceptions -fPIC    -std=c++11 -fno-rtti -fno-exceptions -Wall -Wshadow -DGTEST_HAS_PTHREAD=1 -fexceptions -Wextra -Wno-unused-parameter -Wno-missing-field-initializers "-Wall -Werror -Wno-multichar -Wno-sign-compare " -fdiagnostics-color -MD -MT ThirdParty/googletest/googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o -MF ThirdParty/googletest/googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o.d -o ThirdParty/googletest/googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o -c ../ThirdParty/googletest/googletest/src/gtest-all.cc
c++: error: unrecognized command line option ‘-Wall -Werror -Wno-multichar -Wno-sign-compare ’

स्ट्रिंग (CONCAT) समाधान का उपयोग करके दर्शाए गए लंबे जनरेटर अभिव्यक्तियों का मूल्यांकन करने के लिए, प्रत्येक जनरेटर अभिव्यक्ति को किसी भी स्थान के साथ एकल विकल्प का मूल्यांकन करना चाहिए:

string(CONCAT WALL "$<"
    "$<AND:"
        "$<CXX_COMPILER_ID:Clang,GNU>,"
        "$<NOT:$<STREQUAL:${CMAKE_CXX_SIMULATE_ID},MSVC>>"
    ">:"
    "-Wall"
">")
string(CONCAT WERROR "$<"
    "$<AND:"
        "$<CXX_COMPILER_ID:Clang,GNU>,"
        "$<NOT:$<STREQUAL:${CMAKE_CXX_SIMULATE_ID},MSVC>>"
    ">:"
    "-Werror"
">")
message(STATUS "Warning Options: " ${WALL} ${WERROR})
add_compile_options(${WALL} ${WERROR})

यह उस प्रश्न से असंबंधित हो सकता है जिसका उत्तर मैं दे रहा हूं, दुर्भाग्यवश मैं जिस प्रश्न का उत्तर दे रहा हूं वह गलत तरीके से इस प्रश्न के डुप्लिकेट के रूप में चिह्नित है।

जेनरेटर सूचियों को संभाला नहीं जाता है और तार को उसी तरह से पार्स किया जाता है, और इस वजह से, एक अतिरिक्त सूची को कई लाइनों में एक जनरेटर सूची को विभाजित करने के लिए अतिरिक्त उपाय करने होंगे।


संभवतः इस उत्तर का एक संस्करण लिंक किए गए "डुप्लिकेट" पर पोस्ट करना भी सार्थक होगा। यह वह उत्तर था जिसकी मुझे तलाश थी जब मैं इसके पार आया।
कीथ प्रूसिंग

3

अपने कोड में अच्छा इंडेंटेशन बनाए रखने के लिए यह सिर्फ इतना सीधा है

message("These strings " "will all be "
        "concatenated. Don't forget "
        "your trailing spaces!")

या सीधे के साथ एक स्ट्रिंग बनाएँ

string(CONCAT MYSTR "This and " "that "
                    "and me too!")

डगलस के जवाब में जैसा कि अधिक विवरण है। हालाँकि मुझे लगा कि यह आवश्यक बिंदु को संक्षेप में प्रस्तुत कर सकता है।

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