随机
Enter 搜索 ↑↓ 切换 Esc 清空

cmake

命令

跨平台构建系统生成器

cmake

跨平台构建系统生成器

补充说明

cmake 是开源的跨平台构建系统生成器,通过 CMakeLists.txt 配置文件生成特定平台的构建文件(如 Makefile、Visual Studio 项目)。是现代 C/C++ 项目的主流构建工具。

语法

cmake [OPTIONS] <source_dir>
cmake [OPTIONS] -B <build_dir> -S <source_dir>
cmake --build <build_dir> [OPTIONS]

基本项目结构

project/
├── CMakeLists.txt
├── src/
│   ├── main.cpp
│   └── utils.cpp
├── include/
│   ├── main.h
│   └── utils.h
└── build/          # 构建目录

最小 CMakeLists.txt

cmake_minimum_required(VERSION 3.16)

# 项目名称和版本
project(MyProject VERSION 1.0.0 LANGUAGES CXX)

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

# 添加可执行文件
add_executable(myapp src/main.cpp)

# 包含目录
target_include_directories(myapp PRIVATE ${CMAKE_SOURCE_DIR}/include)

# 链接库
target_link_libraries(myapp PRIVATE pthread)

常用命令

# 项目信息
cmake_minimum_required(VERSION 3.16)
project(ProjectName VERSION 1.0.0 LANGUAGES C CXX)

# 设置变量
set(VAR_NAME value)
set(VAR_NAME value1 value2 value3)

# 条件设置
option(BUILD_TESTS "Enable tests" ON)
set(ENABLE_FEATURE OFF CACHE BOOL "Enable feature")

# 列表操作
list(APPEND MY_LIST "item1" "item2")
list(GET MY_LIST 0 1 VAR1 VAR2)
list(LENGTH MY_LIST LEN)
list(REMOVE_ITEM MY_LIST "item1")

# 添加子目录
add_subdirectory(src)
add_subdirectory(tests)

# 包含文件
include(CMakeLists.txt.in)
include_directories(path)              # 全局包含目录
target_include_directories(target PRIVATE path)  # 目标特定

添加源文件

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

# 添加静态库
add_library(static_lib STATIC utils.cpp)

# 添加共享库
add_library(shared_lib SHARED utils.cpp)

# 添加头文件库(仅头文件)
add_library(header_lib INTERFACE)
target_include_directories(header_lib INTERFACE include/)

# 从模式添加文件
file(GLOB SOURCES "src/*.cpp")
add_executable(app ${SOURCES})

# 递归添加
file(GLOB_RECURSE SOURCES "src/*.cpp" "src/*.c")

# 排除文件
file(GLOB SOURCES "src/*.cpp")
list(FILTER SOURCES EXCLUDE REGEX "test_.*")

包含目录和链接库

# 包含目录
include_directories(${CMAKE_SOURCE_DIR}/include)
include_directories(BEFORE ${CMAKE_SOURCE_DIR}/src)

# 目标包含目录
target_include_directories(myapp
    PUBLIC
        ${CMAKE_SOURCE_DIR}/include
    PRIVATE
        ${CMAKE_SOURCE_DIR}/src
)

# 链接库
target_link_libraries(myapp
    PUBLIC
        ${CMAKE_SOURCE_DIR}/lib/libfoo.a
    PRIVATE
        pthread
)

# 链接多个库
target_link_libraries(myapp
    lib1
    lib2
    ${CMAKE_DL_LIBS}    # dlopen
)

# 查找库
find_library(LIB_NAME NAMES foo PATHS /usr/lib)
target_link_libraries(myapp ${LIB_NAME})

# 查找包(使用 pkg-config)
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
target_include_directories(myapp PRIVATE ${GTK3_INCLUDE_DIRS})
target_link_libraries(myapp PRIVATE ${GTK3_LIBRARIES})

条件编译

# 简单条件
if(WIN32)
    # Windows 特定
elseif(UNIX)
    # Unix 特定
endif()

# 变量判断
if(VAR)
    # VAR 非空或 ON/YES/TRUE
endif()

# 变量比较
if(VAR1 STREQUAL VAR2)
if(VAR1 EQUAL VAR2)        # 数值比较
if(VAR1 LESS VAR2)          # 数值小于
if(VAR1 GREATER VAR2)       # 数值大于
if(VAR1 MATCHES REGEX)      # 正则匹配

# 选项
option(ENABLE_TESTS "Build tests" ON)
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)

# 平台检测
if(WIN32)
    set(PLATFORM_LIBS advapi32)
elseif(APPLE)
    set(PLATFORM_LIBS "-framework Cocoa")
elseif(UNIX)
    set(PLATFORM_LIBS pthread)
endif()

生成器表达式

# 条件包含目录
target_include_directories(myapp
    PRIVATE
        $<$<CONFIG:Debug>:${DEBUG_INCLUDES}>
        $<$<CONFIG:Release>:${RELEASE_INCLUDES}>
)

# 条件定义
target_compile_definitions(myapp
    PRIVATE
        $<$<CONFIG:Debug>:DEBUG_MODE=1>
        $<$<CONFIG:Release>:NDEBUG>
)

# 条件链接
target_link_libraries(myapp
    PRIVATE
        $<$<BOOL:${ENABLE_TLS}>:OpenSSL::SSL>
)

测试

# 启用测试
enable_testing()

# 添加测试
add_executable(test_app tests/test.cpp)
target_link_libraries(test_app PRIVATE doctest)  # 或 catch2, gtest

add_test(NAME MyTest COMMAND test_app)

# 测试命令
add_test(NAME mytest COMMAND python ${CMAKE_SOURCE_DIR}/test.py)

# 自定义测试命令
add_test(NAME coverage COMMAND python coverage.py)
set_tests_properties(coverage PROPERTIES TIMEOUT 300)

安装

# 安装目标
install(TARGETS myapp mylib
    RUNTIME DESTINATION bin
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib
    PUBLIC_HEADER DESTINATION include/myproject
)

# 安装文件
install(FILES header.h DESTINATION include)
install(FILES config.conf DESTINATION etc)

# 安装目录
install(DIRECTORY data/ DESTINATION share/myproject/data)
install(DIRECTORY icons/ DESTINATION share/icons FILES_MATCHING PATTERN "*.png")

# 安装 CMake 配置
include(GNUInstallDirs)
install(EXPORT MyTargets FILE MyTargets.cmake DESTINATION cmake)
export(TARGETS mylib FILE MyTargets.cmake)

交叉编译

# 工具链文件 toolchain.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_C_COMPILER arm-linux-gnueabi-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabi-g++)
set(CMAKE_FIND_ROOT_PATH /path/to/sysroot)

# 使用工具链
cmake -B build -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake

# 目标系统处理器
set(CMAKE_SYSTEM_PROCESSOR arm)

# 查找程序(禁用系统路径)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

常用选项

# 首次配置
cmake -S . -B build
cmake -B build -DCMAKE_BUILD_TYPE=Release

# 构建
cmake --build build
cmake --build build --target myapp
cmake --build build -- -j4                    # 并行构建

# 清理构建
rm -rf build
cmake --build build -- clean

# 重新配置
cmake -B build

# 显示所有变量
cmake -LA . | grep VAR

# 设置变量
cmake -B build -DVAR=value

# 安装
cmake --install build
cmake --install build --prefix /usr/local

# 预设
cmake --preset list
cmake --preset default
cmake --build --preset default

presets

// CMakePresets.json
{
    "version": 4,
    "configurePresets": [
        {
            "name": "default",
            "binaryDir": "${sourceDir}/build",
            "cacheVariables": {
                "CMAKE_BUILD_TYPE": "Release",
                "ENABLE_TESTS": "ON"
            }
        },
        {
            "name": "debug",
            "inherits": "default",
            "cacheVariables": {
                "CMAKE_BUILD_TYPE": "Debug"
            }
        }
    ]
}

FetchContent(依赖)

include(FetchContent)

FetchContent_Declare(
    googletest
    GIT_REPOSITORY https://github.com/google/googletest.git
    GIT_TAG v1.12.1
)

FetchContent_MakeAvailable(googletest)