7

【CMake 系列】(七)常用变量、函数以及模块

 3 years ago
source link: https://blog.xizhibei.me/2020/06/02/cmake-7-common-var-func-and-modules/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

【CMake 系列】(七)常用变量、函数以及模块

0 Comments

用了 CMake 较长一段时间后,在笔记本里面记录了不少知识,这些知识其实应该放在这个系列文章的开始来讲,因为算是很入门的部分,这里就简单总结下。

生成配置文件

1
2
configure_file("${PROJECT_SOURCE_DIR}/include/config.h.in"
"${PROJECT_BINARY_DIR}/include/config.h")

比如,你可以将 cmake 中,project 命令中设置的版本,通过这个方式传递给程序:

1
2
3
4
5
6
7
8
// config.h.in
#pragma once

#define MY_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define MY_VERSION_MINOR @PROJECT_VERSION_MINOR@
#define MY_VERSION_PATCH @PROJECT_VERSION_PATCH@
#define MY_VERSION_TWEAK @PROJECT_VERSION_TWEAK@
#define MY_VERSION "@PROJECT_VERSION@"

通过两个 @ 符号,就可以将 cmake 中的变量传递到我们所需要编译的程序中。

禁止在源目录编译以及修改,可以在不小心在当前目录编译的时候,报错退出,防止污染源代码:

1
2
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
set(CMAKE_DISABLE_SOURCE_CHANGES ON)

第三方库的查找

这里需要用到 CMAKE_FIND_ROOT_PATH 以及 CMAKE_PREFIX_PATH,因为 CMake 回去系统默认的地方查找对应的库,如果你需要用到放在其他地方的库,可以在这个变量中添加。

另外,对于单个库,也可以使用这两个变量:

  • <PackageName>_ROOT:用来指定头文件以及库、可执行文件的路径;
  • <PackageName>_DIR:用来指定库的 CMake 文件路径;

假如在系统中存在多种编译器或者版本,可以通过设置以下两个变量来设置 C 以及 C++ 的编译器:

1
2
CMAKE_C_COMPILER=/path/to/gcc
CMAKE_CXX_COMPILER=/path/to/g++

FLAGS

如果需要自定义编译配置,还可以设置以下的变量,大部分情况下,你都不需要配置,CMake 会根据环境以及其它变量自动配置:

1
2
CMAKE_C_FALGS=
CMAKE_CXX_FALGS=-fopenmp

如果你说需要上面的 FALGS 来配置 -std=c++17,那也不需要,你可以设置其他的变量来达到这个目的,比如全局的:

1
2
3
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS ON)

以及更被建议的局部做法:

1
2
3
4
5
6
add_library(myTarget lib.cpp)
set_target_properties(myTarget PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED YES
CXX_EXTENSIONS NO
)

另外,如果想要 -fPIC,也有专门的变量:CMAKE_POSITION_INDEPENDENT_CODE,当然,这个也建议在局部做:

1
set_target_properties(myTarget PROPERTIES POSITION_INDEPENDENT_CODE ON)

预处理定义

1
2
add_compile_definitions(-DTEST) # 全局
target_compile_definitions(-DTEST) # 局部

编译类别 CMAKE_BUILD_TYPE 我们常用的也就 ReleaseDebug,由于编译环境的不同,也会对这个值进行限制,具体需要参考 CMAKE_CONFIGURATION_TYPES,比如 还可以有 RelWithDebInfo 以及 MinSizeRel

这个变量,会决定编译是否优化以及带上调试信息,千万不要给你们公司的私有程序以 Debug 模型发布出去了,原因?一个是代码没优化,性能会比较差,另外就是会泄露源码。

动态库与静态库

需要用到 BUILD_SHARED_LIBS 这个变量,常常被用到 option 里面提供给用户进行配置,这个变量控制的是 add_libary(myLib ...) 最后生成的类别。

或许你会奇怪为什么没有 BUILD_STATIC_LIBS,其实默认就是 static,也就是相当于 BUILD_SHARED_LIBS=OFF

另外,还有个小技巧,如果你需要同时编译动态库与静态库,可以用类似以下的方式来做到:

1
2
3
4
add_libary(myLib STATIC lib.cpp)

add_libary(mySharedLib SHARED lib.cpp)
set_target_properties(mySharedLib PROPERTIES OUTPUT_NAME myLib)

几个有用的模块

ExternalProject 就不用多说了,前面在 【CMake 系列】(三)ExternalProject 实践 专门介绍过。

注意:这几个模块需要通过 include 来引入后才能使用。

CMakePrintHelpers

非常适合用来调试,cmake_print_variables 帮助你打印出变量的值以及 cmake_print_properties 可以打印出 target 中的一些属性。

下面就是一个打印出 include 路径的例子:

1
2
cmake_print_properties(TARGETS foo bar PROPERTIES
LOCATION INTERFACE_INCLUDE_DIRECTORIES)

WriteCompilerDetectionHeader

有些时候,为了写跨平台的代码,我们需要判别编译器是否支持一些特性,CMake 就提供了这个模块,它可以帮助你生成一个预定义头文件,帮你把一些编译器支持的特性全部罗列出来:

1
2
3
4
5
write_compiler_detection_header(
FILE "${PROJECT_BINARY_DIR}/include/foo_compiler_detection.h"
PREFIX MY_PREFIX
COMPILERS GNU Clang AppleClang MSVC
FEATURES cxx_constexpr)

这里的编译特性还可以有:

  • cxx_constexpr
  • cxx_deleted_functions
  • cxx_extern_templates
  • cxx_variadic_templates
  • cxx_noexcept
  • cxx_final
  • cxx_override

FeatureSummary

这个模块适合在项目初始化完成的最后,打印出一些总结性信息:

1
feature_summary(WHAT ALL)

然后,你还可以给这个总结添加更多说明:

1
2
3
4
5
6
set_package_properties(LibXml2 PROPERTIES
TYPE RECOMMENDED
PURPOSE "Enables HTML-import in MyWordProcessor")

option(WITH_FOO "Help for foo" ON)
add_feature_info(Foo WITH_FOO "The Foo feature provides very cool stuff.")

这样,你就可以看到更多的总结信息了。

这个就太简单了,但是又非常常见,怕初学者不清楚,这里就提示下:

直接设置 CMAKE_INSTALL_PREFIX 即可,最后执行安装命令的时候,会将对应的文件安装到制定的目录。

上面简单罗列了我们团队项目中常用的,也是经过我挑选之后的,毕竟那么多的特性,不可能在这一篇文章中全部列出,详细的还是需要看 CMake 官方文档。另外,文中大部分的例子也是来自于 CMake 官方文档。


首发于 Github issues: https://github.com/xizhibei/blog/issues/140 ,欢迎 Star 以及 Watch

本文采用 署名-非商业性使用-相同方式共享(BY-NC-SA)进行许可
作者:习之北 (@xizhibei)
原链接:https://blog.xizhibei.me/2020/06/02/cmake-7-common-var-func-and-modules/


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK