मैं सीएमके में सी ++ 11 को कैसे सक्रिय कर सकता हूं?


356

जब मैं अपने प्रोग्राम को संकलित करने के लिए सीएमके जनरेट किए गए मेकफाइल को चलाने की कोशिश करता हूं, तो मुझे वह त्रुटि मिलती है

लूप के लिए आधारित रेंज C ++ 98 मोड में समर्थित नहीं हैं।

मैंने add_definitions(-std=c++0x)अपने साथ जोड़ने की कोशिश की CMakeLists.txt, लेकिन इससे कोई फायदा नहीं हुआ।

मैंने यह भी कोशिश की:

if(CMAKE_COMPILER_IS_GNUCXX)
    add_definitions(-std=gnu++0x)
endif()

जब मैं करता हूं g++ --version, मुझे मिलता है:

g ++ (Ubuntu / Linaro 4.6.1-9ubuntu3) 4.6.1

मैंने भी कोशिश की है SET(CMAKE_CXX_FLAGS "-std=c++0x"), जो भी काम नहीं करता है।

मुझे समझ में नहीं आ रहा है कि मैं सीएमके का उपयोग करके सी ++ 11 सुविधाओं को कैसे सक्रिय कर सकता हूं।


11
SET(CMAKE_CXX_FLAGS "-std=c++0x")मेरे लिए ठीक काम करता है, इसलिए वहाँ शायद CMakeLists फ़ाइल में कहीं और एक समस्या है। सुनिश्चित करें कि आप गलती से बाद में CMAKE_CXX_FLAGS की सामग्री को अधिलेखित नहीं करते हैं।
ComicSansMS

7
add_definitions (-std = c ++ 11) मेरे लिए CMake 2.8.8 के साथ काम करता है
kyku

@ComicSansMS: आप पूरी तरह से सही हैं! मैंने इसे खत्म कर दिया, जो मेरी अपनी गलती थी। मैंने इसे ठीक कर लिया है, और अब यह ठीक काम कर रहा है! C ++ 11 सामान बहुत अच्छा है! मैं संरचनाओं के एक वेक्टर पर लूप करना चाहता था, जिसके लिए लूप के लिए रेंज नहीं होने पर इटरेटर और अनावश्यक कोडिंग शोर की आवश्यकता होगी। मुझे लगता है कि मैं BOOST_FOREACH का उपयोग कर सकता हूं, लेकिन ओह अच्छी तरह से ...
Subhamoy S.

32
CMake target3.1 के लिए, set(CMAKE_CXX_STANDARD 11)(लक्ष्य को परिभाषित करने से पहले) सबसे अच्छा तरीका है।
इमलाई

@tuple_cat आप इसे लक्ष्य-आधारित भी कर सकते हैं। लेकिन ध्यान रखें कि MSVC पर काम नहींCXX_STANDARD करता है , इसलिए मूल रूप से आपको वापस गिरना होगा यदि आप ऐसा कुछ चाहते हैं जो क्रॉस-प्लेटफॉर्म पर काम करे। target_compile_features
इला .२ El२

जवाबों:


395

CMake 3.1 ने CMAKE_CXX_STANDARD चर पेश किया जिसका आप उपयोग कर सकते हैं। यदि आप जानते हैं कि आपके पास हमेशा CMake 3.1 उपलब्ध होगा, तो आप इसे केवल अपने शीर्ष-स्तरीय CMakeLists.txt फ़ाइल में लिख सकते हैं, या किसी भी नए लक्ष्य को परिभाषित करने से पहले इसे सही तरीके से रख सकते हैं:

set (CMAKE_CXX_STANDARD 11)

यदि आपको CMake के पुराने संस्करणों का समर्थन करने की आवश्यकता है, तो यहां एक मैक्रो है जो मैं आपके साथ उपयोग कर सकता हूं:

macro(use_cxx11)
  if (CMAKE_VERSION VERSION_LESS "3.1")
    if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
      set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
    endif ()
  else ()
    set (CMAKE_CXX_STANDARD 11)
  endif ()
endmacro(use_cxx11)

मैक्रो अभी केवल जीसीसी का समर्थन करता है, लेकिन इसे अन्य संकलक तक विस्तारित करने के लिए सीधे-आगे होना चाहिए।

तब आप use_cxx11()किसी भी CMakeLists.txt फ़ाइल के शीर्ष पर लिख सकते हैं जो C ++ 11 का उपयोग करने वाले लक्ष्य को परिभाषित करता है।

MacOS को लक्षित करने वाले क्लैंग उपयोगकर्ताओं के लिए CMake मुद्दा # 15943

यदि आप CMake का उपयोग कर रहे हैं और macOS को निशाना बनाने के लिए हैं, तो एक बग है जो CMAKE_CXX_STANDARDफीचर को काम नहीं करने का कारण बन सकता है (किसी भी कंपाइलर झंडे को नहीं जोड़ें)। सुनिश्चित करें कि आप निम्न में से एक काम करते हैं:

  • CMake 3.0 या बाद के संस्करण की आवश्यकता के लिए cmake_minimum_required का उपयोग करें , या
  • projectकमांड से पहले अपने CMakeLists.txt फ़ाइल के शीर्ष पर निम्न कोड के साथ पॉलिसी CMP0025 को नया सेट करें :

    # Fix behavior of CMAKE_CXX_STANDARD when targeting macOS.
    if (POLICY CMP0025)
      cmake_policy(SET CMP0025 NEW)
    endif ()

12
यह स्वीकृत उत्तर होना चाहिए। इसे व्यक्तिगत रूप से प्रत्येक लक्ष्य के गुणों को छूने की आवश्यकता नहीं है, और क्रॉस-प्लेटफ़ॉर्म काम करता है।
DevSolar

4
सहमत, यह सीएमके 3.1+ के रूप में स्वीकृत उत्तर होना चाहिए। हालांकि यह मेरे लिए मैक पर काम नहीं करता है। आप इसे मैक पर डिफ़ॉल्ट --std = c ++ 11 के साथ --stdlib = libc ++ देने के लिए बाध्य कर सकते हैं। इसके बजाय CMAKE_CXX_STANDARD में हमेशा ग्नू एक्सटेंशन शामिल होते हैं यदि वे समर्थित हैं, और परिणाम --stdlib = libc ++ के विरुद्ध नहीं बनता है। इसके बजाय आपको gnu's --stdlib = libstdc ++ पर स्विच करना होगा। मैक हालांकि विशेष मामला है। लिनक्स के लिए, libstdc ++ के साथ gnu ++ 11 चुनना आदर्श है। बेशक, यह आसानी से सही है अगर झंडे से निपटने के लिए (APPLE) add_compile_options () के साथ।
आतिफम

2
इस दृष्टिकोण की एक समस्या यह है कि gnu++11लागू किया जाता है, तब भी जब ये चर परिभाषित किए जाते हैं set(CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION clang) set(CMAKE_ANDROID_STL_TYPE c++_static)। मेरे लिए एकमात्र व्यवहार्य तरीका क्लासिक थाset (CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
एंटोनियो

2
मेरे लिए macOS (CMake 3.9.4, homebrew-clang) पर काम नहीं करता है। दूसरों को निराशा से बचाना। यकीन नहीं होता कि यह @EvanMoran के लिए क्यों काम करता है लेकिन मैं नहीं।
अनपिड्रा

2
@Unapiedra: यह एक सीएमके बग है, लेकिन आप इसके चारों ओर काम कर सकते हैं, gitlab.kitware.com/cmake/cmake/issues/15943
डेविड ग्रेसन

186

CMake कमांड target_compile_features()का उपयोग आवश्यक C ++ फीचर को निर्दिष्ट करने के लिए किया जाता है cxx_range_for। CMake तब C ++ मानक का उपयोग करने के लिए प्रेरित करेगा।

cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
project(foobar CXX)
add_executable(foobar main.cc)
target_compile_features(foobar PRIVATE cxx_range_for)

add_definitions(-std=c++11)CMake चर का उपयोग करने या संशोधित करने की कोई आवश्यकता नहीं है CMAKE_CXX_FLAGS, क्योंकि CMake सुनिश्चित करेगा कि C ++ कंपाइलर उचित कमांड लाइन के झंडे के साथ लगाया गया है।

हो सकता है कि आपका C ++ प्रोग्राम अन्य C ++ सुविधाओं का उपयोग करता हो cxx_range_for। CMake वैश्विक संपत्ति आपके द्वारा चुनी CMAKE_CXX_KNOWN_FEATURESजा सकने वाली C ++ सुविधाओं को सूचीबद्ध करती है।

उपयोग करने के बजाय target_compile_features()आप CMake गुण सेट करके CXX_STANDARD और CXX_STANDARD_REQUIREDअपने CMake लक्ष्य के लिए C ++ मानक स्पष्ट रूप से निर्दिष्ट कर सकते हैं ।

मेरा और अधिक विस्तृत उत्तर भी देखें ।


4
ऐसा लगता है कि आज से संपादित भ्रामक है। CMake 3.0.0 में target_compile_features नहीं है। यदि मैं गलत हूं तो मुझे सही करों। मुझे लगता है कि आदेश केवल सीएमके के रात के निर्माण में मौजूद है।
एरिक सोजलंड

4
मैं कहता हूँ कि यह सबसे सटीक उत्तर है
माइकल वालेंसीक

8
मुझे लगता है कि यह कैसे करना है। अन्य उत्तर बस मैन्युअल रूप से झंडे जोड़ते हैं और इसलिए असंगति का परिचय देते हैं। हालाँकि ऐसा लगता है कि यह केवल CMake 3.1+ में उपलब्ध है
Uli Köhler

2
@ UliKöhler यह वास्तव में अभी भी उपलब्ध नहीं है, और संभवतः 3.2 में कुछ संकलक के लिए बदल सकता है । इस विधि का अल्पावधि में उपयोग न करें; पूरी तरह से पोर्टेबल नहीं है।
डग

2
किसी भी विचार कैसे CMake 2.6 में यह करने के लिए?
nuzzolilo

93

मै इस्तेमाल कर रहा हूँ

include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
        message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()

लेकिन अगर आप साथ खेलना चाहते हैं C++11, g++ 4.6.1तो बहुत पुराना है। एक नया g++संस्करण प्राप्त करने का प्रयास करें ।


4
यह मेरे लिए, इस सवाल का एकमात्र सही और अच्छा उत्तर है, वर्तमान (लुढ़का हुआ) के साथ सबसे हाल ही में लिनक्स 'जी + का उपयोग कर' पर सेंकना।
पैट्रिक बी।

1
इसे कॉपी और पेस्ट किया गया और इसने पूरी तरह से काम किया। मैं साइगविन पर 2.8.9 CMAKE का उपयोग कर रहा हूं। मुझे पता है कि मैं यहां पढ़ रहे अधिकांश दृष्टिकोणों के बारे में जानता हूं क्योंकि मैं CMAKE मेलिंग सूची का पालन करता हूं और मैंने वेबकीट को विभिन्न प्रकार के कंपाइलरों में पोर्ट किया है। WebKit पोर्ट के लिए हमने जो काम किया था वह CMake 2.8.12 स्थापित करना था। हालाँकि, क्योंकि मुझे पता है कि Cygwin का CMAKE पुराना है, मैं कुछ ऐसा चाहता था जो उस संस्करण पर लागू हो। (साइकेटविन, सॉरी के लिए वेबकीट को पोर्ट नहीं करना)
कार्डिफ स्पेस मैन

महान, यह पुराने सीएमके और जी ++ 4.6 (और भविष्य के सबूत) के लिए एक ड्रॉप-इन है। मैंने -bbed CXX_STANDARDउत्तरों को भी उकेरा , लेकिन यह मेरी स्थिति में उपयोगी एकमात्र उत्तर था।
टॉमस गैंडर

यह वही है जो मैं देख रहा था, हालांकि यह स्पष्ट नहीं है कि उस मॉड्यूल का उपयोग करने के लिए आवश्यक न्यूनतम cmake संस्करण क्या है। cmake --help-मॉड्यूल इसके बारे में ज्यादा मदद नहीं करता है।
Jan Segre

1
@ जैनसेगर मॉड्यूल पहली बार 2.4, cmake.org/…
KoKuToru

57

Cxx मानक सेट करने का सबसे आसान तरीका है:

 set_property(TARGET tgt PROPERTY CXX_STANDARD 11)

देखें CMake प्रलेखन अधिक जानकारी के लिए।


2
हां, यह निश्चित रूप से आधुनिक
सीएमके

14
या आप बस set(CMAKE_CXX_STANDARD 11)उसके बाद बनाए गए सभी लक्ष्यों के लिए डिफ़ॉल्ट संपत्ति को परिभाषित कर सकते हैं।
इमलाई

1
यदि आप विभिन्न लक्ष्यों पर विभिन्न C ++ मानकों को सेट करना चाहते हैं तो यह भी समाधान है, क्योंकि set@emlai द्वारा सुझाई गई कमांड वैश्विक है और बाद के सभी लक्ष्यों को प्रभावित करती है।
इलियट स्लॉटर

40

जैसा कि यह पता चला है, SET(CMAKE_CXX_FLAGS "-std=c++0x")कई सी ++ 11 सुविधाओं को सक्रिय करता है। यह काम नहीं करने का कारण यह था कि बयान इस तरह दिखता था:

set(CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS} -g -ftest-coverage -fprofile-arcs")

इस दृष्टिकोण के बाद, किसी भी तरह -std=c++0xझंडे को अधिलेखित कर दिया गया और यह काम नहीं किया। झंडे को एक-एक करके सेट करना या सूची विधि का उपयोग करना काम कर रहा है।

list( APPEND CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS} -g -ftest-coverage -fprofile-arcs")

36
मैं हमेशा सिर्फ उपयोग करता हूं: सेट (CMAKE_CXX_FLAGS "$ {CMAKE_CXX_FLAGS} -std = c ++ 11") # gcc के लिए = = 4.7, या c ++ 0x 4.6 के लिए।
डेविड डोरिया

मैंने एक बार उसके लिए एक छोटी सी स्क्रिप्ट की थी (हालांकि पूरी नहीं): github.com/Morwenn/POLDER/blob/master/cmake/set_cxx_norm.cmake
Morwenn

9
-1। यदि आप कमांड लाइन से किसी भी CMAKE_CXX_FLAGS को निर्दिष्ट करते हैं, तो दूसरी विधि बिल्ड कमांड में अर्धविराम का उत्पादन करेगी (और मूल CMAKE_CXX_FLAGS को दो बार दोहराएं)।
निकोलाई

मैन्युअल रूप से -g ध्वज जोड़ने के बजाय आपको CMAKE_BUILD_TYPE चर को डीबग करने के लिए सेट करना चाहिए: voices.canonical.com/jussi.pakkanen/2013/03/26/…
bames53

1
CXX_STANDARDके रूप में यह संकलक-नास्तिक है संपत्ति बेहतर है।
jaskmar


19

सीएमके 3.8 और नए के लिए आप उपयोग कर सकते हैं

target_compile_features(target PUBLIC cxx_std_11)

1
यह सीएमके के नवीनतम संस्करण की सिफारिश करने का तरीका है
कैमिनो

PUBLICयहाँ का कार्य क्या है ?
रॉटाइज़र मो

2
@RotsiserMho का PUBLICअर्थ है कि आपके लक्ष्य पर निर्भर अन्य लक्ष्य C ++ 11 का भी उपयोग करेंगे। उदाहरण के लिए यदि आपका लक्ष्य एक पुस्तकालय है तो आपके पुस्तकालय के खिलाफ लिंक वाले सभी लक्ष्यों target_link_librariesको C ++ 11 समर्थन के साथ संकलित किया जाएगा।
बरौनी

17

यह C ++ 11 समर्थन को सक्षम करने का एक और तरीका है,

ADD_DEFINITIONS(
    -std=c++11 # Or -std=c++0x
    # Other flags
)

मुझे ऐसे उदाहरणों का सामना करना पड़ा है जहाँ केवल यह विधि काम करती है और अन्य विधियाँ विफल हो जाती हैं। शायद सीएमके के नवीनतम संस्करण के साथ इसका कुछ करना है।


9
यह तभी काम करेगा जब आप केवल C ++ कंपाइलर का उपयोग कर रहे हैं। यदि आप भी CC संकलक का उपयोग कर रहे हैं तो यह विफल हो जाएगा।
इमैनुएल

5
add_definitionsइसका उपयोग केवल परिभाषाएँ जोड़ने के लिए किया जाना चाहिए, अर्थात -DOMETHING। और जैसा @ इमानुएल ने कहा, यह कई मामलों में काम नहीं करता है।
xuhdev

मैंने पहले भी इसका इस्तेमाल किया था, लेकिन जब मैंने सी फाइल शामिल की तो समस्या थी क्योंकि add_definitionsझंडे लगाने के लिए नहीं बनाया गया था।
Jan Segre

17

आधुनिक सीएमके पर (> = 3.1) वैश्विक आवश्यकताओं को निर्धारित करने का सबसे अच्छा तरीका है:

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

इसका अनुवाद "मुझे सभी लक्ष्यों के लिए C ++ 11 चाहिए, यह वैकल्पिक नहीं है, मैं किसी भी GNU या Microsoft एक्सटेंशन का उपयोग नहीं करना चाहता।" C ++ 17 के रूप में, यह अभी भी IMHO सबसे अच्छा तरीका है।

स्रोत: C ++ 11 और बाद में CMake में सक्षम करना


1
यदि आपके पास नवीनतम CMake नहीं है तो यह तरीका C ++ के नवीनतम संस्करणों के लिए आदर्श नहीं है। जैसे आप C ++ 2a को CMake 3.12 तक इस तरह से सक्षम नहीं कर सकते।
रुस्लान

6

मेरे लिए आपके CMakeLists.txt में निम्न लाइन सेट करने के लिए क्या काम करता है:

set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

इस कमांड को सेट करना कंपाइलर के लिए C ++ 11 फीचर्स को सक्रिय करता है और cmake ..कमांड को निष्पादित करने के बाद , आपको range based for loopsअपने कोड में उपयोग करने में सक्षम होना चाहिए और इसे बिना किसी त्रुटि के संकलित करना चाहिए ।


यह अंत में सबसे अच्छा उत्तर है यदि आप वास्तव में चाहते हैं -std=c++11, जैसा set (CMAKE_CXX_STANDARD 11)कि ध्वज का उपयोग करेगा -std=gnu++11, जो अवांछनीय हो सकता है।
एंटोनियो

1
@Antonioset (CMAKE_CXX_EXTENSIONS OFF)
mloskot

3

मुझे लगता है कि बस ये दो लाइनें काफी हैं।

set(CMAKE_CXX_STANDARD 11)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

1
यह तब समझ में आता है जब किसी परियोजना में सभी लक्ष्य समान C ++ मानक (सभी संकलित पुस्तकालय और निष्पादन योग्य C ++ 11, उदाहरण के लिए) का उपयोग करते हैं। अन्यथा, Cmake target_compile_featuresफ़ंक्शन, प्रत्येक व्यक्तिगत लक्ष्य के लिए लागू किया जाता है, जैसा कि अन्य उत्तरों में दिखाया गया है, एक अधिक अनुशंसित दृष्टिकोण है।
एलन

3

यदि आप हमेशा नवीनतम C ++ मानक को सक्रिय करना चाहते हैं , तो हाल ही में (सीएमके 3.8 और सीएमके 3.11) सीएमएकेई_एक्सएक्सएक्स-बैंकैंडर्ड के लिए 17 और 20 के मूल्यों के जोड़ में, डेविड ग्रेसन के जवाब के बारे में मेरा विस्तार ।

IF (CMAKE_VERSION VERSION_LESS "3.8")
    SET(CMAKE_CXX_STANDARD 14)
ELSEIF (CMAKE_VERSION VERSION_LESS "3.11")
    SET(CMAKE_CXX_STANDARD 17)
ELSE()
    SET(CMAKE_CXX_STANDARD 20)
ENDIF()

# Typically, you'll also want to turn off compiler-specific extensions:
SET(CMAKE_CXX_EXTENSIONS OFF)

( set (CMAKE_CXX_STANDARD 11)लिंक किए गए उत्तर में उस कोड का उपयोग करें ।)


1

आधुनिक सीमेक सी ++ के एक विशिष्ट संस्करण का उपयोग करने के लिए संकलक को कॉन्फ़िगर करने के सरल तरीके प्रदान करता है। केवल एक चीज जो किसी को करने की आवश्यकता है वह है प्रासंगिक लक्ष्य गुण। के अलावा cmake द्वारा समर्थित गुण , जो कि उपयोग किया जाता है निर्धारित करने के लिए कैसे कॉन्फ़िगर compilers के लिए सी की ++ अनुसरण कर रहे हैं एक विशेष संस्करण का समर्थन करने के लिए:

  • CXX_STANDARDC ++ मानक सेट करता है जिसकी विशेषताएं लक्ष्य बनाने के लिए अनुरोध की जाती हैं। 11C ++ 11 को लक्षित करने के लिए इसे सेट करें ।

  • CXX_EXTENSIONS, एक बूलियन निर्दिष्ट करता है कि संकलक विशिष्ट एक्सटेंशन का अनुरोध किया जाता है या नहीं। इसे Offकिसी भी कंपाइलर-विशिष्ट एक्सटेंशन के समर्थन के रूप में सेट करना ।

प्रदर्शित करने के लिए, यहाँ एक न्यूनतम काम करने का उदाहरण है CMakeLists.txt

cmake_minimum_required(VERSION 3.1)

project(testproject LANGUAGES CXX )

set(testproject_SOURCES
    main.c++
    )

add_executable(testproject ${testproject_SOURCES})

set_target_properties(testproject
    PROPERTIES
    CXX_STANDARD 11
    CXX_EXTENSIONS off
    )

-5

ओएस एक्स और होमब्रेव एलएलवीएम संबंधित:

इसके बाद cmake_minimum_required (संस्करण 3.3) और प्रोजेक्ट () कॉल करना न भूलें!

या सीएमके project()लाइन 1 से पहले अंतर्निहित रूप से सम्मिलित करेगा , जिससे क्लैंग संस्करण का पता लगाने और संभवतः अन्य प्रकार की परेशानियों का सामना करना पड़ेगा । यहाँ एक संबंधित मुद्दा है


2
सवाल ओएसएक्स या एलवीवीएम से संबंधित नहीं है, विशेष रूप से। इसके अलावा, C ++ 11 विकास के लिए CMake v3.x की आवश्यकता का कोई कारण नहीं है। क्लैंग संस्करण का पता लगाने के लिए - यह वही है जो ओपी ने नहीं पूछा।
19p में einpoklum
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.