Basic 11-cpp-standard
# 设置编译器的 C 语言标准
CMake 提供了三种方法来设置编译器的 C 语言标准:
- common-method: 在大部分版本的 CMake 上都能使用
- cxx-standard: 使用变量
CMAKE_CXX_STANDARD, 在 CMake3.1 版本被引入。 - complie-features: 使用函数
target_compile_features, 在 CMake3.1 版本被引入。
# common-method
# 介绍
这种方法在大部分的 CMake 版中上都能被使用,但是我不建议使用这种方法。因为新版本的 CMake 引入了 target_complie_features ,使得 C 标准的选择是面向 target 的。
本例的目录🌲:
A-hello-cmake$ tree
.
├── CMakeLists.txt
├── main.cpp
2
3
4
CMakeLists.txt:
# Set the minimum version of CMake that can be used
# To find the cmake version run
# $ cmake --version
cmake_minimum_required(VERSION 2.8)
# Set the project name
project (hello_cpp11)
# try conditional compilation
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
# check results and add flag
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()
# Add an executable
add_executable(hello_cpp11 main.cpp)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 概念解释
# 检查编译标志 (Compile Flag)
CMake 支持向函数 CMAKE_CXX_COMPILER_FLAG 中传入参数,然后检查该参数在默认的编译器中是否可用,并将判断结果保存到一个变量中。
举例:
include告诉 CMake 引入函数CheckCXXCompilerFlag,使得该函数可用- 通过函数
CHECK_CXX_COMPILER_FLAG检查参数"-std=c++11"在编译器中是否是可用的,然后将判断结果保存到变量COMPILER_SUPPORTS_CXX11中。
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
2
# 添加编译标志
在检查完编译标志是否可用后,就可以决定是否需要向变量 CMAKE_CXX_FLAGS 中添加次编译标志标志。举例:
其中 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 的作用是在当前编译标志 ${CMAKE_CXX_FLAGS} 的末尾添加新的标志 "-std=c++11"
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()
2
3
4
5
6
7
# 构建本例
$ mkdir build
$ cd build
$ cmake ..
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Check for working C compiler: /usr/lib/ccache/cc
-- Check for working C compiler: /usr/lib/ccache/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/lib/ccache/c++
-- Check for working CXX compiler: /usr/lib/ccache/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Performing Test COMPILER_SUPPORTS_CXX11
-- Performing Test COMPILER_SUPPORTS_CXX11 - Success
-- Performing Test COMPILER_SUPPORTS_CXX0X
-- Performing Test COMPILER_SUPPORTS_CXX0X - Success
-- Configuring done
-- Generating done
-- Build files have been written to: /home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/i-common-method/build
$ make
Scanning dependencies of target hello_cpp11
[ 50%] Building CXX object CMakeFiles/hello_cpp11.dir/main.cpp.o
[100%] Linking CXX executable hello_cpp11
[100%] Built target hello_cpp11
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# cxx-standard
# 介绍
本例展示了如何使用变量 CMAKE_CXX_STANDARD 来指定编译器编译的 C++ 版本。
本例的目录🌲:
A-hello-cmake$ tree
.
├── CMakeLists.txt
├── main.cpp
2
3
4
CMakeLists.txt
# Set the minimum version of CMake that can be used
# To find the cmake version run
# $ cmake --version
cmake_minimum_required(VERSION 3.1)
# Set the project name
project (hello_cpp11)
# set the C++ standard to C++ 11
set(CMAKE_CXX_STANDARD 11)
# Add an executable
add_executable(hello_cpp11 main.cpp)
2
3
4
5
6
7
8
9
10
11
12
13
# 概念解释
设置变量 CMAKE_CXX_STANDARD 会导致 CMakeLists.txt 中的所有目标都使用 CXX_STANDARD 来进行编译。
如果设置给 CMAKE_CXX_STANDARD 的值不存在,CMkae 会自动设置一个最近的 C++ 标志。比如你设置了 set(CMAKE_CXX_STANDARD 11) 并且该标志在当前编译器不可用,最终可能会得到 -std=gnu0x ,并且不会报错。
# 构建本例
$ mkdir build
$ cd build
$ cmake ..
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Check for working C compiler: /usr/lib/ccache/cc
-- Check for working C compiler: /usr/lib/ccache/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/lib/ccache/c++
-- Check for working CXX compiler: /usr/lib/ccache/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/ii-cxx-standard/build
$ make VERBOSE=1
/usr/bin/cmake -S/home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/ii-cxx-standard -B/home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/ii-cxx-standard/build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/ii-cxx-standard/build/CMakeFiles /home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/ii-cxx-standard/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/ii-cxx-standard/build'
make -f CMakeFiles/hello_cpp11.dir/build.make CMakeFiles/hello_cpp11.dir/depend
make[2]: Entering directory '/home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/ii-cxx-standard/build'
cd /home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/ii-cxx-standard/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/ii-cxx-standard /home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/ii-cxx-standard /home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/ii-cxx-standard/build /home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/ii-cxx-standard/build /home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/ii-cxx-standard/build/CMakeFiles/hello_cpp11.dir/DependInfo.cmake --color=
Dependee "/home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/ii-cxx-standard/build/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/ii-cxx-standard/build/CMakeFiles/hello_cpp11.dir/depend.internal".
Scanning dependencies of target hello_cpp11
make[2]: Leaving directory '/home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/ii-cxx-standard/build'
make -f CMakeFiles/hello_cpp11.dir/build.make CMakeFiles/hello_cpp11.dir/build
make[2]: Entering directory '/home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/ii-cxx-standard/build'
[ 50%] Building CXX object CMakeFiles/hello_cpp11.dir/main.cpp.o
/usr/lib/ccache/c++ -std=gnu++11 -o CMakeFiles/hello_cpp11.dir/main.cpp.o -c /home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/ii-cxx-standard/main.cpp
[100%] Linking CXX executable hello_cpp11
/usr/bin/cmake -E cmake_link_script CMakeFiles/hello_cpp11.dir/link.txt --verbose=1
/usr/lib/ccache/c++ -rdynamic CMakeFiles/hello_cpp11.dir/main.cpp.o -o hello_cpp11
make[2]: Leaving directory '/home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/ii-cxx-standard/build'
[100%] Built target hello_cpp11
make[1]: Leaving directory '/home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/ii-cxx-standard/build'
/usr/bin/cmake -E cmake_progress_start /home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/ii-cxx-standard/build/CMakeFiles 0
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# complie feature (推荐🌟🌟🌟🌟🌟)
# 介绍
本例介绍如何使用 Modern CMake 的 target_complie_feature 设置编译器使用的 C++ 版本。
在 Modern CMake 上,建议使用这种方法来设置编译器使用的 C++ 版本。
本例的目录🌲:
.
├── CMakeLists.txt
├── main.cpp
2
3
CMakeLists.txt:
# Set the minimum version of CMake that can be used
# To find the cmake version run
# $ cmake --version
cmake_minimum_required(VERSION 3.1)
# Set the project name
project (hello_cpp11)
# Add an executable
add_executable(hello_cpp11 main.cpp)
# set the C++ standard to the appropriate standard for using auto
target_compile_features(hello_cpp11 PUBLIC cxx_auto_type)
# Print the list of known compile features for this version of CMake
message("List of compile features: ${CMAKE_CXX_COMPILE_FEATURES}")
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 概念
# 使用 target_compile_features
使用 target_compile_features 的好处在于可以指定编译特征的可见性。关于 target_xxx 我在 Basic 03-static-library 有过具体讲解。
该函数可以使用的 feature 可以在CMAKE_CXX_COMPILE_FEATURES (opens new window) 中找到。
你可以使用 message("List of compile features: ${CMAKE_CXX_COMPILE_FEATURES}") 打印出所有可用的 complie feature。
# 构建本例
$ mkdir build
$ cd build
$ cmake ..
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Check for working C compiler: /usr/lib/ccache/cc
-- Check for working C compiler: /usr/lib/ccache/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/lib/ccache/c++
-- Check for working CXX compiler: /usr/lib/ccache/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
List of compile features: cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20
-- Configuring done
-- Generating done
-- Build files have been written to: /home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/iii-compile-features/build
$ make VERBOSE=1
/usr/bin/cmake -S/home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/iii-compile-features -B/home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/iii-compile-features/build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/iii-compile-features/build/CMakeFiles /home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/iii-compile-features/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/iii-compile-features/build'
make -f CMakeFiles/hello_cpp11.dir/build.make CMakeFiles/hello_cpp11.dir/depend
make[2]: Entering directory '/home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/iii-compile-features/build'
cd /home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/iii-compile-features/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/iii-compile-features /home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/iii-compile-features /home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/iii-compile-features/build /home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/iii-compile-features/build /home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/iii-compile-features/build/CMakeFiles/hello_cpp11.dir/DependInfo.cmake --color=
Dependee "/home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/iii-compile-features/build/CMakeFiles/hello_cpp11.dir/DependInfo.cmake" is newer than depender "/home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/iii-compile-features/build/CMakeFiles/hello_cpp11.dir/depend.internal".
Dependee "/home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/iii-compile-features/build/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/iii-compile-features/build/CMakeFiles/hello_cpp11.dir/depend.internal".
Scanning dependencies of target hello_cpp11
make[2]: Leaving directory '/home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/iii-compile-features/build'
make -f CMakeFiles/hello_cpp11.dir/build.make CMakeFiles/hello_cpp11.dir/build
make[2]: Entering directory '/home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/iii-compile-features/build'
[ 50%] Building CXX object CMakeFiles/hello_cpp11.dir/main.cpp.o
/usr/lib/ccache/c++ -o CMakeFiles/hello_cpp11.dir/main.cpp.o -c /home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/iii-compile-features/main.cpp
[100%] Linking CXX executable hello_cpp11
/usr/bin/cmake -E cmake_link_script CMakeFiles/hello_cpp11.dir/link.txt --verbose=1
/usr/lib/ccache/c++ -rdynamic CMakeFiles/hello_cpp11.dir/main.cpp.o -o hello_cpp11
make[2]: Leaving directory '/home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/iii-compile-features/build'
[100%] Built target hello_cpp11
make[1]: Leaving directory '/home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/iii-compile-features/build'
/usr/bin/cmake -E cmake_progress_start /home/tartarus/cmake/cmake-examples/01-basic/L-cpp-standard/iii-compile-features/build/CMakeFiles 0
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46