返回介绍

1.10 使用控制流

发布于 2025-05-06 21:45:53 字数 4411 浏览 0 评论 0 收藏

NOTE : 此示例代码可以在 https://github.com/dev-cafe/cmake-cookbook/tree/v1.0/chapter-01/recipe-10 中找到,有一个 C++示例。该示例在 CMake 3.5 版(或更高版本) 中是有效的,并且已经在 GNU/Linux、macOS 和 Windows 上进行过测试。

本章前面的示例中,已经使用过 if-else-endif 。CMake 还提供了创建循环的语言工具: foreach endforeachwhile-endwhile 。两者都可以与 break 结合使用,以便尽早从循环中跳出。本示例将展示如何使用 foreach ,来循环源文件列表。我们将应用这样的循环,在引入新目标的前提下,来为一组源文件进行优化降级。

准备工作

将重用第 8 节中的几何示例,目标是通过将一些源代码汇集到一个列表中,从而微调编译器的优化。

具体实施

下面是 CMakeLists.txt 中要的详细步骤:

  1. 与示例 8 中一样,指定了 CMake 的最低版本、项目名称和语言,并声明了几何库目标:
    cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
    project(recipe-10 LANGUAGES CXX)
    add_library(geometry
      STATIC
        geometry_circle.cpp
        geometry_circle.hpp
        geometry_polygon.cpp
        geometry_polygon.hpp
        geometry_rhombus.cpp
        geometry_rhombus.hpp
        geometry_square.cpp
        geometry_square.hpp
      )
  2. 使用 -O3 编译器优化级别编译库,对目标设置一个私有编译器选项:
    target_compile_options(geometry
      PRIVATE
          -O3
      )
  3. 然后,生成一个源文件列表,以较低的优化选项进行编译:
    list(
      APPEND sources_with_lower_optimization
        geometry_circle.cpp
        geometry_rhombus.cpp
      )
  4. 循环这些源文件,将它们的优化级别调到 -O2 。使用它们的源文件属性完成:
    message(STATUS "Setting source properties using IN LISTS syntax:")
    foreach(_source IN LISTS sources_with_lower_optimization)
      set_source_files_properties(${_source} PROPERTIES COMPILE_FLAGS -O2)
      message(STATUS "Appending -O2 flag for ${_source}")
    endforeach()
  5. 为了确保设置属性,再次循环并在打印每个源文件的 COMPILE_FLAGS 属性:
    message(STATUS "Querying sources properties using plain syntax:")
    foreach(_source ${sources_with_lower_optimization})
      get_source_file_property(_flags ${_source} COMPILE_FLAGS)
      message(STATUS "Source ${_source} has the following extra COMPILE_FLAGS: ${_flags}")
    endforeach()
  6. 最后,添加 compute-areas 可执行目标,并将 geometry 库连接上去:
    add_executable(compute-areas compute-areas.cpp)
    target_link_libraries(compute-areas geometry)
  7. 验证在配置步骤中正确设置了标志:
    $ mkdir -p build
    $ cd build
    $ cmake ..
    ​
    ...
    -- Setting source properties using IN LISTS syntax:
    -- Appending -O2 flag for geometry_circle.cpp
    -- Appending -O2 flag for geometry_rhombus.cpp
    -- Querying sources properties using plain syntax:
    -- Source geometry_circle.cpp has the following extra COMPILE_FLAGS: -O2
    -- Source geometry_rhombus.cpp has the following extra COMPILE_FLAGS: -O2
  8. 最后,还使用 VERBOSE=1 检查构建步骤。将看到 -O2 标志添加在 -O3 标志之后,但是最后一个优化级别标志(在本例中是 -O2 ) 不同:
    $ cmake --build . -- VERBOSE=1

工作原理

foreach-endforeach 语法可用于在变量列表上,表示重复特定任务。本示例中,使用它来操作、设置和获取项目中特定文件的编译器标志。CMake 代码片段中引入了另外两个新命令:

  • set_source_files_properties(file PROPERTIES property value) ,它将属性设置为给定文件的传递值。与目标非常相似,文件在 CMake 中也有属性,允许对构建系统进行非常细粒度的控制。源文件的可用属性列表可以在这里找到: https://cmake.org/cmake/help/v3.5/manual/cmake-properties.7.html#source-file-properties
  • get_source_file_property(VAR file property) ,检索给定文件所需属性的值,并将其存储在 CMake VAR 变量中。

NOTE : CMake 中,列表是用分号分隔的字符串组。列表可以由 listset 命令创建。例如, set(var a b c d e)list(APPEND a b c d e) 都创建了列表 a;b;c;d;e

TIPS : 为了对一组文件降低优化,将它们收集到一个单独的目标(库) 中,并为这个目标显式地设置优化级别,而不是附加一个标志,这样可能会更简洁,不过在本示例中,我们的重点是 foreach-endforeach

更多信息

foreach() 的四种使用方式:

  • foreach(loop_var arg1 arg2 ...) : 其中提供循环变量和显式项列表。当为 sources_with_lower_optimization 中的项打印编译器标志集时,使用此表单。注意,如果项目列表位于变量中,则必须显式展开它;也就是说, ${sources_with_lower_optimization} 必须作为参数传递。
  • 通过指定一个范围,可以对整数进行循环,例如: foreach(loop_var range total)foreach(loop_var range start stop [step])
  • 对列表值变量的循环,例如: foreach(loop_var IN LISTS [list1[...]]) 。参数解释为列表,其内容就会自动展开。
  • 对变量的循环,例如: foreach(loop_var IN ITEMS [item1 [...]]) 。参数的内容没有展开。

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。