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版本來傳遞正確的開關?
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版本來傳遞正確的開關?
當想要指定一個特定的C++版本,推薦的方法通過CMake 3.1做到這一點,後面是使用CXX_STANDARD
,CXX_STANDARD_REQUIRED
和CXX_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
(因爲它們與一個編譯器標誌一起指定)。
檢查編譯器是否支持標誌?也許類似
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()
@einpoklum沒有猜測,我一直在使用這個確切的代碼幾年沒有問題。使用GCC和Clang(上次我嘗試不支持'-std = C++ 17'選項)。 –
現代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瞭解更多的部分。
什麼是「構建要求」而不是「使用要求」? – einpoklum
還應該強調,對cxx_std_YY元功能的支持也僅在CMake 3中添加。8,而'CXX_STANDARD'目標屬性系列已經存在很長時間了,而'cxx_std_YY'元函數本身並不能控制是否可以使用編譯器擴展。 –
@einpoklum如答案中所用,_build requirements_指的是構建目標本身所需的東西,而_usage requirements_是任何鏈接到目標的東西都將作爲需求繼承的東西。 –
* 「也許還有與C++ 11類似的問題。」 *這將是C++ 11 VS的C++ 0x,前者是在gcc4.7/8左右推出。 –
順便說一句,即使在支持現代編譯器的編譯器上,舊開關(0x,1y,1z)也能正常工作,所以沒有*真正的*需要得到這個「正確」。 –
有**是需要得到這個「正確的」,因爲傳遞原始編譯器標誌是一個CMake反模式和對元生成系統/生成系統生成器的整個概念。 –