CMake'de C ++ 11'i nasıl etkinleştiririm?


357

Programımı derlemek için bir CMake oluşturulan makefile çalıştırmayı denediğimde,

döngüler için aralık C ++ 98 modunda desteklenmez.

Ben ekleyerek çalıştı add_definitions(-std=c++0x)kardeşime karşı CMakeLists.txt, ancak yardım etmedi.

Ben de denedim:

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

Ben ne zaman g++ --versionben alıyorum:

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

Ben de denedim SET(CMAKE_CXX_FLAGS "-std=c++0x"), bu da çalışmıyor.

CMake kullanarak C ++ 11 özelliklerini nasıl etkinleştirebileceğimi anlamıyorum.


11
SET(CMAKE_CXX_FLAGS "-std=c++0x")Benim için para cezası çalışır, bu yüzden CMakeLists dosyasında başka bir yerde bir sorun muhtemelen yoktur. Daha sonra CMAKE_CXX_FLAGS içeriğinin üzerine yanlışlıkla yazmadığınızdan emin olun.
ComicSansMS

7
add_definitions (-std = c ++ 11) CMake 2.8.8 ile benim için çalışıyor
kyku

@ComicSansMS: Tamamen haklısın! Üzerine yazdım, ki bu benim hatamdı. Düzelttim ve şimdi iyi çalışıyor! C ++ 11 şeyler çok güzel! Döngülere dayalı bir aralığım olmasaydı yineleyici ve gereksiz kodlama gürültüsü gerektiren bir yapı vektörü üzerinde döngü yapmak istedim. Ben olsa BOOST_FOREACH kullanabilirsiniz, ama oh iyi ...
Subhamoy S.

33
CMake ≥3.1 için, set(CMAKE_CXX_STANDARD 11)(hedefi tanımlamadan önce) en iyi yoldur.
emlai

@tuple_cat Hedef tabanlı da yapabilirsiniz. Ama unutmayın CXX_STANDARDyapar değil bu yüzden temelde geri düşmek zorunda MSVC üzerinde çalışmaya target_compile_featuresarası bir platform çalışan bir şey istiyorum.
Ela782

Yanıtlar:


394

CMake 3.1 , kullanabileceğiniz CMAKE_CXX_STANDARD değişkenini tanıttı . CMake 3.1'in her zaman kullanılabilir olacağını biliyorsanız, bunu sadece üst düzey CMakeLists.txt dosyanıza yazabilir veya herhangi bir yeni hedef tanımlanmadan hemen önce koyabilirsiniz:

set (CMAKE_CXX_STANDARD 11)

CMake'in eski sürümlerini desteklemeniz gerekiyorsa, kullanabileceğiniz bir makro burada:

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)

Makro şu anda yalnızca GCC'yi desteklemektedir, ancak diğer derleyicilere genişletmek düz olmalıdır.

Daha sonra use_cxx11(), C ++ 11 kullanan bir hedefi tanımlayan herhangi bir CMakeLists.txt dosyasının üstüne yazabilirsiniz .

C macOS'u hedefleyen clang kullanıcıları için sorun # 15943

MacOS'u hedeflemek için CMake ve clang kullanıyorsanız , özelliğin çalışmamasına neden olabilecek bir hata var CMAKE_CXX_STANDARD(derleyici bayrakları eklemeyin). Aşağıdakilerden birini yaptığınızdan emin olun:

  • CMake 3.0 veya üstünü gerektirmek için cmake_minimum_required kullanın veya
  • CMakeLists.txt dosyanızın üstünde komuttan önce aşağıdaki kodla CMP0025 politikasını YENİ olarak ayarlayın project:

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

12
Bu kabul edilen cevap olmalı. Her hedefin özelliklerine ayrı ayrı dokunmayı gerektirmez ve platformlar arası çalışır.
DevSolar

4
Kabul ediyorum, bu CMake 3.1+'tan itibaren kabul edilen cevap olmalıdır. Yine de mac benim için çalışmıyor gibi görünüyor. Mac'te varsayılan olarak --stdlib = libc ++ ile --std = c ++ 11 vermeye zorlayabilirsiniz. Bunun yerine CMAKE_CXX_STANDARD destekleniyorsa her zaman gnu uzantılarını içerir ve sonuç --stdlib = libc ++ 'a karşı oluşturulmuş gibi görünmez. Bunun yerine gnu'nun --stdlib = libstdc ++ 'a geçmelisiniz. Mac de özel bir durum. Linux için libstdc ++ ile gnu ++ 11 seçmek normdur. Tabii ki, bayraklara yapışmak için bir if (APPLE) add_compile_options () ile kolayca düzeltilebilir.
Atifm

2
Bu yaklaşımın bir problemi, gnu++11bu değişkenler tanımlansa bile uygulanmaktır set(CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION clang) set(CMAKE_ANDROID_STL_TYPE c++_static). Benim için tek geçerli yol klasiktiset (CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
Antonio

2
MacOS'ta benim için çalışmıyor (CMake 3.9.4, homebrew-clang). Diğerlerine umutsuzluğu kurtarmak. Neden @EvanMoran için çalıştığından emin değilim ama ben değil.
Unapiedra

2
@Unapiedra: Bu bir CMake hatası ama etrafında çalışabilirsiniz, bkz. Gitlab.kitware.com/cmake/cmake/issues/15943
David Grayson

185

CMake komutu target_compile_features(), gerekli C ++ özelliğini belirtmek için kullanılır cxx_range_for. CMake daha sonra kullanılacak C ++ standardını indükleyecektir.

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 değişkenini kullanmaya veya değiştirmeye gerek yoktur CMAKE_CXX_FLAGS, çünkü CMake C ++ derleyicisinin uygun komut satırı bayrakları ile çağrıldığından emin olur.

Belki de C ++ programınız diğer C ++ özelliklerini kullanır cxx_range_for. CMake global özelliği CMAKE_CXX_KNOWN_FEATURES, aralarından seçim yapabileceğiniz C ++ özelliklerini listeler.

Kullanmak yerine target_compile_features(), CMake özelliklerini CXX_STANDARD ve CXX_STANDARD_REQUIREDCMake hedefinizi ayarlayarak C ++ standardını da açıkça belirtebilirsiniz .

Ayrıca daha ayrıntılı cevabımı da görün .


4
Bugünkü düzenleme yanıltıcı görünüyor. CMake 3.0.0, target_compile_features içermez. Yanlışsam düzelt. Bence komuta sadece CMake'in gece yapılarında var.
Erik Sjölund

4
Bunun en doğru cevap olduğunu söyleyebilirim
Michał Walenciak

8
Bence böyle yapılması gerekiyordu. Diğer cevaplar sadece manuel olarak bayrak ekler ve bu nedenle uyumsuzluklar getirir. Ancak bu sadece CMake 3.1+ 'da mevcut gibi görünüyor
Uli Köhler

2
@ UliKöhler bu hala mevcut değildir ve 3.2'de bazı derleyiciler için gelebilir . Bu yöntemi kısa vadede kullanmayın; tamamen taşınabilir değil.
Doug

2
CMake 2.6'da bunu nasıl yapacağınız hakkında bir fikriniz var mı?
nuzzolilo

92

Ben kullanıyorum

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()

Eğer oynamak istiyorsanız C++11, g++ 4.6.1oldukça eskidir. Daha yeni bir g++sürüm almaya çalışın .


4
Benim için, bu sorunun tek doğru ve güzel yanıtı, en son Linux 'da g ++ kullanan mevcut cmake.
Patrick B.

1
Kopyaladı ve yapıştırdı ve mükemmel çalıştı. CMAKE 2.8.9 kullanarak Cygwin kullanıyorum. Burada okuduğum yaklaşımların çoğunu biliyorum çünkü CMAKE posta listesini takip ediyorum ve WebKit'i çeşitli derleyicilere taşıdım. WebKit bağlantı noktaları için yaptığımız şey CMake 2.8.12'yi kurmaktı. Ancak Cygwin'in CMAKE'sinin eski olduğunu bildiğim için, bu sürüme uygulanan bir şey istedim. (WebKit'i Cygwin'e aktarmıyoruz, üzgünüm)
cardiff space man

Harika, bu eski CMake ve g ++ 4.6 (ve geleceğe yönelik) için bir drop-in. Ayrıca, CXX_STANDARDtemelli cevapları da iptal ettim , ancak bu benim durumumda yararlı olan tek cevaptı.
Tomasz Gandor

Bu tam olarak aradığım şey, ancak bu modülü kullanmak için gereken minimum cmake sürümünün ne olduğu açık değil. cmake --help-module bu konuda pek yardımcı olmuyor.
Jan Segre

1
@JanSegre modül ilk olarak 2.4, cmake.org/…
KoKuToru

56

Cxx standardını belirlemenin en kolay yolu:

 set_property(TARGET tgt PROPERTY CXX_STANDARD 11)

Daha fazla bilgi için CMake belgelerine bakın.


2
Evet, bu kesinlikle modern
CMake'de

16
Veya set(CMAKE_CXX_STANDARD 11)bundan sonra oluşturulan tüm hedefler için varsayılan özelliği tanımlayabilirsiniz.
emlai

1
set@Emlai tarafından önerilen komut global olduğundan ve sonraki tüm hedefleri etkilediğinden , farklı hedeflerde farklı C ++ standartları ayarlamak istiyorsanız bu da ihtiyacınız olan çözümdür .
Elliott Slaughter

39

Anlaşıldığı gibi, SET(CMAKE_CXX_FLAGS "-std=c++0x")birçok C ++ 11 özelliğini etkinleştirir. Çalışmamasının nedeni ifadenin şöyle görünmesiydi:

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

Bu yaklaşımı takiben bir şekilde -std=c++0xbayrağın üzerine yazıldı ve işe yaramadı. Bayrakları tek tek ayarlamak veya bir liste yöntemi kullanmak çalışıyor.

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

36
Ben her zaman sadece şunu kullanıyorum: SET (CMAKE_CXX_FLAGS "$ {CMAKE_CXX_FLAGS} -std = c ++ 11") # gcc için> = 4.7 veya 4.6 için c ++ 0x
David Doria

Bir keresinde bunun için küçük bir senaryo yaptım (tam değil): github.com/Morwenn/POLDER/blob/master/cmake/set_cxx_norm.cmake
Morwenn

9
-1. Komut satırından herhangi bir CMAKE_CXX_FLAGS belirtirseniz, ikinci yöntem build komutunda noktalı virgül oluşturur (ve orijinal CMAKE_CXX_FLAGS öğesini iki kez tekrarlar).
Nikolai

-g bayrağını manuel olarak eklemek yerine CMAKE_BUILD_TYPE değişkenini hata ayıklamaya ayarlamalısınız: voices.canonical.com/jussi.pakkanen/2013/03/26/…
bames53

1
CXX_STANDARDO derleyici-agnostik olduğu gibi mülkiyet iyidir.
jaskmar

22

En kolay yol:

add_compile_options(-std=c++11)


5
Yalnızca cmake 3.0
Raúl Salinas-Monteagudo

5
Bu, aynı projede C dosyaları derlenirken uyarı ve hatalara neden olur.
rosewater

Kesinlikle bunu yapmayın. Düz C programlarının derlenmesini bozacaktır. CMakeLists.txt dosyanızı belirli bir derleyiciye yapıştırır ve yine de bunun için yerleşik destek vardır.
Alex Reinking

20

CMake 3.8 ve daha yeni sürümler için

target_compile_features(target PUBLIC cxx_std_11)

1
Bu CMake
Camino

PUBLICBurada işlevi nedir ?
Rotsiser Mho

3
@RotsiserMho PUBLIC, hedefinize bağlı diğer hedeflerin de C ++ 11 kullanacağı anlamına gelir. Örneğin hedefiniz bir kitaplıksa, kitaplığınıza bağlanan tüm hedefler target_link_librariesC ++ 11 desteği ile derlenir.
kirpik

19

Modern CMake'de (> = 3.1) küresel gereksinimleri belirlemenin en iyi yolu:

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

"Tüm hedefler için C ++ 11 istiyorum, isteğe bağlı değil, herhangi bir GNU veya Microsoft uzantısı kullanmak istemiyorum" anlamına gelir. C ++ 17'den itibaren, bu hala IMHO'nun en iyi yoludur.

Kaynak: C ++ 11 ve Daha Sonra CMake'de Etkinleştirme


1
Bu şekilde, en son CMake'ye sahip değilseniz, C ++ 'nın en yeni sürümleri için ideal değildir. CMake 3.12'ye kadar C ++ 2a'yı bu şekilde etkinleştiremezsiniz.
Ruslan

Yine de en son CMake'e sahip olmamak için bir neden yok. Chocolatey, Homebrew ve Snap'in hepsinde güncel paketler var.
Alex Reinking

16

Bu, C ++ 11 desteğini etkinleştirmenin başka bir yoludur,

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

Yalnızca bu yöntemin çalıştığı ve diğer yöntemlerin başarısız olduğu örneklerle karşılaştım. Belki de CMake'in en son sürümüyle ilgisi vardır.


9
Bu yalnızca SADECE C ++ derleyicisi kullanıyorsanız çalışır. Ayrıca CC derleyicisini kullanıyorsanız başarısız olur.
Emmanuel

5
add_definitionsyalnızca TANIMLAR, yani -D SOMETHING eklemek için kullanılır. @Emmanuel'in dediği gibi, birçok durumda çalışmaz.
xuhdev

Bunu daha önce kullandım ama add_definitionsbayrakları ayarlamak için yapılmadı çünkü bir C dosyası dahil ederken sorunları vardı .
Jan Segre

5

Benim için işe yarayan CMakeLists.txt dosyasında aşağıdaki satırı ayarlamaktır:

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

Bu komutun ayarlanması, derleyici için C ++ 11 özelliklerini etkinleştirir ve komutu yürüttükten sonra , kodunuzda cmake ..kullanabilmeniz range based for loopsve hatasız olarak derleyebilmeniz gerekir.


Bu, sonuçta, arzu edilmeyebilecek bayrağı kullanacağı -std=c++11gibi set (CMAKE_CXX_STANDARD 11), tam olarak istiyorsanız en iyi cevaptır -std=gnu++11.
Antonio

2
@Antonioset (CMAKE_CXX_EXTENSIONS OFF)
mloskot

4

Her zaman en son C ++ standardını etkinleştirmek istiyorsanız, işte David Grayson'un cevabının uzantısı, CMAKE_CXX_STANDARD için 17 ve 20 değerlerinin sonları (CMake 3.8 ve CMake 3.11) ışığında:

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)

(Bu kodu set (CMAKE_CXX_STANDARD 11)bağlantılı cevap yerine kullanın .)


2

Bence sadece bu iki çizgi yeterli.

set(CMAKE_CXX_STANDARD 11)

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

1
Bu, bir projedeki tüm hedefler aynı C ++ standardını kullandığında anlamlıdır (örneğin, derlenmiş tüm kitaplıklar ve yürütülebilir dosyalar C ++ 11 kullanır). Aksi takdirde, target_compile_featuresdiğer cevaplarda gösterildiği gibi her bir hedef için uygulanan Cmake işlevi daha önerilen bir yaklaşımdır.
Allan

1

Modern cmake, derleyicileri belirli bir C ++ sürümünü kullanacak şekilde yapılandırmanın daha basit yollarını sunar. Herkesin yapması gereken tek şey, ilgili hedef özellikleri ayarlamaktır. Cmake tarafından desteklenen özellikler arasında, belirli bir C ++ sürümünü desteklemek için derleyicilerin nasıl yapılandırılacağını belirlemek için kullanılan özellikler şunlardır:

  • CXX_STANDARDHedefi oluşturmak için özellikleri istenen C ++ standardını ayarlar. Bunu 11hedef C ++ 11 olarak ayarlayın .

  • CXX_EXTENSIONS, derleyiciye özel uzantıların istenip istenmediğini belirten bir boole. Bunu olarak ayarlamak, Offderleyiciye özgü uzantıların desteğini devre dışı bırakır.

Göstermek için, a'nın minimal bir çalışma örneği 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

OS X ve Homebrew LLVM ile ilgili:

Bundan sonra cmake_minimum_required (VERSION 3.3) ve project () 'i çağırmayı unutmayın!

Veya CMake, project()satır 1'den önce örtük olarak ekleyerek Clang sürüm algılaması ve muhtemelen diğer türden sorunlara neden olur. İşte ilgili bir konu .


2
Soru özellikle OSX veya LVVM ile ilgili değil. Ayrıca, CMake v3.x için C ++ 11 geliştirme gerektirmez. Clang sürüm algılama gelince - OP'nin sorduğu şey bu değil.
einpoklum
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.