{fmt} 快速上手:CMake 集成、多包管理器安装与从源码构建完整指南
2026/9/11 15:51:47 网站建设 项目流程

{fmt} 快速上手:CMake 集成、多包管理器安装与从源码构建完整指南

【免费下载链接】fmtA modern formatting library项目地址: https://gitcode.com/GitHub_Trending/fm/fmt

{fmt} 是一个开源的现代 C++ 格式化库,以安全、快速、易用的方式替代 C stdio 与 C++ iostreams,并实现了 C++20std::format与 C++23std::print的核心功能。本篇指南基于本仓库的 doc/get-started.md 快速上手文档,系统讲解在项目中使用 {fmt} 的全部路径:三种 CMake 集成方式、主流包管理器安装、从源码构建与运行测试、C++20 Module 支持,以及其他构建系统(build2、Meson、Android NDK)的接入方法。读完后你将能根据自己的项目类型和构建环境,选择最合适的 {fmt} 接入与部署方案,并完成从printffmt::print的平滑迁移。

本文对应的仓库为当前 {fmt} 源码树,其版本定义位于 include/fmt/base.h:#define FMT_VERSION 120201,即 12.2.1(版本号编码规则为主版本 * 10000 + 次版本 * 100 + 补丁版本)。

与构建系统无关的通用特性

{fmt} 与任何构建系统兼容。无论你使用 CMake、Meson、build2、Bazel、Android NDK,还是手写 Makefile,都可以接入。库本身的源码组织非常精简:公共 API 集中在include/fmt/目录下的若干头文件中(base.h、format.h、chrono.h、color.h、ranges.h、os.h、printf.h 等),核心实现位于 src/format.cc,操作系统相关 API 位于 src/os.cc。

如果你只是想在浏览器里快速体验 {fmt} 的格式化语法,也可以使用 Compiler Explorer 在线编译运行仓库中的示例代码,无需本地安装任何东西。

使用 CMake 集成 {fmt}

{fmt} 提供开箱即用的 CMake 支持,并暴露以下导入目标(target):

目标名说明
fmt::fmt标准编译库(推荐),编译时间开销最小
fmt::fmt-header-only头文件库(header-only),通过FMT_HEADER_ONLY宏启用
fmt::fmt-moduleC++20 模块库,仅在FMT_MODULECMake 选项开启时可用

官方建议优先使用编译库或模块库,以获得更好的构建性能。这三种目标的定义可以在仓库根目录 CMakeLists.txt 中找到:编译库fmt由 src/format.cc 与全部头文件构建(CMakeLists.txt),fmt-header-only是一个 INTERFACE 库,向其消费者传播FMT_HEADER_ONLY=1宏定义(CMakeLists.txt),而fmt-module则在FMT_MODULE开启时由模块源文件 src/fmt.cc 构建(CMakeLists.txt)。

方式一:FetchContent(自动下载依赖)

从 CMake 3.11 开始,可以在配置阶段通过FetchContent自动下载 {fmt} 作为项目依赖:

include(FetchContent) FetchContent_Declare( fmt GIT_REPOSITORY https://github.com/fmtlib/fmt GIT_TAG e69e5f977d458f2650bb346dadf2ad30c5320281) # 10.2.1 FetchContent_MakeAvailable(fmt) target_link_libraries(<your-target> fmt::fmt)

需要注意:原文档示例中的GIT_TAG指向 10.2.1 版本的提交哈希,而本仓库当前版本为 12.2.1(见 include/fmt/base.h)。实际使用时建议将GIT_TAG更新为你需要的具体版本号标签或对应提交,以保证行为与预期一致。

方式二:已安装版本(find_package)

如果系统上已通过包管理器或make install安装了 {fmt},可以在CMakeLists.txt中直接查找并使用:

find_package(fmt) target_link_libraries(<your-target> fmt::fmt)

find_package(fmt)会读取安装时生成的fmt-config.cmake配置(模板见 support/cmake/fmt-config.cmake.in),并导入命名空间目标。仓库还提供了一个最小化的验证工程 test/find-package-test/CMakeLists.txt,展示了find_package(FMT REQUIRED)后同时链接fmt::fmtfmt::fmt-header-only的完整写法,其 main.cc 中fmt::print的用法可以直接参考。注意find_package(fmt)find_package(FMT)两种写法均被支持。

方式三:嵌入式子目录(add_subdirectory)

将 {fmt} 源码树放进你的项目,并在CMakeLists.txt中加入:

add_subdirectory(fmt) target_link_libraries(<your-target> fmt::fmt)

这种方式的验证工程位于 test/add-subdirectory-test/CMakeLists.txt,它通过add_subdirectory(../.. fmt)引入 {fmt},并分别链接了fmt::fmtfmt::fmt-header-only,还测试了"依赖 {fmt} 的目标自身可被export"的场景。

替换目标:header-only 与 module

要使用头文件库或模块库,只需把上述三种方式中的fmt::fmt替换为fmt::fmt-header-onlyfmt::fmt-module即可:

# 头文件库 target_link_libraries(<your-target> fmt::fmt-header-only) # 模块库(需先启用 FMT_MODULE) target_link_libraries(<your-target> PRIVATE fmt::fmt-module)

从源码结构看,fmt-header-only通过FMT_HEADER_ONLY=1宏定义工作(CMakeLists.txt),因此无需编译 src/format.cc 即可使用全部格式化功能,代价是每个包含头文件的翻译单元都会实例化实现代码,可能增加编译时间。

使用 C++20 Module

fmt::fmt-module目标仅在FMT_MODULECMake 选项开启时可用。启用方式有两种:

  1. 在加入 {fmt} 之前配置项目时传入-DFMT_MODULE=ON
  2. CMAKE_CXX_STANDARD设为至少 20——在工具链支持时,模块支持会被自动启用。

启用后,链接到fmt::fmt-module,并用import fmt;替代#include头文件:

import fmt; int main() { fmt::print("Hello, world!\n"); }

使用 CMake 原生 C++ 模块支持时有如下工具链前提:

  • CMake 3.28 或更新版本;
  • 使用 Ninja 生成器时,Ninja 1.11 或更新版本;
  • 使用 GCC 时,GCC 15 或更新版本。

{fmt} 同时为其他工具链提供了回退构建路径(fallback build path)。这一逻辑与仓库根目录 CMakeLists.txt 中FMT_USE_CMAKE_MODULES的探测逻辑一致:它要求 CMake ≥ 3.28 且 C++ 标准 ≥ 20,并对 Ninja(≥ 1.11)配合 GCC ≥ 15、Clang ≥ 16 或 MSVC ≥ 17.4 的组合进行检测;AppleClang 21 及以上也会启用模块支持(CMakeLists.txt)。

模块库的完整导出实体可以通过 test/module-test.cc 一窥全貌:该测试文件直接import fmt;,覆盖了fmt::formatfmt::format_tofmt::print、命名参数、时间日期、颜色、printf兼容接口等几乎全部公开 API,并验证了命名模块不会泄漏宏定义([cpp.import]/5.1)等语义。

通过包管理器安装

Debian / Ubuntu(apt)

在 Debian、Ubuntu 或其他基于 Debian 的 Linux 发行版上:

apt install libfmt-dev

安装后即可在 CMake 中通过find_package(fmt)使用(见上文"方式二")。

macOS(Homebrew)

在 macOS 上使用 Homebrew 安装:

brew install fmt

跨平台(Conda)

在 Linux、macOS 和 Windows 上均可通过 Conda 及其 conda-forge 频道安装:

conda install -c conda-forge fmt

Windows / Linux(vcpkg)

vcpkg 是微软维护的 C/C++ 包管理器,按如下流程安装:

git clone https://github.com/Microsoft/vcpkg.git cd vcpkg ./bootstrap-vcpkg.sh ./vcpkg integrate install ./vcpkg install fmt

安装完成后,在 CMake 项目中配合CMAKE_TOOLCHAIN_FILE指向 vcpkg 工具链,即可通过find_package(fmt)使用。

跨平台(Conan)

使用 Conan 包管理器,从 Conan Center 获取 {fmt}:

conan install -r conancenter --requires="fmt/[*]" --build=missing

--requires="fmt/[*]"表示获取 fmt 的最新可用版本,--build=missing表示对缺失的预编译包从源码构建。

从源码构建 {fmt}

CMake 通过生成原生 makefile 或工程文件来适配你选择的编译器环境。典型流程从仓库根目录开始:

mkdir build # 创建存放构建输出的目录 cd build cmake .. # 生成原生构建脚本

在 Unix-like 系统上,此时当前目录会生成 Makefile,然后:

make # 编译库 make test # 运行测试

控制测试目标:FMT_TEST

make test测试目标的生成由FMT_TESTCMake 选项控制(默认开启)。当你把 {fmt} 作为子目录嵌入自己的项目、又不希望把 {fmt} 的测试并入你项目的test目标时,可以这样关闭:

cmake -DFMT_TEST=OFF ..

该选项在 CMakeLists.txt 中声明,并在 test/CMakeLists.txt 中注册了大量测试:args-testbase-testchrono-testcolor-testformat-testprintf-testranges-teststd-testunicode-testxchar-test等,另有perf-sanity性能冒烟测试程序,以及仅在FMT_MODULE开启时构建的module-test(test/CMakeLists.txt)。

构建共享库:BUILD_SHARED_LIBS

默认构建的是静态库。要构建共享库,将BUILD_SHARED_LIBS设为TRUE

cmake -DBUILD_SHARED_LIBS=TRUE ..

在共享库模式下,构建系统会为fmt定义FMT_LIB_EXPORT(私有)与FMT_SHARED(接口)宏(CMakeLists.txt),以正确处理符号导出。

位置无关代码:CMAKE_POSITION_INDEPENDENT_CODE

如果要把静态库链接进另一个共享库(例如 Python 扩展模块),需要构建带位置无关代码(PIC)的静态库:

cmake -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE ..

安装到系统

构建完成后,在 Unix-like 系统上执行:

sudo make install

安装会将头文件、库文件以及 CMake 配置包(fmt-config.cmakefmt-config-version.cmake)和 pkg-config 文件(fmt.pcfmt-c.pc,模板见 support/cmake/fmt.pc.in 与 support/cmake/fmt-c.pc.in)一同部署,之后即可在其他工程中find_package(fmt)使用。

构建文档

构建 API 文档需要以下软件:

  • Python
  • Doxygen
  • MkDocs,并安装mkdocs-materialmkdocstringspymdown-extensionsmike插件

先按前文方式用 CMake 生成构建脚本,然后编译doc目标:

make doc

从当前仓库的 CMakeLists.txt 看,doc自定义目标会检查doxygenmkdocs是否可用(缺失时自动禁用该目标),然后以 support/mkdocs.yml 为配置、在构建目录下生成 HTML 文档。本文涉及的入门指南 doc/get-started.md 连同 doc/api.md、doc/syntax.md 等即属于该文档工程的一部分。

常用 CMake 选项一览

以下选项均可在 CMakeLists.txt 中找到定义,供配置时参考:

选项默认值作用
FMT_DOC主项目时 ON生成doc文档目标
FMT_INSTALL主项目时 ON生成install安装目标
FMT_TEST主项目时 ON生成test测试目标
FMT_FUZZOFF生成模糊测试目标
FMT_CUDA_TESTOFF生成 CUDA 测试目标
FMT_OSON是否包含操作系统相关 API(src/os.cc)
FMT_MODULE视工具链而定是否构建 C++20 模块库
FMT_SYSTEM_HEADERSOFF将头文件以 system header 方式暴露,避免警告
FMT_UNICODEON启用 Unicode 支持
FMT_PEDANTICOFF启用额外警告与较昂贵的测试
FMT_WERROROFF编译警告按错误处理

在其他构建系统中使用

build2

build2 是一个集依赖管理于一体的构建系统,{fmt} 在其中可作为包使用:

  • 包名:fmt
  • 库目标名:lib{fmt}

让 build2 工程依赖 {fmt}:

  1. 将 {fmt} 包仓库加入配置或repositories.manifest(如尚未加入):
: role: prerequisite location: https://pkg.cppget.org/1/stable
  1. manifest文件中添加依赖(以版本 10 为例,按实际所需版本调整):
depends: fmt ~10.0.0
  1. buildfile中导入目标并作为前置依赖:
import fmt = fmt%lib{fmt} lib{mylib} : cxx{**} ... $fmt

然后照常使用bbdep update构建项目。

Meson

Meson WrapDB 收录了fmt子项目,接入方式如下:

  1. 在工程根目录执行,安装fmt子项目:
meson wrap install fmt
  1. meson.build中添加子项目并取得依赖对象:
fmt = subproject('fmt') fmt_dep = fmt.get_variable('fmt_dep')
  1. 在目标中链接该依赖:
my_build_target = executable( 'name', 'src/main.cc', dependencies: [fmt_dep])

构建变体选项:

{fmt} 既可以构建为静态库,也可以构建为纯头文件库。

静态构建:

fmt = subproject('fmt', default_options: 'default_library=static') fmt_dep = fmt.get_variable('fmt_dep')

头文件库构建:

fmt = subproject('fmt', default_options: ['header-only=true']) fmt_dep = fmt.get_variable('fmt_header_only_dep')

注意头文件库变体获取的是fmt_header_only_dep变量。

Android NDK

仓库提供了现成的 support/Android.mk 文件,可用于通过 Android NDK 构建 {fmt} 库。将 {fmt} 源码目录加入你的 Android 工程后,即可在Android.mk中引用该构建描述。仓库 test/cuda-test/CMakeLists.txt 等工程也展示了 {fmt} 在多工具链环境中的接入方式。

其他构建系统

对于任何其他构建系统,最底层的接入方式是把以下文件加入工程:

  • include/fmt/base.h(基础 API,建议最先包含)
  • include/fmt/format.h(核心格式化 API)
  • include/fmt/format-inl.h(实现细节头文件)
  • src/format.cc(核心实现,必须参与编译与链接)
  • 按需加入其他头文件,例如 include/fmt/chrono.h、include/fmt/color.h、include/fmt/ranges.h、include/fmt/os.h、include/fmt/printf.h 等

具体步骤:将include目录加入头文件搜索路径,并确保src/format.cc被编译并链接进你的目标。如需操作系统相关 API,还需加入 src/os.cc。这也是 {fmt} 的最小配置形态——仅需三个文件(base.hformat.hformat-inl.h)加一个实现单元,即可获得核心格式化能力。

从 printf 迁移到 fmt

对于存量代码库,clang-tidy 从 v18 起提供了modernize-use-std-print检查,可以自动将printffprintf调用转换为fmt::print(默认配置下转换为std::print,可通过配置改为输出fmt::print)。这让从 C 风格格式化迁移到类型安全的 {fmt} 变得几乎零成本。

{fmt} 的printf兼容层也值得一提:通过 include/fmt/printf.h 提供的fmt::printffmt::sprintffmt::fprintf可以直接沿用旧有%d%f风格,同时获得类型安全与 POSIX 位置参数扩展支持,可以视为迁移过程中的中间过渡方案。

结语

{fmt} 的接入路径覆盖了从"系统包管理器安装"到"源码级最小集成"的全部层次:CMake 用户可以选择 FetchContent、find_package、add_subdirectory 三种模式中的任意一种,并按需切换编译库、头文件库与 C++20 模块库;非 CMake 用户则可以使用 build2、Meson、Android NDK 或直接编译 src/format.cc 手工接入。仓库自带的 test/CMakeLists.txt 中的各类测试工程(find-package、add-subdirectory、module-test 等)本身就是最贴近实战的接入范例,遇到集成问题时可以直接对照排查。

【免费下载链接】fmtA modern formatting library项目地址: https://gitcode.com/GitHub_Trending/fm/fmt

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询