feat: add fmt 12.2.0 as C++23 module package (import fmt;)#63
Open
1115040131 wants to merge 1 commit into
Open
feat: add fmt 12.2.0 as C++23 module package (import fmt;)#631115040131 wants to merge 1 commit into
1115040131 wants to merge 1 commit into
Conversation
Module sibling of the header-based compat.fmt: the public `fmt` package (empty namespace) exposes the C++23 module `fmt` so users write `import fmt;`. fmt's release ships an official module unit at src/fmt.cc, but mcpp's M1 scanner rejects any `import` inside a conditional preprocessor block (even a dead one), and fmt.cc guards `import std;` behind `#ifdef FMT_IMPORT_STD`. So the descriptor reproduces fmt.cc via generated_files with exactly those three lines removed — everything else verbatim, including the tail `#include "format.cc"/"os.cc"` that attaches the implementation to module fmt. include_dirs exposes */include and */src so both the module unit and its impl includes resolve. Empty-namespace packages can't be workspace members (like the imgui module package), so a thin driver tests/smoke_fmt_module.sh reseeds the default index and consumes `import fmt;`, wired into validate.yml as the fmt-module job. Verified locally on mcpp 0.0.81 (== CI): the smoke builds module fmt and its behavioral assertions pass. No mcpp-res write access, so the download url is a plain upstream string (CN mirror to be added by a maintainer). Co-Authored-By: Claude <noreply@anthropic.com>
Sunrisepeak
requested changes
Jul 7, 2026
| # thin driver that reseeds the default index and consumes `import fmt;`. | ||
| fmt-module: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 60 |
| modules = { "fmt" }, | ||
| include_dirs = { "*/include", "*/src" }, | ||
| generated_files = { | ||
| ["mcpp_generated/fmt_module.cc"] = "// Formatting library for C++ - C++20 module\n//\n// Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors\n// All rights reserved.\n//\n// For the license information refer to format.h.\n\nmodule;\n\n#define FMT_MODULE\n\n#ifdef _MSVC_LANG\n# define FMT_CPLUSPLUS _MSVC_LANG\n#else\n# define FMT_CPLUSPLUS __cplusplus\n#endif\n\n// Put all implementation-provided headers into the global module fragment\n// to prevent attachment to this module.\n#ifndef FMT_IMPORT_STD\n# include <algorithm>\n# include <bitset>\n# include <chrono>\n# include <cmath>\n# include <complex>\n# include <cstddef>\n# include <cstdint>\n# include <cstdio>\n# include <cstdlib>\n# include <cstring>\n# include <ctime>\n# include <exception>\n# if FMT_CPLUSPLUS > 202002L\n# include <expected>\n# endif\n# include <filesystem>\n# include <fstream>\n# include <functional>\n# include <iterator>\n# include <limits>\n# include <locale>\n# include <memory>\n# include <optional>\n# include <ostream>\n# include <source_location>\n# include <stdexcept>\n# include <string>\n# include <string_view>\n# include <system_error>\n# include <thread>\n# include <type_traits>\n# include <typeinfo>\n# include <utility>\n# include <variant>\n# include <vector>\n#else\n# include <limits.h>\n# include <stdint.h>\n# include <stdio.h>\n# include <stdlib.h>\n# include <string.h>\n# include <time.h>\n#endif\n#include <cerrno>\n#include <climits>\n#include <version>\n\n#if __has_include(<cxxabi.h>)\n# include <cxxabi.h>\n#endif\n#if defined(_MSC_VER) || defined(__MINGW32__)\n# include <intrin.h>\n#endif\n#if defined __APPLE__ || defined(__FreeBSD__)\n# include <xlocale.h>\n#endif\n#if __has_include(<winapifamily.h>)\n# include <winapifamily.h>\n#endif\n#if (__has_include(<fcntl.h>) || defined(__APPLE__) || \\\n defined(__linux__)) && \\\n (!defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP))\n# include <fcntl.h>\n# include <sys/stat.h>\n# include <sys/types.h>\n# ifndef _WIN32\n# include <unistd.h>\n# else\n# include <io.h>\n# endif\n#endif\n#ifdef _WIN32\n# if defined(__GLIBCXX__)\n# include <ext/stdio_filebuf.h>\n# include <ext/stdio_sync_filebuf.h>\n# endif\n# define WIN32_LEAN_AND_MEAN\n# include <windows.h>\n#endif\n\nexport module fmt;\n\n\n#define FMT_EXPORT export\n#define FMT_BEGIN_EXPORT export {\n#define FMT_END_EXPORT }\n\n// If you define FMT_ATTACH_TO_GLOBAL_MODULE\n// - all declarations are detached from module 'fmt'\n// - the module behaves like a traditional static library, too\n// - all library symbols are mangled traditionally\n// - you can mix TUs with either importing or #including the {fmt} API\n#ifdef FMT_ATTACH_TO_GLOBAL_MODULE\nextern \"C++\" {\n#endif\n\n#ifndef FMT_OS\n# define FMT_OS 1\n#endif\n\n// All library-provided declarations and definitions must be in the module\n// purview to be exported.\n#include \"fmt/args.h\"\n#include \"fmt/chrono.h\"\n#include \"fmt/color.h\"\n#include \"fmt/compile.h\"\n#include \"fmt/format.h\"\n#if FMT_OS\n# include \"fmt/os.h\"\n#endif\n#include \"fmt/ostream.h\"\n#include \"fmt/printf.h\"\n#include \"fmt/ranges.h\"\n#include \"fmt/std.h\"\n#include \"fmt/xchar.h\"\n\n#ifdef FMT_ATTACH_TO_GLOBAL_MODULE\n}\n#endif\n\n#ifdef FMT_ATTACH_TO_GLOBAL_MODULE\nextern \"C++\" {\n#endif\n\n#if FMT_HAS_INCLUDE(\"format.cc\")\n# include \"format.cc\"\n#endif\n#if FMT_OS && FMT_HAS_INCLUDE(\"os.cc\")\n# include \"os.cc\"\n#endif\n\n#ifdef FMT_ATTACH_TO_GLOBAL_MODULE\n}\n#endif\n", |
Member
There was a problem hiding this comment.
这个可以使用多行语法展开 不用使用 \n 放到单行。类似下面
generated_files = {
["mcpp_generated/nlohmann.json.cppm"] = [[
// L1
// L2
// ....
]],
},
| if [[ -z "$MCPP_BIN" || ! -x "$MCPP_BIN" ]]; then | ||
| echo "FATAL: set MCPP=/path/to/mcpp or put mcpp on PATH" >&2 | ||
| exit 1 | ||
| fi |
Sunrisepeak
requested changes
Jul 7, 2026
| -- (no glob), like nlohmann.json / compat.eigen. | ||
| package = { | ||
| spec = "1", | ||
| namespace = "", |
Member
|
这个62PR 很规范, 建议 本PR直接 作为支持模块化的 fmt 库 然后 添加类似 62的 tests 最小测试工程。就可以省略 62 compat 模式了 |
Member
|
最新版本好像默认就是支持 模块化的 不用额外 使用 generated_files 好像 |
Member
|
#ifdef FMT_IMPORT_STD 包描述文件直接定义这个宏就可以了 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概述
新增公开的
fmt包(空命名空间),将 {fmt} 12.2.0 以 C++23 模块形态收录,用户可直接
import fmt;。它是 header 版compat.fmt的模块孪生包,两者消费模型不同、可共存。
形态:module wrapper(generated_files)
fmt 的 release 自带官方模块单元
src/fmt.cc(export module fmt;),但不能逐字喂给 mcpp:mcpp 的 M1 模块扫描器拒绝任何位于条件预处理块内的
import(即使是不启用的死分支),而 fmt.cc 把
import std;包在#ifdef FMT_IMPORT_STD里。该限制在 mcpp 0.0.81 / 0.0.82 / main 均存在,非版本问题。
因此描述符用
generated_files复刻 fmt.cc,仅删除那 3 行(#ifdef/import std;/#endif),其余逐字保留:#include(std 头挂到全局模块)export module fmt;(mcpp 据此注册 provider)export)#include "format.cc"/"os.cc"(把实现附着到模块 fmt;若作为独立 TU编译会留在全局模块,破坏模块链接)
include_dirs暴露*/include(模块单元的#include <fmt/*.h>可解析)与*/src(末尾 impl include 可解析)。import_std = false(默认走文本 std 头)。CI
空命名空间包无法作为 workspace 成员(同公开的
imgui包:空命名空间映射到mcpp 内建默认索引,
[indices]无法把默认索引重定向到本地 path)。故新增tests/smoke_fmt_module.sh—— reseed 默认索引后消费import fmt;,在validate.yml中作为fmt-modulejob 运行(与imgui-module同构)。镜像
无 mcpp-res 写权限,下载 url 采用纯上游字符串(lint 对纯字符串 url 放行),
CN 镜像待维护者后续补充。
验证
mcpp 0.0.81(与 CI
MCPP_VERSION一致)本地跑 smoke:构建模块fmt并通过行为断言。
本地复现 CI lint 全过,validate.yml YAML 校验通过。