引入 fmt 后旧编码源码编译异常:区分 /utf-8 的两层作用
fmt 的 Unicode CMake 配置会在 MSVC 上传递 /utf-8,同时改变源文件和字符串字面量编码。旧编码工程应先确认实际编译参数,再选择迁移或受控关闭。
旧 C++ 工程加入 fmt 的 CMake 目标后,某些原本按本地编码保存的源码出现字符解释错误。先查看 MSVC 实际命令行是否新增了 /utf-8,不要只改 Windows 控制台代码页。
fmt 12.2.0 的 CMake Unicode 路径会为 MSVC 消费者传递 /utf-8。这个选项同时设置源字符集与执行字符集为 UTF-8,相当于 /source-charset:utf-8 和 /execution-charset:utf-8。它改变的不只是终端显示,也会影响编译器怎样理解源码和生成窄字符串字面量。
能迁移时,先统一源码编码
优先确认受影响文件的真实编码、是否带 BOM,以及代码生成器和编辑器保存方式。准备迁移到 UTF-8 时,在版本控制中检查转换前后的文字内容,避免把已有乱码重新编码后固定下来。
fmt 自己的头与测试使用 UTF-8。只从传递选项中删掉 /source-charset:utf-8,不能证明所有库代码与业务代码仍会按预期解释。控制台 chcp、系统区域设置和源码编译选项也不能相互替代。
必须保留旧编码时明确取舍
fmt 提供 FMT_UNICODE CMake 选项。对仍需兼容旧源码编码的项目,可以在引入 fmt 之前显式关闭:
set(FMT_UNICODE OFF CACHE BOOL "Enable Unicode support." FORCE)
add_subdirectory(external/fmt)
实际目录替换为项目中的 fmt 路径。FORCE 会覆盖该构建目录中已有值,应作为明确的工程策略使用。此设置会改变 fmt 的 Unicode 配置,不只是去掉一项警告;必须确认项目不依赖被关闭的行为。
如果业务仍要求窄字符串字面量为 UTF-8,却必须用其他源编码,应分别核对 /source-charset 与 /execution-charset 的选择,并在自身目标上配置,不要假定一个 CMake 开关已经完成所有转换。可用转义形式表达字符,但也应验证生成的字节;写出 \u 并不能代替整条工具链的编码检查。
修改后检查所有消费 fmt 的目标实际参数,并覆盖非 ASCII 文本、格式化结果和输出接收端。编译成功只说明字符被接受,不能证明没有替换字符或数据损失。保留编码转换和构建配置差异,回退时一并恢复,避免源码编码与编译参数再次不匹配。


