Alex Blog

CMake 学习笔记

 

一: CMakeLists.txt 的基本结构

cmake_minimum_required(VERSION 3.10)

# 设置项目名称和版本
project(MyProject VERSION 1.0)

# 指定 C++ 标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# 包含头文件所在的目录
include_directories(${PROJECT_SOURCE_DIR}/include)

# 添加库目录(全局)
link_directories(${Boost_LIBRARY_DIRS})

# 添加一个可执行文件
add_executable(MyExecutable main.cpp)

# 添加一个库
add_library(MyLibrary SHARED mylibrary.cpp)

# 将库链接到可执行文件
target_link_libraries(MyExecutable PRIVATE MyLibrary)

二: 示例项目

这是一个简单项目的更全面示例,包含一个库和一个可执行文件:

目录结构:
MyProject/
├── CMakeLists.txt
├── src/
│   ├── CMakeLists.txt
│   ├── main.cpp
├── include/
│   └── myheader.h
├── tests/
│   ├── CMakeLists.txt
│   ├── test_main.cpp

三: 其他常用命令

find_package

find_package 是 CMake 中用于查找外部依赖项(例如库、框架、工具等)的命令。它能够自动检测系统上是否安装了所需的依赖项,并设置相应的变量以便在构建过程中使用。

find_package( [version] [REQUIRED] [components...])
:要查找的包的名称。
[version]:可选参数,指定所需包的最低版本。
[REQUIRED]:可选参数,如果设置,则在包未找到时将导致配置错误。
[components...]:可选参数,指定需要的包组件(如果有)。

# 设置查找路径(可选)
set(CMAKE_PREFIX_PATH "/path/to/custom/package")

# 查找 OpenCV 库
find_package(OpenCV REQUIRED)
if (OpenCV_FOUND)
    include_directories(${OpenCV_INCLUDE_DIRS})
endif()
if (OpenCV_FOUND)
    target_link_libraries(my_program ${OpenCV_LIBS})
endif()

target_compile_options

target_compile_options() 是 CMake 中用于为目标添加编译器选项的命令。它允许你为指定的目标添加编译选项,这些选项将传递给编译器。

target_compile_options( <INTERFACE|PUBLIC|PRIVATE> [options...])
: 目标(例如,可执行文件或库)的名称。
<INTERFACE|PUBLIC|PRIVATE>: 选项的可见性:
    INTERFACE: 只有使用目标的依赖方可见。
    PUBLIC: 目标及其依赖方都可见。
    PRIVATE: 仅对目标本身可见。
[options...]: 要传递给编译器的选项。

例如:
target_compile_options(MyExecutable PRIVATE -Wall -Werror -O3)

另外一个编译器选项命令:set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ...")
set(CMAKE_CXX_FLAGS …) 是全局设置,会影响到项目中所有使用 C++ 编译器的目标(包括库和可执行文件)。这种方式修改了全局变量 CMAKE_CXX_FLAGS,添加了一些编译选项。

settarget_compile_options 的主要区别:
作用范围:

– set(CMAKE_CXX_FLAGS …) 影响全局范围内的所有目标。

– target_compile_options() 仅影响指定的目标。

灵活性:

– set(CMAKE_CXX_FLAGS …) 对于所有目标都是一致的,不灵活。

– target_compile_options() 允许你为不同的目标设置不同的编译选项,更加灵活。

可维护性:

– set(CMAKE_CXX_FLAGS …) 设置全局编译选项,可能导致后续维护困难,尤其是在大项目中。

– target_compile_options() 更适合模块化和可维护性强的项目设置,可以为不同的模块或目标单独设置编译选项。

targecompile_definitions

target_compile_definitions() 是 CMake 中用于定义预处理宏的命令,这些宏将在编译目标时使用。它允许你为指定的目标添加编译定义,这些定义可以在源代码中使用 #ifdef#if defined() 等预处理指令进行条件编译。


target_compile_definitions( <INTERFACE|PUBLIC|PRIVATE> [items...])
: 目标(例如,可执行文件或库)的名称。
<INTERFACE|PUBLIC|PRIVATE>: 定义的可见性:
    INTERFACE: 只有使用目标的依赖方可见。
    PUBLIC: 目标及其依赖方都可见。
    PRIVATE: 仅对目标本身可见。
[items...]: 要定义的宏。

target_compile_definitions(MyExecutable PRIVATE MY_MACRO)
或者
target_compile_definitions(MyExecutable PRIVATE MY_MACRO=1)

在代码中使用:
#ifdef MY_MACRO
    std::cout << "MY_MACRO is defined" << std::endl;
#elif MY_MACRO == 1 
    std::cout << "MY_MACRO is defined and equals 1" << std::endl;
#else
    std::cout << "MY_MACRO is not defined or does not equal 1" << std::endl;
#endif

option 和 set

option() 用于定义一个布尔类型的选项,这个选项可以在配置项目时由用户进行设置。通常用于启用或禁用项目的某些特性或功能。

option( "help string" [initial_value])
: 选项变量名称。
"help string": 帮助字符串,描述选项的用途。
[initial_value]: 初始值(可选,默认为 OFF)。

set() 用于设置变量的值,可以是任何类型(如字符串、路径、布尔值等)。如果与 CACHE 关键字一起使用,变量的值会被存储在 CMake 的缓存中,允许用户在配置项目时进行修改。

set(  [CACHE   [FORCE]])
: 变量名称。
: 变量值。
CACHE: 指定将变量存储在缓存中。
: 变量类型,如 BOOL, PATH, STRING。
: 帮助字符串,描述变量的用途。
FORCE: 强制覆盖已有缓存变量的值(可选)。
# 定义一个布尔选项来启用或禁用测试构建
option(BUILD_TESTS "Build the test suite" ON)

# 定义一个路径变量用于 HailoRT 的包含目录
set(HAILORT_INCLUDE "/usr/include/hailo" CACHE PATH "Path to HailoRT include directory")

if (BUILD_TESTS)
    enable_testing()
    add_subdirectory(tests)
endif()

include_directories(${HAILORT_INCLUDE})

# 在命令行修改这些选项和变量
cmake -DBUILD_TESTS=OFF -DHAILORT_INCLUDE=/custom/path/to/hailo ..

配置文件和生成文件

configure_file() 用于配置文件,将变量值替换到文件中。

configure_file(config.h.in config.h)

file() 用于文件操作,如创建目录、复制文件等。

file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/output)

依赖管理

add_subdirectory() 添加子目录,构建子目录中的 CMakeLists.txt。

add_subdirectory(src)
add_subdirectory(tests)

include() 包含其他 CMake 脚本文件。

include(cmake/MyMacros.cmake)

 


已发布

分类

,

来自

标签:

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注