cmake 变量总结

CMakeLists中的变量

常规变量

CMakeLists.txt中的常规变量有作用域的, 变量分以下两种变量:

  1. 常规变量set(abc "123")
  2. 缓存变量set(abc "123" CACHE STRING ""), 在CMakeLists.txt构造以后,会在CMakeCache.txt中有所有缓存变量的记录.

常规变量有如下特点:

  1. 常规变量每次重新创建, 没有缓存
  2. 常规变量使用set(abc "123")的方式创建
  3. 其他变量要引用这个创建的变量,需要用解引用方法${}, 例如:set(bcd "${abc}xyz"), 此时bcd的值是123xyz
  4. 常规变量受作用域影响, 作用域的变化会产生父作用域和子作用域的关系, 子作用域中会继承所有的父作用的常规变量
    1. functionadd_subdirectory 内部会创建新的作用域!!!新作用域内会继承父作用域的变量, 改变子作用域中的变量的值,不会影响父作用域中变量的值
    2. includemacro 并不会创建新的作用域!!! 因此, 在这内容中,修改变量会影响变量的值
    3. 如果在子作用域中, 如果想修改父作用域中的变量的值, 需要使用PARENT_SCOPE关键字 -- set(abc "786" PARENT_SCOPE). 注意这里不会改变子作用域中的abc的值, 只会修改父作用域中abc的值
  5. 常规变量使用unset(abc)来重置某个变量在当前作用域的值
    变量以外,我们在命令行中使用的-D参数也是声明缓存变量的方式.

变量的引用于解引用${...}:

cmake_minimum_required(VERSION 2.8)
project(foo NONE)

set(a "xyz")

set(b "${a}_321")
set(${a}_1 "456")
set(variable_${a} "${a} + ${b} + 155")

message("b: '${b}'")
message("xyz_1: '${xyz_1}'")
message("variable_xyz: '${variable_xyz}'")

 

[usage-of-variables]> rm -rf _builds
[usage-of-variables]> cmake -Hdereference -B_builds
b: 'xyz_321'
xyz_1: '456'
variable_xyz: 'xyz + xyz_321 + 155'
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds

嵌套使用${...}:

cmake_minimum_required(VERSION 2.8)
project(foo)

foreach(lang C CXX)
  message("Compiler for language ${lang}: ${CMAKE_${lang}_COMPILER}")
  foreach(build_type DEBUG RELEASE RELWITHDEBINFO MINSIZEREL)
    message("Flags for language ${lang} + build type ${build_type}: ${CMAKE_${lang}_FLAGS_${build_type}}")
  endforeach()
endforeach()

 

Compiler for language C: /usr/bin/cc
Flags for language C + build type DEBUG: -g
Flags for language C + build type RELEASE: -O3 -DNDEBUG
Flags for language C + build type RELWITHDEBINFO: -O2 -g -DNDEBUG
Flags for language C + build type MINSIZEREL: -Os -DNDEBUG
Compiler for language CXX: /usr/bin/c++
Flags for language CXX + build type DEBUG: -g
Flags for language CXX + build type RELEASE: -O3 -DNDEBUG
Flags for language CXX + build type RELWITHDEBINFO: -O2 -g -DNDEBUG
Flags for language CXX + build type MINSIZEREL: -Os -DNDEBUG

其他的例如 list 列表,常规使用比较少, 可以自己已查资料

需要小结的是:

  1. All variables have a string type
  2. List is nothing but string, elements of list separated by ;
  3. The way how variables are interpreted depends on the command
  4. Do not give same names for cache and regular variables
  5. add_subdirectory and function create new scope
  6. include and macro work in the current scope

缓存变量(全局变量)

缓存变量由如下特点:

  1. 缓存变量是全局作用域, 变量的值会从CMakeCache.txt中获取,缓存变量在写入CMakeCache.txt以后, 每次都从这个缓存文件中读取该值, 而不会重新调用set(... CACHE ...)!!!(Cache变量只会初始化一次,在CMakeCache.txt中存储以后, 多次调用set(... CACHE ...)不起作用!!!)
  2. 缓存变量的常规初始化的方式是set(abc "789" CACHE STRING "")
  3. 当常规变量和缓存变量重名时, 如果缓存变量声明在后面, 会覆盖常规变量
  4. 除了使用set(... CACHE ...)可以声明缓存, 也可以在命令行使用-Dxxx=xxx修改缓存变量的值!!!
  5. 如果某个Cache变量已经存在于CMakeCache.txt中, 代码中的set(... CACHE ...)将不会对这个值有影响, 如果我们在代码中需要强制修改Cache变量的值, 需要使用FORCE字段 --- set(abc "123" CACHE STRING "" FORCE)

最佳实践, 对于全局Cache变量太多,我们最好将他们放在一个单独的文件, 然后在调用CMake .. -C cache.cmake方法将这个文件加载进去.

 

# cache.cmake

set(A "123" CACHE STRING "")
set(B "456" CACHE STRING "")
set(C "789" CACHE STRING "")

 

# CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(foo NONE)

message("A: ${A}")
message("B: ${B}")
message("C: ${C}")

 

[usage-of-variables]> rm -rf _builds
[usage-of-variables]> cmake -C initial-cache/cache.cmake -Hinitial-cache -B_builds
loading initial cache file initial-cache/cache.cmake
A: 123
B: 456
C: 789
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds

option() 命令创建的是一个缓存变量

最佳实践, 由于Cache变量的全局性特点, 用于做开关, 使用option:

 

# top-level CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(zoo)

add_subdirectory(boo)
add_subdirectory(foo)

 

# foo/CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(foo)

option(FOO_FEATURE_1 "Enable feature 1" OFF)
option(FOO_FEATURE_2 "Enable feature 2" OFF)

 

# boo/CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(boo)

option(BOO_FEATURE_1 "Enable feature 1" ON)
option(BOO_FEATURE_2 "Enable feature 2" ON)

总结:

  1. Use cache to set global variables
  2. Cache variables fits perfectly for expressing customized options: default value and respect user’s value
  3. Type of cache variable helps CMake-GUI users
  4. Prefixes should be used to avoid clashing because of the global nature of cache variables

环境变量 Environment variables

环境变量可以使用$ENV{...}访问:

 

cmake_minimum_required(VERSION 2.8)
project(foo NONE)

message("Environment variable USERNAME: $ENV{USERNAME}")

 

[usage-of-variables]> rm -rf _builds
[usage-of-variables]> echo $USERNAME
ruslo
[usage-of-variables]> export USERNAME
[usage-of-variables]> cmake -Hread-env -B_builds
Environment variable USERNAME: ruslo
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds

可以使用set(ENV{...})来设置环境变量:

 

cmake_minimum_required(VERSION 2.8)
project(foo NONE)

set(ENV{USERNAME} "Jane Doe")
message("Environment variable USERNAME: $ENV{USERNAME}")

 

[usage-of-variables]> rm -rf _builds
[usage-of-variables]> echo $USERNAME
ruslo
[usage-of-variables]> export USERNAME
[usage-of-variables]> cmake -Hset-env -B_builds
Environment variable USERNAME: Jane Doe
-- Configuring done
-- Generating done
-- Build files have been written to: /.../usage-of-variables/_builds

总结:

  1. CMake can set, unset and read environment variables
  2. Check carefully configure-build steps where you set environment variables
  3. Child processes will inherit environment variables of parent
  4. Do not make your CMake code depends on environment variable if that variable may change

CMake的代码执行的过程

源码树(source-tree):

CMakeLists.txt一般会通过add_subdirectory方法给source-tree添加节点, 而CMAKE_CURRENT_SOURCE_DIR变量就是当前处理节点的全路径, 而整个source-tree的根节点则是CMAKE_SOURCE_DIR.

二进制树(binary-tree):

在调用CMake命令编译以后,生成的文件夹是一个编译结果二进制树. 其中,CMAKE_BINARY_DIR是二进制树的树根, CMAKE_CURRENT_BINARY_DIR是当前处理的二进制树的节点.

CMakeLists.txt的编写过程中, 我们可以用CMake module结合include()命令来重用代码. 常见的module是*.cmake

不要用include命令加载Find*.cmake模块!!!它有专用命令find_package

如果我们有一个专门存放的cmake module的文件夹, 我们可以将它添加到CMAKE_MODULE_PATH变量中, 最好使用list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/modules"):

 

# Top level CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(foo NONE)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/modules")

include(MyModule)

 

# modules/MyModule.cmake

message("Hello from MyModule!")

除此之外, 一下是一些常用的变量:

  1. CMAKE_CURRENT_LIST_DIRCMAKE_CURRENT_LIST_FILE

可以用下面一个实例展示:

 

# Top-level CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(foo NONE)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")

include(mymodule)

 

# cmake/mymodule.cmake

message("Full path to module: ${CMAKE_CURRENT_LIST_FILE}")
message("Module located in directory: ${CMAKE_CURRENT_LIST_DIR}")

 

[cmake-sources]> rm -rf _builds
[cmake-sources]> cmake -Hpath-to-module -B_builds
Full path to module: /.../cmake-sources/path-to-module/cmake/mymodule.cmake
Module located in directory: /.../cmake-sources/path-to-module/cmake
-- Configuring done
-- Generating done
-- Build files have been written to: /.../cmake-sources/_builds

下面一个图表现几个常见的变量的关系:

关系

  1. CMAKE_SOURCE_DIR/CMAKE_BINARY_DIR these variables point to the root of the source/binary trees. If your project will be added to another project as a subproject by add_subdirectory, the locations like ${CMAKE_SOURCE_DIR}/my-resource.txt will point to <top-level>/my-resource.txtinstead of <my-project>/my-resource.txt
  2. PROJECT_SOURCE_DIR/PROJECT_BINARY_DIR these variables are better then previous but still have kind of a global nature. You should change all paths related to PROJECT_SOURCE_DIR if you decide to move declaration of your project or decide to detach some part of the code and add new project command in the middle of the source tree. Consider using extra variable with clean separate purpose for such job set(FOO_MY_RESOURCES "${CMAKE_CURRENT_LIST_DIR}/resources") instead of referring to ${PROJECT_SOURCE_DIR}/resources.
  3. CMAKE_CURRENT_SOURCE_DIR this is a directory with CMakeLists.txt. If you’re using this variable internally you can substitute is with CMAKE_CURRENT_LIST_DIR. In case you’re creating module for external usage consider moving all functionality to function.

add_executable

 

cmake_minimum_required(VERSION 2.8)
project(foo)

add_executable(foo main.cpp)

注意这里定义的 foo是一个Target, 名称是全局范围的变量, 并且唯一的!!!

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值