2017-03-16 746 views
15

GCC 4.x不接受用於C++ 14代碼的--std=c++14開關 - 取而代之,它需要--std=c++1y。後來的版本採取--std=c++1z,但(可能)不是--std=c++17尚未設置(寫在2016年)。也許在C++ 11中也存在類似的問題。如何讓CMake通過基於GCC版本的std = C++ 14/C++ 1y或C++ 17/C++ 1z?

是否CMake的有一些設施(也許模塊)根據GCC版本來傳遞正確的開關?

+0

* 「也許還有與C++ 11類似的問題。」 *這將是C++ 11 VS的C++ 0x,前者是在gcc4.7/8左右推出。 –

+0

順便說一句,即使在支持現代編譯器的編譯器上,舊開關(0x,1y,1z)也能正常工作,所以沒有*真正的*需要得到這個「正確」。 –

+1

有**是需要得到這個「正確的」,因爲傳遞原始編譯器標誌是一個CMake反模式和對元生成系統/生成系統生成器的整個概念。 –

回答

30

當想要指定一個特定的C++版本,推薦的方法通過CMake 3.1做到這一點,後面是使用CXX_STANDARDCXX_STANDARD_REQUIREDCXX_EXTENSIONS目標屬性,或者它們的變量的等同物來指定目標默認。全部細節,可以發現here,但短期的版本是這樣的:

cmake_minimum_required(VERSION 3.1) 
project(Example) 

set(CMAKE_CXX_STANDARD 14) 
set(CMAKE_CXX_STANDARD_REQUIRED ON) 
set(CMAKE_CXX_EXTENSIONS OFF) 
# ... Define targets, etc. as usual 

CMake的應該然後選擇基於請求的C++標準適當的編譯器標誌是什麼編譯器支持,或沒有錯誤,如果它沒有按」 t支持所要求的標準。

還應當指出的是,CMake的可升級的目標使用比其CXX_STANDARD目標屬性指定的一個更高的語言標準。使用compile feature requirements(如@FlorianWolters答案中所述)可以提高語言標準的要求。事實上,CMake將始終選擇CXX_STANDARD目標屬性或目標上設置的編譯功能要求所指定的更強的語言要求。還要注意的是,CMake的文件爲3.10.1不能準確地反映CXX_EXTENSIONS與編譯功能的交互方式,如CXX_EXTENSIONS纔會生效,如果也爲最常見的編譯器指定CXX_STANDARD(因爲它們與一個編譯器標誌一起指定)。

7

檢查編譯器是否支持標誌?也許類似

include(CheckCXXCompilerFlag) 

# Check for standard to use 
check_cxx_compiler_flag(-std=c++17 HAVE_FLAG_STD_CXX17) 
if(HAVE_FLAG_STD_CXX17) 
    # Have -std=c++17, use it 
else() 
    check_cxx_compiler_flag(-std=c++1z HAVE_FLAG_STD_CXX1Z) 
    if(HAVE_FLAG_STD_CXX1Z) 
     # Have -std=c++1z, use it 
    else() 
     # And so on and on... 
    endif() 
endif() 
+2

@einpoklum沒有猜測,我一直在使用這個確切的代碼幾年沒有問題。使用GCC和Clang(上次我嘗試不支持'-std = C++ 17'選項)。 –

7

現代CMake的代碼應使用target_compile_features命令來請求特定的C++標準。這可以僅指定爲構建要求(PRIVATE),僅指定使用要求(INTERFACE)或構建和使用要求(PUBLIC)。

例子:

cmake_minimum_required(VERSION 3.9.4) 

project(cpp-snippets) 
add_executable(cpp-snippets "main.cpp") 
target_compile_features(cpp-snippets PRIVATE cxx_std_17) 

參考需要語言標準官方的CMake文件中的cmake-compile-features瞭解更多的部分

+0

什麼是「構建要求」而不是「使用要求」? – einpoklum

+2

還應該強調,對cxx_std_YY元功能的支持也僅在CMake 3中添加。8,而'CXX_STANDARD'目標屬性系列已經存在很長時間了,而'cxx_std_YY'元函數本身並不能控制是否可以使用編譯器擴展。 –

+1

@einpoklum如答案中所用,_build requirements_指的是構建目標本身所需的東西,而_usage requirements_是任何鏈接到目標的東西都將作爲需求繼承的東西。 –