## 概述

  • 目标:用现代 CMake 设计清晰的目标与依赖关系,统一构建入口,降低平台差异带来的复杂度。
  • 价值:摆脱旧式全局变量与手工包含路径,采用“目标为中心”的属性与链接模型,实现模块化与可复用。

## 技术参数与环境

  • CMake 版本:建议 `>= 3.21`(完整支持 `CMakePresets.json`;`FetchContent` 自 3.11 可用)。
  • 语言标准:`C++20`(通过目标属性启用)。
  • 生成器:`Ninja` 或平台默认(MSVC、Makefiles)。
  • 平台:Windows(MSVC/Clang)、Linux(GCC/Clang)、macOS(Apple Clang)。

## 基础项目结构

project-root/
  CMakeLists.txt
  CMakePresets.json
  src/
    main.cpp
  lib/
    CMakeLists.txt
    mylib.hpp
    mylib.cpp

## 顶层 CMakeLists(目标为中心)

cmake_minimum_required(VERSION 3.21)
project(modern_cmake LANGUAGES CXX)

add_subdirectory(lib)

add_executable(app src/main.cpp)
target_compile_features(app PRIVATE cxx_std_20)
target_link_libraries(app PRIVATE mylib fmt::fmt)

### 库目标定义(lib/CMakeLists.txt)

add_library(mylib STATIC mylib.cpp)
target_include_directories(mylib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_features(mylib PUBLIC cxx_std_20)

include(FetchContent)
FetchContent_Declare(
  fmt
  GIT_REPOSITORY https://github.com/fmtlib/fmt.git
  GIT_TAG 11.0.2
)
FetchContent_MakeAvailable(fmt)
target_link_libraries(mylib PUBLIC fmt::fmt)

### 示例源码

// src/main.cpp
#include "mylib.hpp"
int main() {
  run_demo();
}

// lib/mylib.hpp
#pragma once
void run_demo();

// lib/mylib.cpp
#include <fmt/format.h>
void run_demo() {
  fmt::print("Hello Modern CMake\\n");
}

## 统一入口:CMakePresets.json

{
  "version": 6,
  "configurePresets": [
    {
      "name": "default",
      "generator": "Ninja",
      "binaryDir": "build",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release"
      }
    }
  ],
  "buildPresets": [
    { "name": "default", "configurePreset": "default" }
  ]
}

说明:使用 Presets 可在不同环境下复用相同的配置与构建入口,避免脚本分叉。


## 构建与运行

  • 通用命令:
  • cmake --preset default
    cmake --build --preset default
    
  • 或不使用 Presets:
  • cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
    cmake --build build
    

## 依赖管理策略

  • 优先使用“目标”为单位的链接:`target_link_libraries(app PRIVATE mylib)`。
  • 第三方库优先 `find_package(... CONFIG REQUIRED)`,如有困难再用 `FetchContent` 引入源代码。
  • 为公共 API 暴露头文件目录:`target_include_directories(mylib PUBLIC ...)`;实现细节用 `PRIVATE`。
  • 版本锁定:为 `FetchContent` 指定稳定 `GIT_TAG`,以保证可重复构建。

## 跨平台要点

  • Windows/MSVC:默认生成器即可;或 `Ninja` 配合 MSVC 编译工具链。
  • Linux:GCC/Clang 均可;确保安装 `ninja-build` 包。
  • macOS:Apple Clang;`xcode-select --install`;可选择 `Ninja` 或 `Xcode` 生成器。

## 常见问题与解法

  • 全局变量与 `include_directories()` 造成污染:改用目标属性与 `target_include_directories()`。
  • 手工拷贝依赖:用 `find_package` 或 `FetchContent`;保持单一真实来源。
  • Debug/Release 配置不一致:收敛到 Presets,统一入口与输出目录。

## 注意事项(发布规范)

  • 关键词需与正文高度相关:`CMake`、`Presets`、`FetchContent`、目标属性。
  • 分类匹配:`C-C++`。
  • 描述准确概括核心价值:现代实践 + 可维护架构 + 依赖管理。
  • 技术参数已验证:CMake 3.21+ 的 Presets、FetchContent、目标属性在主流平台支持良好。
  • 文件名与标题一致:`现代CMake实践:可维护跨平台工程与包管理.md`。

---


采用现代 CMake 能显著提升工程可维护性与跨平台一致性。通过目标中心的设计与 Presets 的统一入口,团队可在不同平台快速复现一致的构建与依赖配置。



点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部