【第六节】CMake小实战(新版)

目录

前言

一、项目结构与代码实现

1.1 项目结构

1.2 核心代码实现

二、现代 CMake 配置

2.1 根目录配置(CMakeLists.txt)

2.2 源码目录配置(src/CMakeLists.txt)

2.3 测试配置(tests/CMakeLists.txt)

三、构建与测试流程

3.1 标准构建流程

3.2 安装与打包

四、高级应用场景

4.1 交叉编译配置

4.2 静态分析集成

五、新旧实践对比

六、扩展建议

6.1 模块化开发

6.2 性能优化

6.3 文档生成


 

前言

        本文通过一个中等复杂度 C++ 项目案例,演示如何基于现代 CMake 最佳实践管理项目。涵盖构建、测试、安装、跨平台支持等全流程,提供可直接复用的工程模板。


一、项目结构与代码实现

1.1 项目结构

 MyProject/
├── CMakeLists.txt                # 根配置(V3.15+)
├── src/
│   ├── CMakeLists.txt            # 库与可执行文件
│   ├── main.cpp
│   ├── lib/
│   │   ├── module1.cpp
│   │   └── module2.cpp
│   └── include/
│       └── mylib.h
└── tests/
    ├── CMakeLists.txt            # 集成 CTest
    └── test_main.cpp

1.2 核心代码实现

src/main.cpp

#include <iostream>
#include "mylib.h"

int main() {
    std::cout << "Hello, Modern CMake!" << std::endl;
    print_module1_info();
    print_module2_info();
    return 0;
}

src/include/mylib.h

#ifndef MYLIB_H
#define MYLIB_H

void print_module1_info();
void print_module2_info();

#endif

src/lib/module1.cpp

#include "mylib.h"
#include <iostream>

void print_module1_info() {
    std::cout << "Module 1 v1.2.3" << std::endl;
}

src/lib/module2.cpp

#include "mylib.h"
#include <iostream>

void print_module2_info() {
    std::cout << "Module 2 v2.3.4" << std::endl;
}

二、现代 CMake 配置

2.1 根目录配置(CMakeLists.txt)

cmake_minimum_required(VERSION 3.15)
project(MyProject VERSION 1.0 LANGUAGES CXX)

# 设置默认构建类型
if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Build type" FORCE)
endif()
message(STATUS "Build configuration: ${CMAKE_BUILD_TYPE}")

# 添加子模块
add_subdirectory(src)
add_subdirectory(tests)

# 安装配置
include(GNUInstallDirs)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)

2.2 源码目录配置(src/CMakeLists.txt)

# 创建静态库
add_library(MyLib STATIC
    lib/module1.cpp
    lib/module2.cpp
)

# 头文件配置(支持安装)
target_include_directories(MyLib PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    $<INSTALL_INTERFACE:include>
)

# C++ 标准配置
target_compile_features(MyLib PUBLIC cxx_std_17)

# 可执行文件配置
add_executable(MyExecutable main.cpp)
target_link_libraries(MyExecutable PRIVATE MyLib)

# 安装规则
install(TARGETS MyLib
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

install(TARGETS MyExecutable
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

# 构建完成提示(跨平台)
add_custom_command(TARGET MyExecutable POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E echo
    "Build output: $<TARGET_FILE_DIR:MyExecutable>/$<TARGET_FILE_NAME:MyExecutable>"
)

# 一键运行目标
add_custom_target(run
    COMMAND $<TARGET_FILE:MyExecutable>
    DEPENDS MyExecutable
    COMMENT "Running main executable..."
)

2.3 测试配置(tests/CMakeLists.txt)

enable_testing()

# 现代 GTest 集成
find_package(GTest REQUIRED CONFIG)

add_executable(TestMyLib test_main.cpp)
target_link_libraries(TestMyLib
    PRIVATE
        MyLib
        GTest::GTest
        GTest::Main
)

# 注册测试用例
add_test(NAME MyLibTest COMMAND TestMyLib)
set_tests_properties(MyLibTest
    PROPERTIES
        TIMEOUT 30
        WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/bin
)

tests/test_main.cpp

#include <gtest/gtest.h>
#include "mylib.h"

TEST(ModuleTest, BasicAssertions) {
    EXPECT_NO_THROW(print_module1_info());
    EXPECT_NO_THROW(print_module2_info());
}

三、构建与测试流程

3.1 标准构建流程

# 1. 创建构建目录
mkdir build && cd build

# 2. 配置项目
cmake -DCMAKE_BUILD_TYPE=Debug ..

# 3. 编译项目 使用生成的构建系统文件进行编译,假设生成了 Makefile
make

# 4. 运行程序(两种方式)
./bin/MyExecutable        # 直接运行
make run                 # 通过自定义目标运行

# 5. 执行测试(两种方式)
./bin/TestMyLib           # 直接运行测试
ctest --output-on-failure # 通过 CTest 运行

3.2 安装与打包

# 安装到系统目录
cmake --install . --prefix /usr/local

# 生成安装包
cpack -G TGZ  # 生成 tar.gz 包
cpack -G DEB  # 生成 Debian 包

四、高级应用场景

4.1 交叉编译配置

基础版工具链文件(toolchain.cmake)

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

完整版工具链文件(arm-toolchain.cmake)

Cmake
# 目标平台配置
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

# 工具链路径
set(CMAKE_C_COMPILER "/opt/toolchains/arm-gcc/bin/arm-linux-gnueabihf-gcc")
set(CMAKE_CXX_COMPILER "/opt/toolchains/arm-gcc/bin/arm-linux-gnueabihf-g++")

# 系统根目录
set(CMAKE_SYSROOT "/opt/sysroots/arm-linux")

# 查找规则
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 -DCMAKE_TOOLCHAIN_FILE=arm-toolchain.cmake ..


 

4.2 静态分析集成

        通过静态分析集成,您可以在项目开发早期发现并修复问题,从而显著提高代码质量和开发效率。

# 在根 CMakeLists.txt 添加
option(ENABLE_CODE_ANALYSIS "Enable static analysis" OFF)
if(ENABLE_CODE_ANALYSIS)
    find_program(CLANG_TIDY clang-tidy)
    find_program(CPPCHECK cppcheck)
    
    if(CLANG_TIDY)
        set(CMAKE_CXX_CLANG_TIDY ${CLANG_TIDY}
            -checks=*,-modernize-use-trailing-return-type
        )
    endif()
    
    if(CPPCHECK)
        set(CMAKE_CXX_CPPCHECK ${CPPCHECK}
            --enable=all
            --suppress=missingInclude
            --inline-suppr
        )
    endif()
endif()

五、新旧实践对比

六、扩展建议

6.1 模块化开发

# 数学模块
add_subdirectory(math)

# 网络模块
add_subdirectory(network)

# 主程序链接模块
target_link_libraries(MyExecutable
    PRIVATE
        MathLib
        NetworkLib
)

6.2 性能优化

# 在根 CMakeLists.txt 添加
if(CMAKE_BUILD_TYPE STREQUAL "Release")
    add_compile_options(-march=native -O3)
endif()

# LTO 配置
include(CheckIPOSupported)
check_ipo_supported(RESULT ipo_supported)
if(ipo_supported)
    set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()

6.3 文档生成

find_package(Doxygen)
if(DOXYGEN_FOUND)
    doxygen_add_docs(docs
        ${PROJECT_SOURCE_DIR}/src/include
        COMMENT "Generate API documentation"
    )
endif()

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

攻城狮7号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值