#CMake 语法详解

CMake 语法详解

1. 基础语法结构

基本命令格式

command_name(argument1 argument2 ...)

注释

# 这是单行注释

#[[
这是多行注释
可以跨越多行
]]

2. 变量和字符串

变量定义和使用

# 设置变量
set(MY_VARIABLE "Hello World")
set(NUMBER_VARIABLE 42)
set(LIST_VARIABLE item1 item2 item3)

# 使用变量
message("Variable: ${MY_VARIABLE}")

# 环境变量
set(ENV{PATH} "$ENV{PATH}:${CMAKE_CURRENT_SOURCE_DIR}")

# 缓存变量(用户可配置)
set(MY_OPTION "ON" CACHE BOOL "Description")

字符串操作

# 字符串连接
set(STR1 "Hello")
set(STR2 "World")
set(RESULT "${STR1} ${STR2}")  # "Hello World"

# 字符串长度
string(LENGTH "${MY_VARIABLE}" STR_LENGTH)

# 子字符串
string(SUBSTRING "${MY_VARIABLE}" 0 5 SUB_STR)

# 查找和替换
string(FIND "${MY_VARIABLE}" "World" POSITION)
string(REPLACE "Hello" "Hi" NEW_STR "${MY_VARIABLE}")

3. 流程控制

条件语句

if(condition)
    # 代码块
elseif(another_condition)
    # 代码块
else()
    # 代码块
endif()

条件表达式

# 布尔运算
if(VARIABLE)                    # 如果变量已定义且不为 false
if(NOT VARIABLE)               # 取反
if(VARIABLE1 AND VARIABLE2)    # 与
if(VARIABLE1 OR VARIABLE2)     # 或

# 比较运算
if("${VAR}" STREQUAL "value")  # 字符串相等
if(NUMBER_VAR EQUAL 42)        # 数字相等
if(NUMBER_VAR GREATER 10)      # 大于
if(NUMBER_VAR LESS 100)        # 小于

# 文件操作
if(EXISTS "file.txt")          # 文件存在
if(IS_DIRECTORY "dir")         # 是目录

# 类型检查
if(DEFINED VARIABLE)           # 变量已定义
if(COMMAND command_name)       # 命令存在

循环语句

# foreach 循环
foreach(item IN ITEMS apple banana cherry)
    message("Fruit: ${item}")
endforeach()

foreach(i RANGE 1 10 2)  # 从1到10,步长为2
    message("Number: ${i}")
endforeach()

# while 循环
set(counter 0)
while(counter LESS 5)
    message("Counter: ${counter}")
    math(EXPR counter "${counter} + 1")
endwhile()

4. 函数和宏

函数定义

function(my_function arg1 arg2)
    message("Arguments: ${arg1} ${arg2}")
    set(${arg1}_RESULT "processed" PARENT_SCOPE)  # 返回给父作用域
endfunction()

# 调用函数
my_function("hello" "world")

宏定义

macro(my_macro arg1 arg2)
    message("Arguments: ${arg1} ${arg2}")
    set(${arg1}_RESULT "processed")  # 会影响调用者的作用域
endmacro()

# 调用宏
my_macro("hello" "world")

函数 vs 宏

  • 函数: 有自己的作用域,不会影响调用者变量
  • : 没有独立作用域,会影响调用者变量

5. 项目配置

基本项目设置

cmake_minimum_required(VERSION 3.16)  # 最低CMake版本
project(MyProject                      # 项目名
    VERSION 1.0.0                      # 版本号
    DESCRIPTION "My CMake Project"     # 描述
    LANGUAGES CXX C                    # 支持的语言
)

编译器选项

# C++ 标准设置
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# 编译选项
if(MSVC)
    target_compile_options(my_target PRIVATE /W4 /WX)
else()
    target_compile_options(my_target PRIVATE -Wall -Wextra -Werror)
endif()

# 预处理器定义
target_compile_definitions(my_target 
    PRIVATE 
        MY_DEFINITION=1
        "OTHER_DEFINITION=\"value\""
)

6. 目标管理

创建目标

# 可执行文件
add_executable(my_app 
    main.cpp 
    utils.cpp 
    headers.h
)

# 静态库
add_library(my_lib STATIC
    lib_source.cpp
    lib_header.h
)

# 动态库
add_library(my_shared_lib SHARED
    shared_source.cpp
)

目标属性设置

# 包含目录
target_include_directories(my_target
    PUBLIC 
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
        $<INSTALL_INTERFACE:include>
    PRIVATE
        ${CMAKE_CURRENT_SOURCE_DIR}/src
)

# 链接库
target_link_libraries(my_target
    PUBLIC
        Threads::Threads
        ${CMAKE_DL_LIBS}
    PRIVATE
        my_internal_lib
)

# 编译特性
target_compile_features(my_target 
    PRIVATE 
        cxx_std_17
        cxx_auto_type
)

7. 查找包和依赖

find_package 使用

# 查找系统包
find_package(OpenCV REQUIRED COMPONENTS core imgproc)

# 使用找到的包
if(OpenCV_FOUND)
    target_link_libraries(my_app ${OpenCV_LIBS})
    target_include_directories(my_app PRIVATE ${OpenCV_INCLUDE_DIRS})
endif()

pkg-config 集成

find_package(PkgConfig REQUIRED)
pkg_check_modules(FFMPEG REQUIRED IMPORTED_TARGET
    libavcodec
    libavformat
    libavutil
)

target_link_libraries(my_app PkgConfig::FFMPEG)

8. 目录和文件操作

文件操作

# 文件操作
file(READ "file.txt" CONTENT)
file(WRITE "output.txt" "Hello World")
file(APPEND "log.txt" "New entry\n")

# 文件查找
file(GLOB SOURCE_FILES "src/*.cpp")
file(GLOB_RECURSE HEADER_FILES "include/*.h")

# 目录操作
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/generated")

配置时文件生成

# 生成配置文件
configure_file(
    "config.h.in"
    "config.h"
    @ONLY
)

# 自定义命令
add_custom_command(
    OUTPUT "${CMAKE_BINARY_DIR}/generated.cpp"
    COMMAND ${PYTHON_EXECUTABLE} script.py
    DEPENDS script.py template.txt
    COMMENT "Generating source file"
)

9. 生成器表达式

条件表达式

# 根据配置设置不同选项
target_compile_definitions(my_target
    PRIVATE
        $<$<CONFIG:Debug>:DEBUG_MODE=1>
        $<$<CONFIG:Release>:OPTIMIZE=1>
)

# 根据编译器设置
target_compile_options(my_target
    PRIVATE
        $<$<CXX_COMPILER_ID:MSVC>:/MP>
        $<$<CXX_COMPILER_ID:GNU>:-fopenmp>
)

目标相关表达式

# 获取目标属性
$<TARGET_FILE:my_target>          # 目标文件路径
$<TARGET_LINKER_FILE:my_lib>      # 链接库文件
$<TARGET_PROPERTY:my_target,PROP> # 目标属性值

10. 安装和打包

安装规则

# 安装目标
install(TARGETS my_app my_lib
    RUNTIME DESTINATION bin
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib/static
)

# 安装文件
install(FILES header.h DESTINATION include)
install(DIRECTORY docs/ DESTINATION share/doc)

# 安装时脚本
install(SCRIPT custom_install.cmake)

打包

# CPack 配置
set(CPACK_PACKAGE_NAME "MyApplication")
set(CPACK_PACKAGE_VERSION "1.0.0")
set(CPACK_PACKAGE_VENDOR "My Company")

include(CPack)

11. 常用变量

CMake 内置变量

CMAKE_SOURCE_DIR          # 源码根目录
CMAKE_BINARY_DIR          # 构建根目录
CMAKE_CURRENT_SOURCE_DIR  # 当前处理的CMakeLists.txt所在目录
CMAKE_CURRENT_BINARY_DIR  # 当前目录对应的构建目录

CMAKE_CXX_COMPILER        # C++ 编译器
CMAKE_CXX_FLAGS           # C++ 编译标志

PROJECT_NAME              # 项目名
PROJECT_SOURCE_DIR        # 项目源码目录

CMAKE_INSTALL_PREFIX      # 安装前缀

平台相关变量

WIN32                     # Windows 平台
UNIX                      # Unix-like 平台
APPLE                     # Apple 平台
MSVC                      # MSVC 编译器
CMAKE_SYSTEM_NAME         # 系统名称

12. 完整示例

基础项目配置

cmake_minimum_required(VERSION 3.16)
project(MyApp
    VERSION 1.0.0
    LANGUAGES CXX
)

# 编译器设置
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 查找依赖
find_package(Threads REQUIRED)

# 添加可执行文件
add_executable(my_app main.cpp)

# 设置属性
target_compile_features(my_app PRIVATE cxx_std_17)
target_link_libraries(my_app PRIVATE Threads::Threads)

# 安装规则
install(TARGETS my_app DESTINATION bin)

包含子目录

# 主 CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(MyProject)

add_subdirectory(src)      # 包含源码目录
add_subdirectory(tests)    # 包含测试目录
add_subdirectory(docs)     # 包含文档目录
CMake 是一个跨平台的构建工具,能够用简单的语句来描述所有平台的安装编译过程,输出各种各样的 makefile 或者 project 文件,本身并不直接构建最终的软件,而是产生其他工具的脚本(如 makefile),再依据这些工具的构建方式使用[^2]。以下是 CMake 语法规则的详细介绍: ### CMake 基本语法 - **注释**:在 CMake 中,使用 `#` 来添加注释,注释内容会被忽略,例如 `# 这是一个注释`。 - **命令**:CMake 命令不区分大小写,但参数区分大小写。命令的调用格式为 `command(arg1 arg2 ...)`,例如 `message(STATUS "Hello, CMake!")`。 - **数据类型**:CMake 主要有字符串、列表和布尔值等数据类型。列表使用分号分隔元素,例如 `set(my_list "item1" "item2" "item3")`。 ### CMake 常用命令详解 - **list**:用于操作列表,如 `list(APPEND my_list "item4")` 可向列表 `my_list` 中添加元素。 - **include**:用于包含其他 CMake 文件,如 `include(OtherFile.cmake)`。 - **option**:用于定义开关选项,如 `option(ENABLE_FEATURE "Enable a certain feature" ON)`。 - **message**:用于输出信息,如 `message(STATUS "This is a status message")`。 - **file**:用于文件操作,如 `file(GLOB sources "src/*.cpp")` 可获取 `src` 目录下所有的 `.cpp` 文件。 - **execute_process**:用于执行外部进程,如 `execute_process(COMMAND ls -l)`。 ### CMake 中常用预定义变量 - **CMake 的预定义变量**:如 `CMAKE_SOURCE_DIR` 表示项目的源目录,`CMAKE_BINARY_DIR` 表示项目的构建目录。 - **系统信息预定义的变量**:如 `CMAKE_SYSTEM_NAME` 表示当前系统的名称。 - **开关选项变量**:如 `CMAKE_BUILD_TYPE` 用于指定构建类型(Debug、Release 等)。 ### CMake 常用语法 项目定义时,使用 `cmake_minimum_required` 指定最低 CMake 版本,`project` 定义项目名称、版本和使用的语言,示例如下: ```cmake cmake_minimum_required(VERSION 3.10) project(MyProject VERSION 1.0.0 LANGUAGES C CXX) ``` ### 常用函数 CMake 还提供了许多自定义函数的功能,可通过 `function` 关键字定义,示例如下: ```cmake function(my_function arg1 arg2) message(STATUS "Arguments: ${arg1}, ${arg2}") endfunction() my_function("value1" "value2") ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值