GCC-12下header-only模式引入fmt/format.h编译失败问题
GCC 12 编译引入fmt/format库触发内部编译器错误解决方案
关联信息
- 自定义封装头文件
format:
#pragma once #define FMT_HEADER_ONLY #include "fmt/format.h" namespace std { using fmt::format; using fmt::format_error; using fmt::formatter; }
- 测试源文件
helloworld.cpp:
// helloworld.cpp import <iostream>; #include "format" int main() { std::cout << std::format("There are {} ways I love you.", 219) << std::endl; return 0; }
- 执行的编译命令:
g++-12 -std=c++2a -fmodules-ts -xc++-system-header iostream g++-12 -std=c++2a -fmodules-ts helloworld.cpp
- 触发的报错:
fmt/format.h:1010:54: internal compiler error: in cxx_eval_call_expression, at cp/constexpr.cc:2835 1010 | return {result.grouping, Char(result.thousands_sep)}; | ^
- 运行环境:
- 操作系统:WSL2/Ubuntu 22.04 LTS
- GCC版本:12
- fmt库版本:8.1.1
问题根因
该报错是GCC 12早期版本C20模块特性实现缺陷导致的内部编译器错误,和业务代码逻辑无关。fmt 8.1.1发布时GCC 12的C20模块支持尚处于实验阶段,预编译系统头文件模块后引入header-only模式的fmt库,会在constexpr求值环节触发编译器源码层面的已知bug,直接中断编译流程。
可落地解决方法
按改动成本从低到高排序:
- 替换模块导入为传统头文件引入:将
helloworld.cpp里的import <iostream>;改为#include <iostream>,去掉编译时的模块相关参数,直接用正式C++20标准编译即可绕过bug,不需要升级任何依赖:
注:g++-12 -std=c++20 helloworld.cpp-std=c++2a是C++20正式发布前的实验性标准开关,正式场景优先使用-std=c++20,稳定性更好。 - 升级fmt库版本:将fmt升级到9.0及以上版本,高版本fmt已经针对GCC 12/13的实验性模块实现做了兼容适配,不需要修改原有代码和编译逻辑即可正常编译。
- 升级GCC版本:将GCC 12升级到12.3及以上的最新小版本,或直接升级到GCC 13,后续版本已经修复了该constexpr求值和模块交互的bug,原有代码和fmt版本都不需要调整即可正常编译。
内容的提问来源于stack exchange,提问作者Xiao Yang
相关产品推荐
相关产品推荐

