《Modern CMake》读书笔记

简介: 《Modern CMake》读书笔记



1. Running cmake


1.1. cmake选项



--build  指定输出目录


-j 指定并行度


--target 指定编译目标



1.2. 选择编译器


EXPORT CC=clang CXX=clang++ cmake ..


1.3. 选择生成器


默认为make  通过cmake -G Ninja指定ninja



1.4. 指定编译选项


cmake -DXXX=YYY

cmake会将各种编译选项缓存到一个文件中,即CMakeCache.txt



1.5. 调试


调试makefile: VERBOSE=1 make

调试cmake:


  • cmake --trace,  打印出cmake运行的每一行脚本


  • cmake --trace-source=打印出中运行的每一行脚本




1.6. 指定编译类型


-DCMAKE_BUILD_TYPE:Debug或Release或RelWithDebInfo

-DCMAKE_INSTALL_PREFIX: 指定安装路径,默认为/usr/local

-DBUILD_SHARED_LIBS: 是否编译共享库,ON or OFF

-DBUILD_TESTING:  是否编译tests



2. Do's and Don'ts


2.1. 不要做


  • 不要使用全局函数:  link_directories, include_libraries等


  • 非必要不使用PULIBC限制


  • 不要用glob匹配文件:当新增文件时,除非重新跑一遍cmake, make或其他编译工具将不会感知到新文件


  • lib不要直接link到最终的target


  • link lib时不要忽略PUBLIC/PRIVATE关键字



2.2. 要做


  • 把cmake当做正经代码维护


  • 站在target的角度思考


  • 善用alias


  • 将通用功能抽象成函数或宏


  • 函数名统一小写



  • 善用cmake_policy


2.3. 选择cmake版本


2.3.1. os支持


  • 3.4: The bare minimum. Never set less.


  • 3.7: Debian old-stable.


  • 3.10: Ubuntu 18.04.


  • 3.11: CentOS 8 (use EPEL or AppSteams, though)


  • 3.13: Debian stable.


  • 3.16: Ubuntu 20.04.


  • 3.19: First to support Apple Silicon.


  • latest: pip/conda-forge/homebew/chocolaty, ect.


笔者目前用的是3.16




2.3.2. 特性

  • 3.8: C++ meta features, CUDA, lots more


  • 3.11: IMPORTED INTERFACE setting, faster, FetchContent, COMPILE_LANGUAGE in IDEs


  • 3.12: C++20, cmake --build build -j N, SHELL:, FindPython


  • 3.14/3.15: CLI, FindPython updates


  • 3.16: Unity builds / precompiled headers, CUDA meta features


  • 3.17/3.18: Lots more CUDA, metaprogramming



3. What's new in in CMake


  • cmake 3.0: interface libraries, 允许将一组头文件抽象成一个lib


  • cmake 3.1: 支持c++11和compile features


  • cmake 3.2: 支持UTF-8


  • cmake 3.4:  支持swift语言,支持ccache


  • cmake 3.5: 支持ARM平台


  • cmake 3.6: 支持clang-tidy


  • 其他:略


4. 基础知识


指定最小版本


cmake_minimum_required(VERSION 3.1)


创建工程

project(MyProject VERSION 1.0
                  DESCRIPTION "Very nice project"
                  LANGUAGES CXX)


新增executable

add_executable(one two.cpp three.h)



新增library

add_library(one STATIC two.cpp three.h)



用户可指定STATIC、SHARED、MODULE 。缺省使用BUILD_SHARED_LIBS选项。

INTERFAC用于创建头文件库

ALIAS用于指定库的别名.


绑定头文件路径


target_include_directories(one PUBLIC include)


PUBLIC表示所有依赖lib的target都自动绑定了该头文件路径


PRIVATE表示该头文件路径仅对本target有效


INTERFACE表示该头文件路径仅对依赖该lib的target生效


PUBLIC = PRIVATE + INTERFACE




5. 变量和cache


定义变量

set(MY_VARIABLE "value")



访问变量时使用${MY_VARIABLE}

变量仅在当前作用域内有效。



定义变量(多个值)

set(MY_LIST "one" "two")



等效于

set(MY_LIST "one;two")



属性

set_property(TARGET TargetName
             PROPERTY CXX_STANDARD 11)
set_target_properties(TargetName PROPERTIES
                      CXX_STANDARD 11)
get_property(ResultVariable TARGET TargetName PROPERTY CXX_STANDARD)




6. cmake编程


6.1. 控制流

if(variable)
    # If variable is `ON`, `YES`, `TRUE`, `Y`, or non zero number
else()
    # If variable is `0`, `OFF`, `NO`, `FALSE`, `N`, `IGNORE`, `NOTFOUND`, `""`, or ends in `-NOTFOUND`
endif()
# If variable does not expand to one of the above, CMake will expand it then try again



There are a variety of keywords as well, such as:

  • Unary: NOT, TARGET, EXISTS (file), DEFINED, etc.
  • Binary: STREQUAL, AND, OR, MATCHES (regular expression), VERSION_LESS, VERSION_LESS_EQUAL (CMake 3.7+), etc.
  • Parentheses can be used to group



generator-expressions


target_compile_options(MyTarget PRIVATE "$<$<CONFIG:Debug>:--my-flag>")


当使用debug编译时,加上--my-flag编译选项

That last one is very common. You'll see something like this in almost every package that supports installing:

target_include_directories(
    MyTarget
  PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    $<INSTALL_INTERFACE:include>
)



相关文章
|
存储 缓存 安全
《optimizing software in c++》读书笔记(二)
《optimizing software in c++》读书笔记(二)
203 0
|
Unix C++ 开发者
CMake 入门教程
CMake 入门教程
497 0
CMake 入门教程
《Modern CMake》读书笔记2
《Modern CMake》读书笔记2
230 0