CMake 学习笔记(target_compile_features())
这一篇博客讲一讲target_compile_features()。这条命令时 CMake 3.1 引入的。在这个之前。如果我们要设置C++ 编译开启 C++11 的支持。需要用如下的两行:
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
这两行对编译器的设置是全局的,也就是整个项目中每一个 C++ 文件编译时都会开启 C++11 的支持。在小项目中没有任何问题。但是如果项目比较大,包含了多个库。有可能编译某些库时就不能开启 C++11。因此我们需要更加细粒度的控制。找个就要用到 target_compile_features()。
下面是个简单的例子,只是一个代码片段:
target_compile_features(Tutorial INTERFACE cxx_std_11)
可以看到一行代码就可以开启C++编译器的支持。其实,大多数时候我们的编译器都是默认支持C++ 的比较高的标准的。上面这行代码主要是当编译器不支持某个特性时,能够报警提示我们。另外就是有时C++的不同版本的标准不兼容时,我们需要告诉编译器我们用的是哪个标准。这时通常是我们要告诉编译器我们的代码用到了某一个特别低的C++ 标准,不要开启对高标准的支持。
大多数的cmake 教程或者官方文档中,都不是我上面那种写法,而是像下面这样:
add_library(tutorial_compiler_flags INTERFACE)
target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
target_link_libraries(Tutorial PUBLIC tutorial_compiler_flags)
这三行第一行引入了一个接口库 tutorial_compiler_flags,找个库其实是个虚拟的库,并没有任何的文件。然后给这个接口库设置了一个编译特性cxx_std_11。那么只要依赖找个虚拟库的对象,在编译时都会使用到cxx_std_11找个特征。
上面这样写的好处是 tutorial_compiler_flags 可以被许多个目标所使用。如果项目中只有一个目标需要用到这个 compile_features ,那就不如像我那样写一行。
对于 C++ 语言来说,CMake 支持的 compile_features 包括下面这些:
-
cxx_std_98
-
cxx_std_11
-
cxx_std_14
-
cxx_std_17
-
cxx_std_20
-
cxx_std_23
-
cxx_std_26
我们知道编译器对C++ 新标准的支持是滞后的。有时,编译器只是部分的支持了C++ 的某个标准。CMake 也有几个这样的 compile_features 用来保证编译器支持某个特定的特性:
- cxx_alias_templates
- cxx_alignas
- cxx_alignof
- cxx_attributes
- cxx_auto_type
- cxx_constexpr
- cxx_decltype_incomplete_return_types
- cxx_decltype
- 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
以上这些是 C++ 的特性,具体每一项的含义可以查看 CMake 的帮助文档。https://cmake.org/cmake/help/latest/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html#prop_gbl:CMAKE_CXX_KNOWN_FEATURES
除此之外还有 C 语言的 compile_features:
- c_std_90
- c_std_99
- c_std_11
- c_std_17
- c_std_23
- c_function_prototypes
- c_restrict :restrict keyword ,C99 中引入的特性
- c_static_assert : Static assert C11 中引入的特性
- c_variadic_macros :Variadic macros, C99 中引入的特性
除此之外,CMake 还支持 CUDA 的一些 features.
- cuda_std_03
- cuda_std_11
- cuda_std_14
- cuda_std_17
- cuda_std_20
- cuda_std_23
- cuda_std_26