
【CMake系列】(七)常用变量、函数以及模块
xizhibei用了 CMake 较长一段时间后,在笔记本里面记录了不少知识,这些知识其实应该放在这个系列文章的开始来讲,因为算是很入门的部分,这里就简单总结下。
配置期间
生成配置文件
| 1 | 
 | 
比如,你可以将 cmake 中,project 命令中设置的版本,通过这个方式传递给程序:
| 1 | 
 | 
通过两个 @ 符号,就可以将 cmake 中的变量传递到我们所需要编译的程序中。
防手贱
禁止在源目录编译以及修改,可以在不小心在当前目录编译的时候,报错退出,防止污染源代码:
| 1 | 
 | 
第三方库的查找
这里需要用到 CMAKE_FIND_ROOT_PATH 以及 CMAKE_PREFIX_PATH,因为 CMake 回去系统默认的地方查找对应的库,如果你需要用到放在其他地方的库,可以在这个变量中添加。
另外,对于单个库,也可以使用这两个变量:
- <PackageName>_ROOT:用来指定头文件以及库、可执行文件的路径;
- <PackageName>_DIR:用来指定库的 CMake 文件路径;
编译期间
编译器
假如在系统中存在多种编译器或者版本,可以通过设置以下两个变量来设置 C 以及 C++ 的编译器:
| 1 | 
 | 
FLAGS
如果需要自定义编译配置,还可以设置以下的变量,大部分情况下,你都不需要配置,CMake 会根据环境以及其它变量自动配置:
| 1 | 
 | 
特性
如果你说需要上面的 FALGS 来配置 -std=c++17,那也不需要,你可以设置其他的变量来达到这个目的,比如全局的:
| 1 | 
 | 
以及更被建议的局部做法:
| 1 | 
 | 
另外,如果想要 -fPIC,也有专门的变量:CMAKE_POSITION_INDEPENDENT_CODE,当然,这个也建议在局部做:
| 1 | 
 | 
预处理定义
| 1 | 
 | 
类别
编译类别 CMAKE_BUILD_TYPE 我们常用的也就 Release 与 Debug,由于编译环境的不同,也会对这个值进行限制,具体需要参考 CMAKE_CONFIGURATION_TYPES,比如 还可以有 RelWithDebInfo 以及 MinSizeRel。
这个变量,会决定编译是否优化以及带上调试信息,千万不要给你们公司的私有程序以 Debug 模型发布出去了,原因?一个是代码没优化,性能会比较差,另外就是会泄露源码。
动态库与静态库
需要用到 BUILD_SHARED_LIBS 这个变量,常常被用到 option 里面提供给用户进行配置,这个变量控制的是 add_libary(myLib ...) 最后生成的类别。
或许你会奇怪为什么没有 BUILD_STATIC_LIBS,其实默认就是 static,也就是相当于 BUILD_SHARED_LIBS=OFF。
另外,还有个小技巧,如果你需要同时编译动态库与静态库,可以用类似以下的方式来做到:
| 1 | 
 | 
几个有用的模块
ExternalProject 就不用多说了,前面在 【CMake 系列】(三)ExternalProject 实践 专门介绍过。
注意:这几个模块需要通过 include 来引入后才能使用。
CMakePrintHelpers
非常适合用来调试,cmake_print_variables 帮助你打印出变量的值以及 cmake_print_properties 可以打印出 target 中的一些属性。
下面就是一个打印出 include 路径的例子:
| 1 | 
 | 
WriteCompilerDetectionHeader
有些时候,为了写跨平台的代码,我们需要判别编译器是否支持一些特性,CMake 就提供了这个模块,它可以帮助你生成一个预定义头文件,帮你把一些编译器支持的特性全部罗列出来:
| 1 | 
 | 
这里的编译特性还可以有:
- cxx_constexpr
- cxx_deleted_functions
- cxx_extern_templates
- cxx_variadic_templates
- cxx_noexcept
- cxx_final
- cxx_override
FeatureSummary
这个模块适合在项目初始化完成的最后,打印出一些总结性信息:
| 1 | 
 | 
然后,你还可以给这个总结添加更多说明:
| 1 | 
 | 
这样,你就可以看到更多的总结信息了。
安装
这个就太简单了,但是又非常常见,怕初学者不清楚,这里就提示下:
直接设置 CMAKE_INSTALL_PREFIX 即可,最后执行安装命令的时候,会将对应的文件安装到制定的目录。
最后
上面简单罗列了我们团队项目中常用的,也是经过我挑选之后的,毕竟那么多的特性,不可能在这一篇文章中全部列出,详细的还是需要看 CMake 官方文档。另外,文中大部分的例子也是来自于 CMake 官方文档。


