Skip to content

Commit d75f816

Browse files
committed
fix: 同步 Galay 5.0.2 Clang 模块修复
1 parent 4acf1b2 commit d75f816

6 files changed

Lines changed: 54 additions & 36 deletions

File tree

.agents/docs/2026-08-29-add-galay-plan.md

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
# Add Galay 5.0.1 (`gzj-creator.galay`)
1+
# Add Galay 5.0.2 (`gzj-creator.galay`)
22

33
Date: 2026-08-30
44
Upstream: <https://github.com/gzj-creator/galay>
5-
Tag: `v5.0.1` (`27d971b0a249189634740575540316fb963136f0`)
6-
Status: v5.0.1 local validation passes; CI run 33269372157 passes on Linux
7-
GCC, macOS, Windows, lint, and mirror checks, but Linux LLVM still exposes an
8-
upstream `async_aio.h` module-compatibility error.
5+
Tag: `v5.0.2` (`d58976711790e47d5b0ad272e068d516192a1a1e`)
6+
Status: upstream has published the Clang 22 module fix as v5.0.2. The index
7+
follows that immutable archive; local GCC/LLVM module and consumer checks,
8+
archive reproducibility, and the mcpp 2026.8.27.2 package tests pass. The
9+
updated PR still needs its post-sync GitHub Actions run.
910

1011
## 1. Shape and identity
1112

12-
Galay is source type (b), a library already developed for mcpp. Its v5.0.1
13+
Galay is source type (b), a library already developed for mcpp. Its v5.0.2
1314
release carries a complete `mcpp.toml`, so the index entry is Form A and does
1415
not duplicate its build recipe.
1516

@@ -30,21 +31,31 @@ not duplicate its build recipe.
3031

3132
Both platform entries use the immutable GitHub tag archive:
3233

33-
https://github.com/gzj-creator/galay/archive/refs/tags/v5.0.1.tar.gz
34+
https://github.com/gzj-creator/galay/archive/refs/tags/v5.0.2.tar.gz
3435

35-
The archive is 5,230,202 bytes. `sha256sum` was run twice on the complete
36+
The archive is 5,231,630 bytes. `sha256sum` was run twice on the complete
3637
archive and returned:
3738

38-
be864cf9467188c231cd69baed496c73d7e4bd29234b9349b284238576f14b77
39+
93a93fabcfeb1b0ae160f3082ed472571532ce208c112bf2697f94267b27332a
3940

4041
`tar -tzf` succeeds and confirms the root `mcpp.toml`, the tracked include
4142
layout, and the fifteen named C++23 module interfaces are present.
4243

43-
The v5.0.1 upstream patch changes the generated module preludes so `intrin.h`
44-
is only included for `_MSC_VER`, and `emmintrin.h` is only included on x86.
45-
This directly addresses the v5.0.0 CI failures on Linux LLVM and macOS, where
46-
Clang's resource `intrin.h` attempted `#include_next <intrin.h>` without an
47-
MSVC header behind it.
44+
The v5.0.1 upstream patch remains intact: the generated module preludes only
45+
include `intrin.h` for `_MSC_VER` and `emmintrin.h` on x86. This addresses the
46+
earlier v5.0.0 Linux LLVM/macOS intrinsic-header failure without changing the
47+
new release's guards.
48+
49+
The v5.0.2 fix addresses the separate Linux LLVM failure found in CI run
50+
33269750913, job 99146034674, with mcpp 2026.8.27.2 and LLVM 22.1.8. In
51+
v5.0.1, `async_aio.h` closed `namespace galay::async` and then defined the
52+
`AioCommitAwaitable::await_suspend` function template with a globally
53+
qualified-id. Because `galay_kernel.cppm` includes that header inside
54+
`export extern "C++"`, Clang 22 rejected the definition as not being at
55+
namespace scope and produced cascading `this`, `handle`, `m_waker`,
56+
`m_controller`, and `m_result` errors. v5.0.2 puts the definition back inside
57+
the `namespace galay::async` block. The declaration, template visibility,
58+
ABI, and Linux `USE_EPOLL` implementation remain unchanged.
4859

4960
## 3. CN mirror
5061

@@ -79,18 +90,22 @@ changed to require the documented empty state. The corrected test then passed.
7990

8091
- `mcpp xpkg parse pkgs/g/gzj-creator.galay.lua` passed with the Form-A result
8192
and Linux/macOS version lists.
82-
- `mcpp test -p galay` with the v5.0.1 descriptor passed on the local default
93+
- `mcpp test -p galay` with the v5.0.2 descriptor passed on the local default
8394
GCC toolchain: `test result ok. 1 passed; 0 failed`.
84-
- The CI-pinned mcpp 2026.8.27.2 Linux default test also passed:
85-
`test result ok. 1 passed; 0 failed`.
95+
- The CI-pinned mcpp 2026.8.27.2 Linux default and LLVM 22.1.8 tests pass:
96+
`test result ok. 1 passed; 0 failed` for each toolchain.
8697
- CI run 33269372157 passed on Linux default, macOS default, Windows default,
8798
lint, mirror reachability, graphics side-effect, and build checks.
88-
- CI's Linux LLVM leg still fails while compiling `galay.kernel`. Clang 22
89-
rejects the v5.0.1 `async_aio.h` out-of-class template definition inside the
90-
module's `export extern "C++"` block (`cannot export 'await_suspend' as it is
91-
not at namespace scope`, followed by invalid member accesses). This is a
92-
separate upstream source issue from the v5.0.0 intrinsic-header failure; the
93-
v5.0.1 prelude guard itself is now effective.
99+
- The upstream Clang 22 regression test (`kernel.alignsrc`) and the complete
100+
CMake/Ninja Linux module surface pass with both GCC and LLVM 22.1.8,
101+
including `USE_EPOLL` and `galay.kernel`.
102+
- A module consumer importing both `galay.utils` and `galay.kernel` compiles,
103+
instantiates `co_await AsyncAio::commit()`, and runs successfully under LLVM
104+
22.1.8; this confirms the template definition remains visible and member
105+
accesses bind to the awaitable instance.
106+
- The previous CI failure was reproduced from run 33269750913/job 99146034674
107+
before the upstream patch and is resolved by v5.0.2; the v5.0.1 intrinsic
108+
guards remain covered by the prelude regression test.
94109
- The build compiled 26 Galay units, including both default module interfaces,
95110
the kernel implementation units, and the transitive libaio package.
96111
- All six descriptor lint checks passed, and all 134 package descriptors passed
@@ -103,6 +118,6 @@ changed to require the documented empty state. The corrected test then passed.
103118

104119
When upstream publishes Windows support or a maintainer creates the
105120
`mcpp-res/galay` release asset, add the platform/mirror entry with the same
106-
archive bytes. The v5.0.1 release remains Linux/macOS in its own manifest, so
121+
archive bytes. The v5.0.2 release remains Linux/macOS in its own manifest, so
107122
the Windows example continues to compile a no-op test until a Windows package
108123
entry exists.

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@
99

1010
### Added
1111

12-
- 收录 `gzj-creator.galay` 5.0.1 原生 Form-A 模块包,覆盖 `galay.utils`
12+
- 收录 `gzj-creator.galay` 5.0.2 原生 Form-A 模块包,覆盖 `galay.utils`
1313
`galay.kernel` 默认模块,并加入 Unix 示例工程和索引文档。
1414

1515
### Fixed
1616

1717
- 跟进 Galay 5.0.1 对 C++23 module prelude 的跨平台 intrinsic 头文件守卫修复,
1818
避免 Clang 在 Linux/macOS 上错误转发 `intrin.h`
19+
- 跟进 Galay 5.0.2 将 `AioCommitAwaitable::await_suspend` 的类外模板定义放回
20+
`galay::async` 命名空间,修复 Clang 22 导出 `galay.kernel` 时的模块语义错误,
21+
同时保留 Linux `USE_EPOLL` AIO 后端行为。

docs/descriptor-examples.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ in the [root README](../README.md#reference-examples).
1313
| Shape | Examples |
1414
|------|------|
1515
| Native module library (Form A) | [`mcpplibs.xpkg`](../pkgs/x/xpkg.lua) · [`mcpplibs.tinyhttps`](../pkgs/t/tinyhttps.lua) · [`tensorvia-cpu`](../pkgs/t/tensorvia-cpu.lua) · [`ffmpeg`](../pkgs/f/ffmpeg.lua) (module layer; sources compiled directly through `compat.ffmpeg`) · [`opencv`](../pkgs/o/opencv.opencv.lua) (single repository: the module layer and the full OpenCV 5 source build both live in the package, and only this descriptor stays on the index side) · [`mcpplibs.grpc`](../pkgs/g/grpc.lua) (gRPC 1.83.0 — the one library here that CANNOT be a compat descriptor: upstream publishes no self-contained source artifact, its tag archive carrying abseil/protobuf/re2/boringssl/zlib as empty submodule placeholders, so [grpc-m](https://github.com/mcpplibs/grpc-m)'s release tarball IS that artifact. It vendors only gRPC's own source and takes the five dependencies from this index, so a consumer that also uses protobuf links one copy rather than two) |
16-
| Native multi-module library with feature-scoped sources | [`gzj-creator.galay`](../pkgs/g/gzj-creator.galay.lua) (Galay 5.0.1 — the upstream Form-A manifest exposes `galay.utils` and `galay.kernel` by default, while SSL, HTTP, database, RPC, MCP, and tracing modules stay behind named features and their corresponding dependencies. The index keeps the upstream manifest intact and tests the default module surface on Unix.) |
16+
| Native multi-module library with feature-scoped sources | [`gzj-creator.galay`](../pkgs/g/gzj-creator.galay.lua) (Galay 5.0.2 — the upstream Form-A manifest exposes `galay.utils` and `galay.kernel` by default, while SSL, HTTP, database, RPC, MCP, and tracing modules stay behind named features and their corresponding dependencies. The index keeps the upstream manifest intact and tests the default module surface on Unix.) |
1717
| C-source compat (with `features`) | [`compat.cjson`](../pkgs/c/compat.cjson.lua) · [`compat.zlib`](../pkgs/c/compat.zlib.lua) · [`compat.hiredis`](../pkgs/c/compat.hiredis.lua) (the classic 1.2.0 — a 7-TU C build whose flat tarball headers get `hiredis/`-prefixed wrapper headers via `generated_files`, so consumers write `#include <hiredis/hiredis.h>` exactly like upstream's install layout) · [`compat.sqlite3`](../pkgs/c/compat.sqlite3.lua) (plain C-source, no features: the single `sqlite3.c` amalgamation; 3.45.3, the final maintenance release of the most widely deployed 3.45.x line) · [`compat.libuv`](../pkgs/c/compat.libuv.lua) (libuv 1.48.0 — the per-OS source sets transcribed from upstream's CMakeLists, because a `src/unix/*.c` glob would compile every OS's backend at once; linux/macos get explicit unix subsets, windows globs `src/win/*.c`) | · [`compat.xxhash`](../pkgs/c/compat.xxhash.lua) (one TU, one header, no features at all — the interesting decision is what is NOT compiled: `xxh_x86dispatch.c` selects an AVX2/AVX512 path at RUNTIME and needs per-file `-mavx2` plus `XXH_X86DISPATCH` at every call site, so the package ships the flagless SSE2 baseline instead. Nor is the header-only `XXH_INLINE_ALL` mode chosen: it re-emits the implementation in every TU that hashes anything, which is the right trade only when there is exactly one such TU — something a package cannot know)
1818
| C-source compat where the library IS a kernel ABI | [`compat.libaio`](../pkgs/c/compat.libaio.lua) (libaio 0.3.113 — twelve syscall-wrapper TUs, and the only `xpm` section is `linux`, because there is no port to declare: `struct iocb` is the kernel's and every TU is `syscall(__NR_io_*, …)`. Consumers gate it with `[target.'cfg(linux)'.dependencies]`, the mirror image of compat.wil. Three things it teaches. **One public header out of a source dir**: upstream installs exactly one, `libaio.h`, but the tarball keeps it in `src/` beside the private headers — one of which is named `syscall.h` and would SHADOW glibc's for every consumer TU — so `include_dirs` names a `generated_files` forwarder and nothing else; the package's own sources reach the real header through it while their quote-form `#include "syscall.h"` still resolves next to the including `.c`, so no `-I` into `src/` is needed at all. **A `c_standard` that is a trap**: `-std=c11` sets `__STRICT_ANSI__`, which hides `syscall()` and `sigset_t`, and the public header then fails to parse at `io_pgetevents`; declaring `c_standard = "gnu11"` LOOKS like the fix but mcpp 2026.8.27.2 accepts the string and still emits `-std=c11` (visible in the emitted `compile_commands.json`), so `-D_GNU_SOURCE` in `cflags` is the spelling that takes effect. **Symbol versioning in a static package**: `io_getevents` and `io_cancel` have no ordinary definitions upstream — the functions are `io_getevents_0_4` etc. publishing short names through `.symver … @@LIBAIO_0.4` — which resolves for an executable under both ld.bfd and lld, but not when a consumer builds a `.so` straight out of these objects; that needs upstream's `src/libaio.map`, exactly as upstream's own `libaio.a` does) |
1919
| C++-source compat, one depending on the other | [`compat.abseil`](../pkgs/c/compat.abseil.lua) (151 TUs; a wildcard over `absl/**` trimmed by upstream's test/benchmark naming conventions) · [`compat.protobuf`](../pkgs/c/compat.protobuf.lua) (the libprotobuf runtime, 79 TUs transcribed from upstream's own `src/file_lists.cmake`; declares `compat.abseil` as a dependency because protobuf's public headers include `absl/…`, and its `gzip` feature defines `HAVE_ZLIB` and pulls `compat.zlib`, while `upb` adds protobuf's 64-TU C runtime out of the same tarball. It also exposes **`protoc`** as a `kind = "bin"` target, so a consumer writing `tools = ["protoc"]` gets the compiler built for its own machine out of the same package it links — making a generator/runtime version mismatch inexpressible) · [`compat.re2`](../pkgs/c/compat.re2.lua) (22 TUs, upstream's own `RE2_SOURCES`) · [`compat.redis-plus-plus`](../pkgs/c/compat.redis-plus-plus.lua) (redis++ 1.3.13 — the sync client, 17 TUs + `patterns/redlock.cpp`, depends on `compat.hiredis`; the one header CMake would generate, `hiredis_features.h`, is snapshotted via `generated_files`, and the async/TLS TUs are left out so the base build stays a two-package pair. An `async` feature adds the libuv-backed `AsyncRedis` interface (the 9 async TUs + `compat.libuv`; `event_loop.cpp` runs `uv_run` on a background thread, and `<hiredis/adapters/libuv.h>` arrives through compat.hiredis' wrapper headers). Two versions, one on each side of the source-structure watershed, share this ONE source list: 1.3.13 (modern 17-TU layout) and 1.3.3 (pre-`redis_uri.cpp`/`redlock` 15-TU layout) — the union works because 1.3.3's TUs are a strict subset, so exactly two globs match nothing there (a warning, not an error; same trick as compat.catch2)) | · [`compat.sqlitecpp`](../pkgs/c/compat.sqlitecpp.lua) (the RAII C++ wrapper over SQLite. Upstream vendors sqlite3 as a GIT SUBMODULE, so a source tarball simply does not contain it and the library cannot link — the dependency edge on `compat.sqlite3` replaces the submodule, and does it better: two consumers of SQLite in one link now share ONE amalgamation instead of each embedding a private copy with its own compile-time options. Its two CMake knobs are deliberately not set — `SQLITECPP_USE_ASSERT_ON_ERRORS` changes the error model from throwing to aborting, and `SQLITE_ENABLE_COLUMN_METADATA` has to agree with how SQLite ITSELF was built; both are the consumer's call, and the headers already guard them with `#ifdef`)

0 commit comments

Comments
 (0)