《Modern CMake》读书笔记2

简介: 《Modern CMake》读书笔记2



6.2. 宏和函数


function(SIMPLE REQUIRED_ARG)
    message(STATUS "Simple arguments: ${REQUIRED_ARG}, followed by ${ARGN}")
    set(${REQUIRED_ARG} "From SIMPLE" PARENT_SCOPE)
endfunction()
simple(This Foo Bar)
message("Output: ${This}")


The output would be:

-- Simple arguments: This, followed by Foo;Bar
Output: From SIMPLE



7. cmake交互


7.1. 配置文件



#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@"
configure_file (
    "${PROJECT_SOURCE_DIR}/include/My/Version.h.in"
    "${PROJECT_BINARY_DIR}/include/My/Version.h"
)



7.2. 读取文件


# Assuming the canonical version is listed in a single line
# This would be in several parts if picking up from MAJOR, MINOR, etc.
set(VERSION_REGEX "#define MY_VERSION[ \t]+\"(.+)\"")
# Read in the line containing the version
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/My/Version.hpp"
    VERSION_STRING REGEX ${VERSION_REGEX})
# Pick out just the version
string(REGEX REPLACE ${VERSION_REGEX} "\\1" VERSION_STRING "${VERSION_STRING}")
# Automatically getting PROJECT_VERSION_MAJOR, My_VERSION_MAJOR, etc.
project(My LANGUAGES CXX VERSION ${VERSION_STRING})




8. 如何组织工程


- project
  - .gitignore
  - README.md
  - LICENCE.md
  - CMakeLists.txt
  - cmake
    - FindSomeLib.cmake
    - something_else.cmake
  - include
    - project
      - lib.hpp
  - src
    - CMakeLists.txt
    - lib.cpp
  - apps
    - CMakeLists.txt
    - app.cpp
  - tests
    - CMakeLists.txt
    - testlib.cpp
  - docs
    - CMakeLists.txt
  - extern
    - googletest
  - scripts
    - helper.py


将cmake/目录加入到工程中.

set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})




9. 运行其他程序


9.1. 在配置时运行命令


find_package(Git QUIET)
if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
    execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive
                    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
                    RESULT_VARIABLE GIT_SUBMOD_RESULT)
    if(NOT GIT_SUBMOD_RESULT EQUAL "0")
        message(FATAL_ERROR "git submodule update --init --recursive failed with ${GIT_SUBMOD_RESULT}, please checkout submodules")
    endif()
endif()



9.2. 在编译时运行命令


find_package(PythonInterp REQUIRED)
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/include/Generated.hpp"
    COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/scripts/GenerateHeader.py" --argument
    DEPENDS some_target)
add_custom_target(generate_header ALL
    DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/include/Generated.hpp")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/Generated.hpp DESTINATION  include)



10. 一个简单示例


# Almost all CMake files should start with this
# You should always specify a range with the newest
# and oldest tested versions of CMake. This will ensure
# you pick up the best policies.
cmake_minimum_required(VERSION 3.1...3.22)
# This is your project statement. You should always list languages;
# Listing the version is nice here since it sets lots of useful variables
project(
  ModernCMakeExample
  VERSION 1.0
  LANGUAGES CXX)
# If you set any CMAKE_ variables, that can go here.
# (But usually don't do this, except maybe for C++ standard)
# Find packages go here.
# You should usually split this into folders, but this is a simple example
# This is a "default" library, and will match the *** variable setting.
# Other common choices are STATIC, SHARED, and MODULE
# Including header files here helps IDEs but is not required.
# Output libname matches target name, with the usual extensions on your system
add_library(MyLibExample simple_lib.cpp simple_lib.hpp)
# Link each target with other targets or add options, etc.
# Adding something we can run - Output name matches target name
add_executable(MyExample simple_example.cpp)
# Make sure you link your targets with this command. It can also link libraries and
# even flags, so linking a target that does not exist will not give a configure-time error.
target_link_libraries(MyExample PRIVATE MyLibExample)




11. 使用技巧


选择c++标准

set_target_properties(myTarget PROPERTIES
    CXX_STANDARD 11
    CXX_STANDARD_REQUIRED YES
    CXX_EXTENSIONS NO
)


启用pisition independent code

set(CMAKE_POSITION_INDEPENDENT_CODE ON)


集成ccache

find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM)
    set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
    set(CMAKE_CUDA_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") # CMake 3.9+
endif()



集成clang-tidy

~/package # cmake -S . -B build-tidy -DCMAKE_CXX_CLANG_TIDY="$(which clang-tidy);-fix"



打印变量

message(STATUS "MY_VARIABLE=${MY_VARIABLE}")
include(CMakePrintHelpers)
cmake_print_variables(MY_VARIABLE)
cmake_print_properties(
    TARGETS my_target
    PROPERTIES POSITION_INDEPENDENT_CODE
)




trace cmake

cmake -S . -B build --trace-source=CMakeLists.txt



debug编译

-DCMAKE_BUILD_TYPE=Debug




12. 测试


add_test(
  NAME
    ExampleCMakeBuild
  COMMAND
    "${CMAKE_CTEST_COMMAND}"
             --build-and-test "${My_SOURCE_DIR}/examples/simple"
                              "${CMAKE_CURRENT_BINARY_DIR}/simple"
             --build-generator "${CMAKE_GENERATOR}"
             --test-command "${CMAKE_CTEST_COMMAND}"
)
相关文章
|
算法 固态存储 关系型数据库
|
JavaScript 前端开发
vue封装点赞👍特效组件
如下图样式,主要是用css写出的动画,一个点击变量开关,控制样式变化。如果你也喜欢我的博客,记得点赞关注哦。我会持续更新,转发记得加上参考地址哦。
6324 0
vue封装点赞👍特效组件
|
Windows
解决.net framework 3.5 安装报错 0x800F0954问题
解决.net framework 3.5 安装报错 0x800F0954 方法步骤。
8844 1
|
Python
python股票量化交易(8)---K线图:锤头,射击之星,早晨之星
python股票量化交易(8)---K线图:锤头,射击之星,早晨之星
2142 0
python股票量化交易(8)---K线图:锤头,射击之星,早晨之星
|
算法
操作系统——经典进程同步问题
经典进程同步问题,消费者生产者问题、读写问题、哲学家进餐问题
687 0
操作系统——经典进程同步问题
|
NoSQL Shell Redis
Redis 中 scan 命令太坑了,千万别乱用!!
原本以为自己对redis命令还蛮熟悉的,各种数据模型各种基于redis的骚操作。但是最近在使用redis的scan的命令式却踩了一个坑,顿时发觉自己原来对redis的游标理解的很有限。所以记录下这个踩坑的过程,背景如下:
4248 1
Redis 中 scan 命令太坑了,千万别乱用!!
|
JavaScript 前端开发 测试技术
研发思维06----嵌入式智能硬件量产过程性设计(下)
研发思维06----嵌入式智能硬件量产过程性设计
1052 0
研发思维06----嵌入式智能硬件量产过程性设计(下)
|
存储 算法 C语言
数据结构与算法-实验2 树的二叉链表表示及其遍历
基本任务:用二叉链表存储结构表示下图所示二叉树, 并用递归方法输出三种遍历结果。 修改数节点值的数据类型及visit函数后,可以正常输出 进阶任务: 1,计算输出所建树的高度 2,用非递归算法实现中序遍历 3,实现层次遍历,提示见后面。 4,用顺序存储表示,并进行层次遍历、先序、中序和后续遍历 5,用非递归算法实现先序遍历、后续遍历
848 0
数据结构与算法-实验2 树的二叉链表表示及其遍历
|
消息中间件 SQL 机器学习/深度学习
校招答疑总结!准备实习、校招的学妹(弟)们,可不要努力错方向了!
大家好,我是路飞,校招答疑帖来啦! 正值秋招季,今天这篇文章来给大家分享一下关于在校生投递实习,应届生参加校招需要注意的一些问题。
校招答疑总结!准备实习、校招的学妹(弟)们,可不要努力错方向了!
|
机器学习/深度学习 人工智能 算法
High&NewTech:人工智能技术滥用之DeepNude技术(从下载致系统宕机→最后被禁用)而引发的AI道德底线的深度拷问—191017再次更新(一)
High&NewTech:人工智能技术滥用之DeepNude技术(从下载致系统宕机→最后被禁用)而引发的AI道德底线的深度拷问—191017再次更新
High&NewTech:人工智能技术滥用之DeepNude技术(从下载致系统宕机→最后被禁用)而引发的AI道德底线的深度拷问—191017再次更新(一)