美文网首页
CMake学习小结--变量

CMake学习小结--变量

作者: brownfeng | 来源:发表于2020-02-11 19:48 被阅读0次

CMake学习小结

参考资料

CGold的Cmake教程 -- 这个教程很新:

https://cgold.readthedocs.io/en/latest/overview.html

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, 名称是全局范围的变量, 并且唯一的!!!

相关文章

  • CMake学习小结--变量

    CMake学习小结 参考资料 CGold的Cmake教程 -- 这个教程很新: https://cgold.rea...

  • CMake学习

    CMake学习 参考自《Cmake Practice --Cjacker》 基本语法规则 变量的引用 变量使用${...

  • cmake学习小结

    CMake简介 CMake是个一个开源的跨平台自动化建构系统,用来管理软件建置的程序,并不依赖于某特定编译器,并可...

  • Boost非标准安装参考

    cmake有没有好的学习教程? - 知乎cmake 常用变量和常用环境变量查表手册---整理 . - 香格里拉(o...

  • cmake Ubuntu 环境下安装

    安装 在cmake官网下载cmake:https://cmake.org/download/ 解压 配置环境变量 ...

  • cmake 变量

    CMake 两种变量原理[https://www.cnblogs.com/ncuneugcj/p/9756324....

  • cmake

    添加编译器开关 可以通过CMAKE_C_FLAGS(C)变量和CMAKE_CXX_FLAGS(C++)变量设置。比如:

  • CMAKE语法摘要

    可以设置的变量 使用方式cmake -DCMAKE_INSTALL_PREFIX=yourpath 或在CMAKE...

  • CMake(二)一些实用参数参考

    一,关于CMake中的常用变量:1)CMAKE_BINARY_DIRPROJECT_BINARY_DIR _BIN...

  • Cmake使用摘要

    Cmake使用常识 Cmake设置变量与我们平时的编程语言不同,并不是如int a = 1这样设置的。Cmake中...

网友评论

      本文标题:CMake学习小结--变量

      本文链接:https://www.haomeiwen.com/subject/lwqffhtx.html