有时候,我们有这样的需求,当处理到某个地方的时候,后面的我们都不想处理或者不需要处理的时候,就可以提前结束当前的处理逻辑,回到父级去处理.在C/C++中,我们有break关键字跳出当前循环,continue关键字进入下一次循环,return关键字返回当前处理的函数.
cmake也提供了break(),continue(),return()命令.
- 如果调用return()命令的地方不在一个函数中,那将结束当前文件的处理,回到引用当前文件的地方.引入一个cmake脚本文件的方式可以是include()命令,也可以是add_subdirrectory()命令.
- 在函数中调用return()命令比较复杂,但是很重要.
在cmake 3.25版本之前,return()命令是没有参数的,从cmake3.25开始,return()命令有了类似block()命令的参数关键字:PROPAGATE,在这个关键字后面我们可以列出一些变量,这些变量在调用return()命令的时候会更新其值.
为了兼容旧版本,我们在使用return()命令的时候如果关键字参数:PROPAGATE,那么我们通常需要把CMP0140这个策略设置为NEW.
demo
目录结构顶层文件夹是021,下面有一个subdir文件夹,一个cmake文件,一个cmake脚本文件
顶层cmake文件:
cmake_minimum_required(VERSION 3.26 FATAL_ERROR)project(021)set(x 1)
set(y 2)message(STATUS "TOP before: x = [${x}]")
message(STATUS "TOP before: y = [${y}]")add_subdirectory(subdir)
# include(test_include.cmake)message(STATUS "TOP after: x = [${x}]")
message(STATUS "TOP after: y = [${y}]")
subdir文件夹下的cmake文件
cmake_minimum_required(VERSION 3.26 FATAL_ERROR)message(STATUS "sub before: x = [${x}]")
message(STATUS "sub before: y = [${y}]")set(x 3)
unset(y)message(STATUS "sub after: x = [${x}]")
message(STATUS "sub after: y = [${y}]")return(PROPAGATE x y)message(STATUS "sub after return x = [${x}]")
message(STATUS "sub after return y = [${y}]")
结果:
cmake脚本文件cmake内容:
cmake_minimum_required(VERSION 3.26 FATAL_ERROR)message(STATUS "sub before: x = [${x}]")
message(STATUS "sub before: y = [${y}]")set(x 3)
unset(y)message(STATUS "sub after: x = [${x}]")
message(STATUS "sub after: y = [${y}]")return()message(STATUS "sub after return x = [${x}]")
message(STATUS "sub after return y = [${y}]")
顶层cmake文件注释add_subdirectory(subdir) 包含include 脚本文件
cmake脚本文件:
cmake_minimum_required(VERSION 3.26 FATAL_ERROR)message(STATUS "sub before: x = [${x}]")
message(STATUS "sub before: y = [${y}]")set(x 3)
unset(y)message(STATUS "sub after: x = [${x}]")
message(STATUS "sub after: y = [${y}]")return()message(STATUS "sub after return x = [${x}]")
message(STATUS "sub after return y = [${y}]")
注意脚本文件大体上和subdir文件夹下的cmake类似不同的是,脚本文件的return()命令是空的.为啥是空的?因为return()命令是需要有父级作用域的,使用include的方式不是父级作用域,所以不用参数.
如果return()命令有值cmake会出错的.
结果是一样的
block()命令结合return()命令
修改顶层cmake文件
cmake_minimum_required(VERSION 3.26 FATAL_ERROR)project(021)set(x 1)
set(y 2)message(STATUS "TOP before: x = [${x}]")
message(STATUS "TOP before: y = [${y}]")block()add_subdirectory(subdir)message(STATUS "block after: x = [${x}]")message(STATUS "block after: y = [${y}]")endblock()# include(test_include.cmake)message(STATUS "TOP after: x = [${x}]")
message(STATUS "TOP after: y = [${y}]")
结果:
在subdir文件下下使用block
顶层cmake文件
cmake_minimum_required(VERSION 3.26 FATAL_ERROR)project(021)set(x 1)
set(y 2)message(STATUS "TOP before: x = [${x}]")
message(STATUS "TOP before: y = [${y}]")# block()# add_subdirectory(subdir)
# message(STATUS "block after: x = [${x}]")
# message(STATUS "block after: y = [${y}]")# endblock()
add_subdirectory(subdir)# include(test_include.cmake)message(STATUS "TOP after: x = [${x}]")
message(STATUS "TOP after: y = [${y}]")
subdir cmake文件
cmake_minimum_required(VERSION 3.26 FATAL_ERROR)message(STATUS "sub before: x = [${x}]")
message(STATUS "sub before: y = [${y}]")block()set(x 3)unset(y)message(STATUS "sub after: x = [${x}]")message(STATUS "sub after: y = [${y}]")return(PROPAGATE x y)
endblock()message(STATUS "sub after return x = [${x}]")
message(STATUS "sub after return y = [${y}]")
结果:
CMake另外一种类似与C/C++头文件防御的方式,在引入新的Cmake脚本文件的时候提前返回.
cmake各个版本通用的方式是这样的:
if (DEFINED cool_stuff_include_guard)return()
endif()set(cool_stuff_include_guard 1)
# ...
cmake 3.10开始,我们可以使用一条命令代替: include_guard()
include_guard()命令支持两个关键字,GLOBAL和DIRECTORY.一般情况下不需要.
- GLOBAL 关键字表示在全局范围内如果曾经处理过这个文件,那就直接返回.
- DIRECTORY 关键字只在当前目录作用域或者其子目录作用域范围内曾经处理过该文件才直接返回.