Cmake

Cmake

子文档:Gtest

B站​[1]

CMakeLists 语法

1
2
cmake_minimum_required(VERSION <version>) # 指定 CMake 的最低版本要求
project(MyProject CXX) # 定义项目的名称和使用的编程语言

set

1
2
3
# 设置 C++ 标准,设置某个参数的值
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

缓存变量

1
set(MY_CACHE_VAR "DefaultValue" CACHE STRING "A cache variable")

set_target_properties

1
set_target_properties(MyExecutable2 PROPERTIES COMPILE_DEFINITIONS "RELEASE")

message

1
2
message("Debug build")
message(STATUS "Variable MY_VAR is ${MY_VAR}")#

find_package

1
2
3
find_package(GTest REQUIRED)
find_package(Boost 1.70 REQUIRED) # 可以指定版本
find_package(OpenCV REQUIRED PATHS /path/to/opencv) # 可以指定路径

add

add_executable

1
add_executable(<target> <source_files>...) # 指定要生成的可执行文件和其源文件

add_subdirectory添加子模块

1
add_subdirectory(PATH)

添加路径以后就会扫描PATH存在CMakeLists.txt文件,构建子模块。

add_library

1
2
add_library(hellolib SHARED ${HELLOSRC}) # 创建一个库(静态库或动态库)及其源文件
add_library(MyLibrary STATIC library.cpp)

include

include_directories

1
include_directories(${PROJECT_SOURCE_DIR}/include) # 添加头文件搜索路径

target

target_include_directories

1
2
3
4
target_include_directories(TARGET target_name
[BEFORE | AFTER]
[SYSTEM] [PUBLIC | PRIVATE | INTERFACE]
[items1...])
1
2
3
target_link_libraries(run_tests gtest gtest_main)# 链接目标文件与其他库
target_link_libraries(run_tests GTest::GTest GTest::Main)
target_link_libraries(run_tests gtest gtest_main Threads::Threads)
特性 GTest::GTest​ 和 GTest::Main gtest​ 和 gtest_main
命名空间 使用命名空间(GTest::​),更规范 直接使用库名称,无命名空间
依赖管理 自动处理依赖(如 pthread​) 需要手动处理依赖(如 pthread​)
现代 CMake 支持 符合现代 CMake 最佳实践 不符合现代 CMake 最佳实践
可移植性 更好,适用于不同平台和构建系统 较差,可能在某些平台上无法正常工作
代码简洁性 更简洁,无需手动处理依赖 需要手动处理依赖,代码稍显冗长

install

include_directories() 和 target_include_directories()区别

在 CMake 中,include_directories() 和 target_include_directories() 都用于指定头文件的搜索路径,但它们的作用范围和使用方式有显著区别。

相同点:

两者都用于添加头文件的搜索路径,编译器会在这些路径中查找 #include 指令中指定的头文件。

两者都支持绝对路径和相对路径,相对路径是相对于当前 CMakeLists.txt 文件所在的目录。

两者都可以用于指定公共头文件路径(PUBLIC)、私有头文件路径(PRIVATE)或接口头文件路径(INTERFACE)。

区别:

特性 include_directories() target_include_directories()
作用范围 全局作用域,影响所有目标(target)。 仅作用于指定的目标(target)。
推荐使用场景 适用于简单的项目或旧版 CMake 项目。 适用于现代 CMake 项目,推荐优先使用。
目标关联性 不直接关联到特定目标,可能影响所有目标。 显式关联到特定目标,避免污染其他目标。
可维护性 较差,容易导致全局路径污染。 较好,路径与目标绑定,逻辑清晰。
作用域控制 无法精确控制路径的作用范围。 可以通过 PUBLIC​、PRIVATE​、INTERFACE​ 精确控制路径的作用范围。
现代 CMake 推荐 不推荐使用,除非有特殊需求。 推荐使用,符合现代 CMake 的最佳实践。

CMake 构建流程​[2]

1
2
3
cmake .. -L # 可以查看编译选项
-H # 查看编译选项解释
cmake --help # 可以查看文档

mkdir build && cd build && cmake .. && make -j4

make clean

CMakeLists 高级特性

自定义脚本

  1. 在项目目录下创建一个 cmake/ 目录,用于存放自定义 CMake 模块

  2. 在 cmake/ 目录下创建一个 MyModule.cmake 文件

  3. 在 CMakeLists.txt 文件中包含自定义模块:

    1
    2
    list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")# 扩展CMake模块搜索路径
    include(MyModule) # 加载并执行指定的 CMake 模块文件(文件名称为MyModule)
1
2
3
4
5
6
# MyModule.cmake 定义函数
function(my_custom_function)
message(STATUS "This is a custom function!")
endfunction()
# CMakeLists.txt 调用函数
my_custom_function()

CMake 跨平台特性 | 交叉编译

以当前系统为x86_64ubuntu为目标系统为aarch64(jetson)编译pcl库为例,失败,认为交叉编译就是xxx,建议使用docker搭建环境,下面给出一个较为详细的

知乎​[3]

选择性编译

1
2
3
4
option(PAEAM_NAME "注释" OFF)# 默认值
if(PAEAM_NAME)
...
endif()

自定义命令 (add_custom_command 命令)

1
2
3
4
5
6
7
8
9
10
11
12
13
add_custom_command(
TARGET target
PRE_BUILD | PRE_LINK | POST_BUILD
COMMAND command1 [ARGS] [WORKING_DIRECTORY dir]
[COMMAND command2 [ARGS]]
[DEPENDS [depend1 [depend2 ...]]]
[COMMENT comment]
[VERBATIM]
)
add_custom_command(
TARGET MyExecutable POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "Build completed."
)

资源链接-CMake

[1] 【从零搭建一个c/c++工程–use_cmake】

[2] CMake 构建流程 | 菜鸟教程

[3] 手把手PCL交叉编译到arm,亲自实践总结 - 知乎


Cmake
http://example.com/post/cmake-zsai8o.html
作者
lovedreamms
发布于
2025年1月23日
许可协议