CMake Tutorial 巡礼(10)_添加生成表达式

CMake Tutorial 巡礼(10)_ 添加生成器表达式

这是本系列的第十一篇。
上一篇我们学习了如何选择静态库和动态库。这一篇我们来学习如何添加生成表达式。

本章导读

在这里插入图片描述

第十步 添加生成器表达式

Generator expressions are evaluated during build system generation to produce information specific to each build configuration.

Generator expressions (生成器表达式)在生成系统期间进行计算,以生成特定于每个生成配置的信息。

Generator expressions are allowed in the context of many target properties, such as LINK_LIBRARIES, INCLUDE_DIRECTORIES, COMPILE_DEFINITIONS and others. They may also be used when using commands to populate those properties, such as target_link_libraries(), target_include_directories(), target_compile_definitions() and others.

Generator expressions允许出现在很多目标属性的文本中,例如LINK_LIBRARIES, INCLUDE_DIRECTORIES, COMPILE_DEFINITIONS 及其他。它们在使用命令行时也会被填入其他命令中,例如 target_link_libraries(), target_include_directories(), target_compile_definitions() 及其他。

Generator expressions may be used to enable conditional linking, conditional definitions used when compiling, conditional include directories and more. The conditions may be based on the build configuration, target properties, platform information or any other queryable information.

Generator expressions (生成器表达式)可用作使能条件链接时,编译时使用条件编译时,条件包含目录时及更多情况下。这些情况均是基于生成参数,目标属性,平台信息以及其他可查询信息。

There are different types of generator expressions including Logical, Informational, and Output expressions.

Generator expressions (生成器表达式)有多种不同的类型,包含逻辑型、信息型,以及输出表达式。

Logical expressions are used to create conditional output. The basic expressions are the 0 and 1 expressions. A $<0:...> results in the empty string, and <1:...> results in the content of .... They can also be nested.

逻辑型表达式用于创建条件输出。基本表达式是0 1表达式。一个$<0:...> 将表示一个空字符串,<1:...> 则表示一个...串,它们也可以被嵌套。

A common usage of generator expressions is to conditionally add compiler flags, such as those for language levels or warnings. A nice pattern is to associate this information to an INTERFACE target allowing this information to propagate. Let’s start by constructing an INTERFACE target and specifying the required C++ standard level of 11 instead of using CMAKE_CXX_STANDARD.

一个常见的生成器表达式应用是条件地添加编译标志位,例如那些语言级别或警告。一种非常好的范式是将此信息关联到一个 INTERFACE (接口)目标,以允许这个信息进行传播。让我们从建立一个接口目标开始,并且替换使用CMAKE_CXX_STANDARD的方式来指定C++11标准。

So the following code:

所以代码如下:
CMakeLists.txt

# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

将会被替换成:

CMakeLists.txt

add_library(tutorial_compiler_flags INTERFACE)
target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)

Note: This upcoming section will require a change to the cmake_minimum_required() usage in the code. The Generator Expression that is about to be used was introduced in 3.15. Update the call to require that more recent version:

注意:下一节将要求更改代码中的 cmake_minimum_required()用法。将要使用的生成器表达式是在版本3.15中引入的。请更新调用此函数所需要的版本。

cmake_minimum_required(VERSION 3.15)

Next we add the desired compiler warning flags that we want for our project. As warning flags vary based on the compiler we use the COMPILE_LANG_AND_ID generator expression to control which flags to apply given a language and a set of compiler ids as seen below:

接下来,我们为项目添加所需的编译器警告标志。由于警告标志因编译器而异,我们使用 COMPILE_LANG_AND_ID生成器表达式来控制在给定语言和一组编译器ID的情况下应用哪些标志,如下所示:

set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>")
set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>")
target_compile_options(tutorial_compiler_flags INTERFACE
  "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>"
  "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
)

Looking at this we see that the warning flags are encapsulated inside a BUILD_INTERFACE condition. This is done so that consumers of our installed project will not inherit our warning flags.

我们看到,警告标志封装在BUILD_INTERFACE 条件中。这样做是为了使已安装项目的使用者不会继承我们的警告标志。

小白按: CMakeLists.txt修改后的全部代码如下所示:

cmake_minimum_required(VERSION 3.15)

# set the project name and version
project(Tutorial VERSION 1.0)

# specify the C++ standard
add_library(tutorial_compiler_flags INTERFACE)
target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)

set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>")
set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>")
target_compile_options(tutorial_compiler_flags INTERFACE
  "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>"
  "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
)

# control where the static and shared libraries are built so that on windows
# we don't need to tinker with the path to run the executable
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")

option(BUILD_SHARED_LIBS "Build using shared libraries" ON)

# configure a header file to pass the version number only
configure_file(TutorialConfig.h.in TutorialConfig.h)

# add the MathFunctions library
add_subdirectory(MathFunctions)

# add the executable
add_executable(Tutorial tutorial.cxx)
target_link_libraries(Tutorial PUBLIC MathFunctions)

# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(Tutorial PUBLIC
                           "${PROJECT_BINARY_DIR}"
                           )

# add the install targets
install(TARGETS Tutorial DESTINATION bin)
install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
  DESTINATION include
  )

# enable testing
include(CTest)

# does the application run
add_test(NAME Runs COMMAND Tutorial 25)

# does the usage message work?
add_test(NAME Usage COMMAND Tutorial)
set_tests_properties(Usage
  PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number"
  )

# define a function to simplify adding tests
function(do_test target arg result)
  add_test(NAME Comp${arg} COMMAND ${target} ${arg})
  set_tests_properties(Comp${arg}
    PROPERTIES PASS_REGULAR_EXPRESSION ${result}
    )
endfunction()

# do a bunch of result based tests
do_test(Tutorial 4 "4 is 2")
do_test(Tutorial 9 "9 is 3")
do_test(Tutorial 5 "5 is 2.236")
do_test(Tutorial 7 "7 is 2.645")
do_test(Tutorial 25 "25 is 5")
do_test(Tutorial -25 "-25 is (-nan|nan|0)")
do_test(Tutorial 0.0001 "0.0001 is 0.01")

include(InstallRequiredSystemLibraries)
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
set(CPACK_SOURCE_GENERATOR "TGZ")
include(CPack)

Exercise: Modify MathFunctions/CMakeLists.txt so that all targets have a target_link_libraries() call to tutorial_compiler_flags.

练习: 修改 MathFunctions/CMakeLists.txt 令所有的目标都有一个针对tutorial_compiler_flagstarget_link_libraries()调用。

小白按:对于这个小练习,小白也是没弄清楚该如何去弄。说句实在话,到了这个阶段,小白也不是特别理解这些功能的真正目的和使用场景。只能留待以后学习时再度体会。

下一篇我们将学习如何添加导出参数。

【水平所限,错漏难免,创作不易,轻喷勿骂】

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值