Skip to content

Commit 82cdb6d

Browse files
authored
test(grpc): 新增 grpc-codegen 成员 —— 一条依赖经已发布索引拿到整条工具链 (#174)
* test(grpc): 新增 grpc-codegen 成员 —— 一条依赖经**已发布索引**拿到整条工具链 这是唯一能证明 `reexport = true` 真的经由已发布索引到达消费者的地方:mcpp 自己的 e2e 用的都是 path 依赖,grpc-m 的 examples/greeter 也是(它要测工作树)。 成员只声明: [target.'cfg(linux)'.dependencies.grpc] grpc = { version = "1.83.0", features = ["codegen"] } build.mcpp 一行 `grpcgen::generate_all()`,proto/ 里放一个 echo.proto,断言生成的 **service** stub 能用(`echotest.Echo`)—— 只跑 protoc 而没跑 grpc 插件的话, `Echo::service_full_name()` 根本不存在,所以半配置的 codegen 过不了这条。 它同时覆盖 `rerun_if_changed_glob`:文件清单没有写在任何地方。 顺带改掉两处已被本次推翻的陈述: * grpc-module 里「gRPC's codegen needs host tools mcpp cannot hand a consumer」 —— 自 mcpp 2026.8.6.2 起不再成立,reexport 正是把它们交出去的机制; * grpc.lua 头部还写着「归档换成 v1.83.0-2」,现已是 -3。 本机已跑通:service = echotest.Echo / grpc-codegen: OK。 * fix(grpc-codegen): windows 上带上规则包,让成员退化成可见的跳过 CI:`build.mcpp:8:8: fatal error: module 'grpcgen' not found`。 成员照抄 grpc-module 把 grpc 依赖放在 cfg(linux)/cfg(macos) 下(compat.openssl 没有 windows 条目),但 grpc-module **没有 build.mcpp**;本成员有,而 `import grpcgen;` 是**编译期**依赖 —— docs/01 §4.2 明令不得用 #if 包裹 import, 所以运行期的守卫救不了它。 grpcgen 是纯 C++23 规则包,自身没有平台受限的依赖,索引里**有 windows 条目**。 因此 windows 上单独声明它:import 成立,守在**调用**上早退。与 tests/examples/protobuf-protoc 的处理完全同形(`if target_os == windows return 0`), 成员照常构建,测试编译成一次可见的跳过。 Linux 本机复验:service = echotest.Echo / grpc-codegen: OK。 * ci: 在 xim-pkgindex#463(gcc alias 运行时展开 subos sysroot)发布后重跑 openssl 的 `assert.h: No such file or directory` 根因是 gcc alias 把安装机的 subos sysroot 写死了;#463 已合入并进入已发布索引(artifact xim-index-5f383b5 里可见 XLINGS_DYNAMIC_SUBOS_DIR)。此前那轮 job 起于修复传播之前。 * ci: 重跑 —— 上一轮死于 GitHub Actions 基础设施故障 Failed to resolve action download info. Error: Service Unavailable 与改动无关;`gh run rerun` 对该 run 不可用,故以空提交触发。 * ci: 再次重跑 —— GitHub Actions 仍处于 partial_outage 官方状态页确认 Actions partial_outage;上一轮 select 死于 `Failed to resolve action download info: Service Unavailable`,lint 被连带取消, workspace 因此全部 skip。与改动无关。 * ci: 重跑 —— 上一轮全部死于 GitHub Actions major_outage 官方状态页已恢复 operational。 * ci: 工具链安装是 job 的准备工作,不该由碰巧排第一的成员承担 grpc-codegen 在 linux 上死于 compat.openssl 的 install(): `stdlib.h: No such file or directory`。同一个成员在 macOS(那里 openssl 用 /usr/bin/cc)和 windows 上都过,而它的姊妹 grpc-module 排在第二、工具链已就位,构建同一个 openssl 毫无问题。 差别只有一个:它是本 shard 第一个成员,于是承担了 mcpp 的一次性 工具链自举 —— 并且是在**它自己的**环境里承担的。带自定义 `[indices]` 的成员用的是项目局部 xlings home (<member>/.mcpp/.xlings),而 openssl 走自己的 Makefile、用裸 gcc, 头文件搜索完全来自 xvm shim 的 --sysroot;那个 sysroot 指到项目局部 subos,它的 usr/include 是空的。 于是 job 的成败取决于成员**顺序**。这一步用一个没有 [indices] 的 最小工程把工具链装进共享 home,一次,单独一个进程,在任何成员开始 之前。这本身也更诚实:job 该显式准备自己的环境,而不是继承上一个 测试留下的副作用。 * bump(grpc): 三个描述符指向 v1.83.0-4 —— grpcgen 分层控制 L0–L3 grpcgen 从「两个旋钮 + 断崖」变成四层,每层是下一层的默认值: generate_all(opt) ≡ submit(plan_all(opt)),.grpc=true ≡ .plugins={cpp()}。 新增 extra_dirs(既生成又搜索)/imports(只搜索)/mock/protoc_args, plan_entries((root,name)) 公开,description 自述用了哪些旋钮。 sha256 991e9928…(GitCode 镜像已回探核验,与 GitHub 源码包逐字节一致)。 * Revert "ci: 工具链安装是 job 的准备工作,不该由碰巧排第一的成员承担" This reverts commit a35381c. * fix(openssl): 编译器也要由本描述符解析,而不是从环境里捡 linux 上 CC 一直留给 PATH,理由写在注释里:「on linux the xim gcc carries its own payload and is the right compiler to use」。二进制 是对的,「它自足」这半不对。 PATH 上的 gcc 是 xvm shim,shim 会注入 `--sysroot=<调用进程解析到的 subos>`(xim-pkgindex pkgs/g/gcc.lua) —— 而同一段注释写着契约的另一半: Consumers that bypass the shim supply their own header flags. OpenSSL 的 Makefile 调裸 `cc`,正是那一类。 这个 hook 的 cwd 在**消费方项目**的 xlings home 里 (<proj>/.mcpp/.xlings/data/runtimedir/openssl-<v>),于是 subos 解析 到项目那个 —— 它只装了该项目自己的东西,没有 usr/include,通常连 usr/ 都没有。而 `--sysroot` 指向空树不会回落,它会**关掉**默认搜索: include/internal/common.h:14:11: fatal error: stdlib.h: No such file .../xim-x-gcc/16.1.0/lib/gcc/.../limits.h:210:15: fatal error: limits.h (后一条是 gcc 自己的 #include_next,读起来像编译器坏了,并不是。) 所以按 make 和 perl 已有的做法办:从声明的 build dep 解析 C 库载荷, 把 payload gcc 需要的三样显式交给它 —— 头(-isystem)、crt(-B)、 -lc(-L)。--sysroot 重指到 glibc 载荷根,它不是 FHS 形状因而不贡献 任何搜索路径:既压掉 shim 注入的那个,又不给宿主 /usr/include 开门。 deps 用 xim:gcc 自己的区间(glibc@>=2.39 / linux-headers@5.11.1)而非 @latest:openssl 的产物要和该 gcc 链在一起,@latest 可能解析出比工具链 更新的 glibc。两边解析同一个节点,而且 gcc 在哪它们就已经在哪。 验证(本机 + xlings subos,非 docker): * 裸载荷 gcc 无 flag → fatal error: stdlib.h: No such file(精确复现) * 加上本次这组 flag → 编译+链接+运行通过 * openssl 成员端到端 → configdata.pm / Makefile 均带上构造出的 CC, test result ok. 1 passed * refactor(tests): 一个条件写一次 —— cfg(linux)+cfg(macos) 合成 cfg(unix) 两个 grpc 成员各有一对逐字相同的 [target.'cfg(linux)'] 与 [target.'cfg(macos)'] 段。它们表达的是**一个**事实——compat.openssl 没有 windows xpm 条目,所以 gRPC 在 windows 之外都可解析——一个事实 写两遍,就是下一次只改一处的机会。 mcpp 的谓词语言本来就够用:any()/all()/not() 加 unix 别名 (family == "unix",见 src/build/prepare.cppm 的 match_alias)。 本机核验:cfg(unix) 下 grpc-codegen 照常解析出 c-ares/openssl/re2/zlib。 * ci: 分片数跟着工作量走,而不是跟着「是否全量」 linux 分片在 1h30m17s 被取消——正好是 job 上限。没有任何东西坏掉: 一片里排了 grpc-codegen(3563s)与 grpc-module(1701s),装不下。 分片数原本是二元的(全量 linux 3 片,否则 1 片),那等于断言「非全量 就是小活」。并不是:改一个被广泛消费的描述符会选中所有消费者——本次 改 compat.openssl.lua 就选中了四个成员。 tests/member-timings.tsv 早就记着每个成员的实测耗时,plan_shards.lua 也早就按它做 LPT 装箱。所以扇出数就从同一张表来:把本次成员的 linux 耗时求和,每 ~45 分钟一片,上限 3(再多会被 runner 并发与每片固定开销 吃掉,见上方既有测量)。macOS 保持 1 片——它并发就是 1,多分只会串行。 同时把 grpc-codegen 的实测值补进表里(linux 3563 / macos 1715 / windows 31)。新成员此前没有条目,按中位数估算,正是它被低估的原因。 本机核验:四成员求和 5313s → 2 片,LPT 切成 shard 0: grpc-codegen (59min) shard 1: grpc-module asio-ssl openssl (29min) * ci: macOS 全量也装不下一片 —— 扇出改为逐平台按实测总量定 上一轮 linux 三片全过(1h17/1h09/44m),macOS 单片在 1h30m20s 撞顶。 原注释只从墙钟论证 macOS 不该分片(并发为 1,分了也串行),漏了另 一半:**每个分片是独立 job、各有各的 timeout-minutes**,所以分片同时 也是「让活装得下」的手段。串行不要紧,跑不完才要紧。 macOS 全量实测 6922s = 115 分钟,本来就超 90 上限;它此前能过,只是 因为总量刚好卡在线下,而 grpc-codegen(macOS 1715s)把它推了过去。 改为三平台同一条规则:从 tests/member-timings.tsv 求本次成员在该平台 的实测总和,每 ~70 分钟一片(在 90 上限下留 ~20 分钟冷缓存余量), 上限按各自 runner 并发定(linux 3 / macOS 2 / windows 2)。 本机核验: 全量 linux 3 片 ~75min · macOS 2 片 ~57min · windows 2 片 ~67min 本 PR 四成员 linux 2 片 ~44min · macOS 1 片 · windows 1 片 linux 全量是最紧的一档(实测最慢片 77/90),注释已写明后续两个杠杆。
1 parent bae3673 commit 82cdb6d

12 files changed

Lines changed: 308 additions & 44 deletions

File tree

.github/workflows/validate.yml

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,65 @@ jobs:
404404
"$1" "$2" "$3" "$4" "$5" "$6" "$i" "$7"
405405
done
406406
}
407-
if [ "$full" = 1 ]; then ln=3; mn=1; wn=2; else ln=1; mn=1; wn=1; fi
407+
# Shard count follows the WORK, per platform, measured.
408+
#
409+
# It used to be binary — full run: linux 3 / macos 1 / windows 2,
410+
# anything else: 1 each — which asserts two things that are not
411+
# true. "A partial run is small": touching a widely consumed
412+
# descriptor selects every member that consumes it, and this PR's
413+
# `pkgs/c/compat.openssl.lua` selected four; one linux shard took
414+
# grpc-codegen (3563s) and grpc-module (1701s) back to back and was
415+
# cancelled at exactly 1h30m, the job cap. "A full macOS run fits in
416+
# one shard": at 6922s measured it does not — it fit only while the
417+
# total sat just under the cap, and the run that added grpc-codegen
418+
# (1715s on macOS) pushed it to 1h30m20s.
419+
#
420+
# Sharding is not only a wall-clock lever. Each shard is its own job
421+
# with its own `timeout-minutes`, so it is also how the work is made
422+
# to FIT. That is the half the "macOS concurrency is 1, so extra
423+
# shards run back to back" note above left out: back to back is fine
424+
# when the alternative is not finishing.
425+
#
426+
# tests/member-timings.tsv already holds every member's measured
427+
# cost and plan_shards.lua already packs by it (LPT), so the fan-out
428+
# comes from the same table: sum this run's members for that
429+
# platform and take one shard per ~70 minutes, which leaves ~20
430+
# minutes of headroom under the 90-minute cap for a cold cache.
431+
#
432+
# The caps are where runner concurrency comes back in: linux 3 (the
433+
# measured concurrency — a 4th shard would queue), macOS 2, windows
434+
# 2. Past those, more shards buy fit that is already there and pay
435+
# another checkout + mcpp download + cache restore.
436+
#
437+
# Full run, from the table: linux 13570s over 3 -> ~75min/shard
438+
# (observed slowest 77), macOS 6922s over 2 -> ~57, windows 8043s
439+
# over 2 -> ~67. linux is the tight one — its cap binds before the
440+
# ~70-minute target does, so it is the first place to look if a
441+
# cold full run starts brushing 90 again. The levers, in order:
442+
# raise the linux cap to 4 (costs a queued runner), then the job
443+
# timeout.
444+
shards_for() { # platform cap -> shard count
445+
local secs
446+
secs=$(XPLAT="$1" lua5.4 -e '
447+
local plat = os.getenv("XPLAT")
448+
local sel, all = {}, (os.getenv("MEMBERS") == "__ALL__")
449+
if not all then
450+
for m in (os.getenv("MEMBERS") or ""):gmatch("%S+") do sel[m] = true end
451+
end
452+
local total = 0
453+
for line in io.lines("tests/member-timings.tsv") do
454+
local p, m, s = line:match("^(%S+)\t(%S+)\t(%d+)$")
455+
if p == plat and m and (all or sel[m]) then total = total + tonumber(s) end
456+
end
457+
print(total)')
458+
local n=$(( secs / 4200 + 1 ))
459+
[ "$n" -gt "$2" ] && n="$2"
460+
echo "$1 work: ${secs}s (measured) -> $n shard(s)" >&2
461+
echo "$n"
462+
}
463+
ln=$(shards_for linux 3)
464+
mn=$(shards_for macos 2)
465+
wn=$(shards_for windows 2)
408466
{
409467
printf '{"include":['
410468
emit linux ubuntu-latest linux-x86_64 tar.gz bin/mcpp registry/bin/xlings "$ln"

mcpp.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ members = [
3636
"tests/examples/godot-cpp-module",
3737
"tests/examples/godot-cpp-module-v10",
3838
"tests/examples/godot-cpp-v10",
39+
"tests/examples/grpc-codegen",
3940
"tests/examples/grpc-module",
4041
"tests/examples/gui-stack",
4142
"tests/examples/imgui",

pkgs/c/compat.openssl.lua

Lines changed: 87 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,23 @@ package = {
5959

6060
xpm = {
6161
linux = {
62-
deps = { "xim:make@latest", "xim:perl@latest" },
62+
-- glibc + linux-headers are here for the same reason make and perl
63+
-- are: this package builds through its own Makefile with a bare
64+
-- `cc`, so every tool it uses has to be something this descriptor
65+
-- resolved, not something it hopes to find. See cc_override().
66+
--
67+
-- The specs are xim:gcc's own, character for character, and NOT
68+
-- `@latest`. openssl's objects are linked into projects built by
69+
-- that gcc, so the C library it compiles against has to be the one
70+
-- the toolchain uses; `@latest` would be free to resolve a NEWER
71+
-- glibc than the toolchain's and introduce symbols the final link
72+
-- cannot satisfy. Matching the ranges means both resolve the same
73+
-- node -- already on disk wherever gcc is, so this costs a
74+
-- resolution rather than a download.
75+
deps = {
76+
"xim:make@latest", "xim:perl@latest",
77+
"xim:glibc@>=2.39", "xim:linux-headers@5.11.1",
78+
},
6379
["3.5.1"] = {
6480
url = {
6581
GLOBAL = "https://github.com/openssl/openssl/releases/download/openssl-3.5.1/openssl-3.5.1.tar.gz",
@@ -161,13 +177,80 @@ end
161177
-- inherit the resolved toolchain's sysroot flags — it just runs `cc`. On macOS
162178
-- the toolchain in PATH is xim's llvm, which has no macOS SDK wired up, so
163179
-- every compile would fail on <stdio.h>. Pin Apple's own driver, which finds
164-
-- the SDK by itself. Left alone elsewhere: on linux the xim gcc carries its
165-
-- own payload and is the right compiler to use.
180+
-- the SDK by itself.
181+
--
182+
-- On linux the compiler used to be left to PATH, on the strength of "the xim
183+
-- gcc carries its own payload and is the right compiler to use". The binary is
184+
-- right; the assumption that it is SELF-SUFFICIENT is not. PATH reaches it
185+
-- through its xvm shim, and the shim injects `--sysroot=<subos>` resolved
186+
-- against **the subos the calling process resolved to** (xim-pkgindex
187+
-- pkgs/g/gcc.lua) -- whose own comment states the other half of the contract:
188+
--
189+
-- Consumers that bypass the shim supply their own header flags.
190+
--
191+
-- OpenSSL's Makefile is exactly such a consumer: it calls a bare `cc`. So the
192+
-- flags are this hook's business, the same way `make` and `perl` already are.
193+
--
194+
-- Leaving it ambient breaks whenever the resolved subos is not the one holding
195+
-- the toolchain. This hook runs with its cwd inside the CONSUMING PROJECT's
196+
-- xlings home (<proj>/.mcpp/.xlings/data/runtimedir/openssl-<v>), so the subos
197+
-- resolves to the PROJECT one, which holds only what that project installed --
198+
-- no usr/include, usually no usr/ at all. A `--sysroot` at an empty tree does
199+
-- not fall back to the default search, it SUPPRESSES it, and every compile
200+
-- dies a long way from the cause:
201+
--
202+
-- include/internal/common.h:14:11: fatal error: stdlib.h: No such file
203+
-- .../xim-x-gcc/16.1.0/lib/gcc/.../limits.h:210:15: fatal error: limits.h
204+
--
205+
-- (the second is gcc's own `#include_next`, which reads like a broken compiler
206+
-- and is not).
207+
--
208+
-- So resolve the C library the way make and perl are resolved -- from declared
209+
-- build deps -- and hand openssl the three things the payload gcc needs:
210+
-- headers (-isystem), crt objects (-B) and -lc (-L). `--sysroot` is re-pointed
211+
-- at the glibc payload root, which is NOT FHS-shaped and therefore contributes
212+
-- no search path of its own: it neutralises whatever the shim injected without
213+
-- opening a door to the host's /usr/include. A later --sysroot wins, so this
214+
-- needs no cooperation from the shim.
215+
--
216+
-- This is a local restatement of what mcpp's own link model does
217+
-- (src/build/flags.cppm, "payload-first, --sysroot fallback"). Duplicating a
218+
-- decision is a real cost; the alternative is worse, because openssl builds
219+
-- outside mcpp's compile rules by construction and has no other way to be told.
220+
-- If xim ever hands install() hooks a ready CC/CFLAGS, this should become that.
221+
local function libc_payloads()
222+
local glibc = pkginfo.build_dep("xim:glibc") or pkginfo.build_dep("glibc")
223+
local kern = pkginfo.build_dep("xim:linux-headers")
224+
or pkginfo.build_dep("linux-headers")
225+
local groot = glibc and glibc.path
226+
local kroot = kern and kern.path
227+
if not (groot and os.isfile(path.join(groot, "include", "stdlib.h"))) then
228+
return nil
229+
end
230+
return groot, kroot
231+
end
232+
166233
local function cc_override()
167234
if os.host() == "macosx" and os.isfile("/usr/bin/cc") then
168235
return "CC=/usr/bin/cc "
169236
end
170-
return ""
237+
if os.host() ~= "linux" then return "" end
238+
239+
local groot, kroot = libc_payloads()
240+
if not groot then
241+
log.warn("openssl: no xim:glibc payload resolved; leaving CC to PATH"
242+
.. " (fails if the active subos carries no libc headers)")
243+
return ""
244+
end
245+
local libdir = os.isdir(path.join(groot, "lib64"))
246+
and path.join(groot, "lib64") or path.join(groot, "lib")
247+
local cc = "gcc --sysroot=" .. groot
248+
.. " -isystem " .. path.join(groot, "include")
249+
if kroot and os.isdir(path.join(kroot, "include")) then
250+
cc = cc .. " -isystem " .. path.join(kroot, "include")
251+
end
252+
cc = cc .. " -B " .. libdir .. " -L " .. libdir
253+
return "CC=" .. sh_quote(cc) .. " "
171254
end
172255

173256
-- Does this perl actually RUN, with the core modules Configure opens with?

pkgs/g/grpc-plugin.lua

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,28 +31,28 @@ package = {
3131
linux = {
3232
["1.83.0"] = {
3333
url = {
34-
GLOBAL = "https://github.com/mcpplibs/grpc-m/archive/refs/tags/v1.83.0-3.tar.gz",
35-
CN = "https://gitcode.com/mcpp-res/grpc/releases/download/1.83.0/grpc-m-1.83.0-3.tar.gz",
34+
GLOBAL = "https://github.com/mcpplibs/grpc-m/archive/refs/tags/v1.83.0-4.tar.gz",
35+
CN = "https://gitcode.com/mcpp-res/grpc/releases/download/1.83.0/grpc-m-1.83.0-4.tar.gz",
3636
},
37-
sha256 = "9a0514a325e348fb013a89bb7b1acb9b41f42d5e9f3c92cee8be788e1e48d74f",
37+
sha256 = "991e9928e0fde0bd9a9fdc80229d976438f03d953b6679a6a71edab258c54baa",
3838
},
3939
},
4040
macosx = {
4141
["1.83.0"] = {
4242
url = {
43-
GLOBAL = "https://github.com/mcpplibs/grpc-m/archive/refs/tags/v1.83.0-3.tar.gz",
44-
CN = "https://gitcode.com/mcpp-res/grpc/releases/download/1.83.0/grpc-m-1.83.0-3.tar.gz",
43+
GLOBAL = "https://github.com/mcpplibs/grpc-m/archive/refs/tags/v1.83.0-4.tar.gz",
44+
CN = "https://gitcode.com/mcpp-res/grpc/releases/download/1.83.0/grpc-m-1.83.0-4.tar.gz",
4545
},
46-
sha256 = "9a0514a325e348fb013a89bb7b1acb9b41f42d5e9f3c92cee8be788e1e48d74f",
46+
sha256 = "991e9928e0fde0bd9a9fdc80229d976438f03d953b6679a6a71edab258c54baa",
4747
},
4848
},
4949
windows = {
5050
["1.83.0"] = {
5151
url = {
52-
GLOBAL = "https://github.com/mcpplibs/grpc-m/archive/refs/tags/v1.83.0-3.tar.gz",
53-
CN = "https://gitcode.com/mcpp-res/grpc/releases/download/1.83.0/grpc-m-1.83.0-3.tar.gz",
52+
GLOBAL = "https://github.com/mcpplibs/grpc-m/archive/refs/tags/v1.83.0-4.tar.gz",
53+
CN = "https://gitcode.com/mcpp-res/grpc/releases/download/1.83.0/grpc-m-1.83.0-4.tar.gz",
5454
},
55-
sha256 = "9a0514a325e348fb013a89bb7b1acb9b41f42d5e9f3c92cee8be788e1e48d74f",
55+
sha256 = "991e9928e0fde0bd9a9fdc80229d976438f03d953b6679a6a71edab258c54baa",
5656
},
5757
},
5858
},

pkgs/g/grpc.lua

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
-- 索引(#151),满打满算一天,唯一的消费者是本仓的 tests/examples/grpc-module。
77
-- 为一天的历史留一份永久重复条目不划算。
88
--
9-
-- 归档换成 v1.83.0-2:`src/` / `include/` / `third_party/` 与 v1.83.0 逐字节相同,
10-
-- 多出的只有 plugin/(grpc_cpp_plugin)与 rules/(grpcgen)。v1.83.0 的 sha256 已
11-
-- 经发布过,移动 tag 会让它校验失败(mcpp#349:发布数据不得让程序失效),故另起。
9+
-- 归档现为 v1.83.0-4。历次重打包中 `src/` / `include/` / `third_party/` 与
10+
-- v1.83.0 逐字节相同,变的只有 plugin/(grpc_cpp_plugin)、rules/(grpcgen)
11+
-- 与本包 manifest 的 codegen feature。已发布过的 sha256 不能靠移动 tag 复用
12+
-- (mcpp#349:发布数据不得让程序失效),所以每次重打包都另起一个 tag。
1213
-- Form A descriptor: the public gRPC package ships its own mcpp.toml, so this
1314
-- file carries metadata and a download address and nothing else. mcpp's default
1415
-- lookup finds <verdir>/*/mcpp.toml inside the GitHub source tarball wrap.
@@ -58,19 +59,19 @@ package = {
5859
linux = {
5960
["1.83.0"] = {
6061
url = {
61-
GLOBAL = "https://github.com/mcpplibs/grpc-m/archive/refs/tags/v1.83.0-3.tar.gz",
62-
CN = "https://gitcode.com/mcpp-res/grpc/releases/download/1.83.0/grpc-m-1.83.0-3.tar.gz",
62+
GLOBAL = "https://github.com/mcpplibs/grpc-m/archive/refs/tags/v1.83.0-4.tar.gz",
63+
CN = "https://gitcode.com/mcpp-res/grpc/releases/download/1.83.0/grpc-m-1.83.0-4.tar.gz",
6364
},
64-
sha256 = "9a0514a325e348fb013a89bb7b1acb9b41f42d5e9f3c92cee8be788e1e48d74f",
65+
sha256 = "991e9928e0fde0bd9a9fdc80229d976438f03d953b6679a6a71edab258c54baa",
6566
},
6667
},
6768
macosx = {
6869
["1.83.0"] = {
6970
url = {
70-
GLOBAL = "https://github.com/mcpplibs/grpc-m/archive/refs/tags/v1.83.0-3.tar.gz",
71-
CN = "https://gitcode.com/mcpp-res/grpc/releases/download/1.83.0/grpc-m-1.83.0-3.tar.gz",
71+
GLOBAL = "https://github.com/mcpplibs/grpc-m/archive/refs/tags/v1.83.0-4.tar.gz",
72+
CN = "https://gitcode.com/mcpp-res/grpc/releases/download/1.83.0/grpc-m-1.83.0-4.tar.gz",
7273
},
73-
sha256 = "9a0514a325e348fb013a89bb7b1acb9b41f42d5e9f3c92cee8be788e1e48d74f",
74+
sha256 = "991e9928e0fde0bd9a9fdc80229d976438f03d953b6679a6a71edab258c54baa",
7475
},
7576
},
7677
-- No windows block, and the reason is a DEPENDENCY rather than gRPC:

pkgs/g/grpcgen.lua

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,28 +31,28 @@ package = {
3131
linux = {
3232
["1.83.0"] = {
3333
url = {
34-
GLOBAL = "https://github.com/mcpplibs/grpc-m/archive/refs/tags/v1.83.0-3.tar.gz",
35-
CN = "https://gitcode.com/mcpp-res/grpc/releases/download/1.83.0/grpc-m-1.83.0-3.tar.gz",
34+
GLOBAL = "https://github.com/mcpplibs/grpc-m/archive/refs/tags/v1.83.0-4.tar.gz",
35+
CN = "https://gitcode.com/mcpp-res/grpc/releases/download/1.83.0/grpc-m-1.83.0-4.tar.gz",
3636
},
37-
sha256 = "9a0514a325e348fb013a89bb7b1acb9b41f42d5e9f3c92cee8be788e1e48d74f",
37+
sha256 = "991e9928e0fde0bd9a9fdc80229d976438f03d953b6679a6a71edab258c54baa",
3838
},
3939
},
4040
macosx = {
4141
["1.83.0"] = {
4242
url = {
43-
GLOBAL = "https://github.com/mcpplibs/grpc-m/archive/refs/tags/v1.83.0-3.tar.gz",
44-
CN = "https://gitcode.com/mcpp-res/grpc/releases/download/1.83.0/grpc-m-1.83.0-3.tar.gz",
43+
GLOBAL = "https://github.com/mcpplibs/grpc-m/archive/refs/tags/v1.83.0-4.tar.gz",
44+
CN = "https://gitcode.com/mcpp-res/grpc/releases/download/1.83.0/grpc-m-1.83.0-4.tar.gz",
4545
},
46-
sha256 = "9a0514a325e348fb013a89bb7b1acb9b41f42d5e9f3c92cee8be788e1e48d74f",
46+
sha256 = "991e9928e0fde0bd9a9fdc80229d976438f03d953b6679a6a71edab258c54baa",
4747
},
4848
},
4949
windows = {
5050
["1.83.0"] = {
5151
url = {
52-
GLOBAL = "https://github.com/mcpplibs/grpc-m/archive/refs/tags/v1.83.0-3.tar.gz",
53-
CN = "https://gitcode.com/mcpp-res/grpc/releases/download/1.83.0/grpc-m-1.83.0-3.tar.gz",
52+
GLOBAL = "https://github.com/mcpplibs/grpc-m/archive/refs/tags/v1.83.0-4.tar.gz",
53+
CN = "https://gitcode.com/mcpp-res/grpc/releases/download/1.83.0/grpc-m-1.83.0-4.tar.gz",
5454
},
55-
sha256 = "9a0514a325e348fb013a89bb7b1acb9b41f42d5e9f3c92cee8be788e1e48d74f",
55+
sha256 = "991e9928e0fde0bd9a9fdc80229d976438f03d953b6679a6a71edab258c54baa",
5656
},
5757
},
5858
},
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// One line, and it finds every .proto under proto/ by itself.
2+
//
3+
// The rule comes from the `grpcgen` package, which this project does NOT
4+
// declare on linux/macOS: `grpc = { features = ["codegen"] }` re-exports it,
5+
// along with protoc and grpc_cpp_plugin. Which tools gRPC codegen needs is the
6+
// gRPC package's knowledge.
7+
import std;
8+
import mcpp;
9+
import grpcgen;
10+
11+
int main() {
12+
// No gRPC on windows — compat.openssl has no windows xpm entry, so the
13+
// grpc package is linux/macOS only and there is nothing to generate. The
14+
// guard is on the CALL, not the import: `import grpcgen;` is a
15+
// compile-time dependency and cannot be conditional (docs/01 §4.2 forbids
16+
// #if-guarded imports), so the module is declared on windows too — it is a
17+
// pure C++23 rule package with no platform-limited dependencies of its own.
18+
//
19+
// Same shape as tests/examples/protobuf-protoc: return 0 so the member
20+
// still builds, and let the test compile to a visible skip.
21+
if (std::string_view(mcpp::target_os()) == "windows") return 0;
22+
return grpcgen::generate_all() ? 0 : 1;
23+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# grpc-codegen test project: the ONE-DEPENDENCY form of gRPC codegen.
2+
#
3+
# Its sibling tests/examples/grpc-module covers the module surface with no
4+
# codegen at all. This member covers what that one's header says is impossible:
5+
#
6+
# "NO protoc output anywhere: gRPC's codegen needs host tools mcpp cannot
7+
# hand a consumer"
8+
#
9+
# That stopped being true in mcpp 2026.8.6.2. `features = ["codegen"]` makes
10+
# the grpc package re-export protoc, grpc_cpp_plugin and the grpcgen rule to
11+
# whoever depends on it, so this manifest names ONE package and build.mcpp is
12+
# one line — and the .proto below is compiled from a stub that did not exist
13+
# when the build started.
14+
#
15+
# What this member protects, and what no other member can:
16+
# * `reexport = true` really reaches a consumer through the published index
17+
# (every other test of it is a path dependency in mcpp's own e2e);
18+
# * `rerun_if_changed_glob` really drives `generate_all()` — the file list is
19+
# never written down anywhere;
20+
# * the host tools are built for the BUILD machine and produce stubs that
21+
# link against the runtime this project links, which is the property the
22+
# whole design exists to make inexpressible-to-get-wrong.
23+
#
24+
# linux + macOS only, for the same reason grpc-module is: compat.openssl has no
25+
# windows xpm entry, so on windows this member carries no dependency and the
26+
# test compiles to a no-op main().
27+
[package]
28+
name = "grpc-codegen-tests"
29+
version = "0.1.0"
30+
31+
# `cfg(unix)`, not one block per OS: the condition is "everywhere gRPC
32+
# resolves", and what excludes windows is compat.openssl having no xpm entry
33+
# there — a single fact, so a single predicate. mcpp evaluates `unix` as
34+
# family == "unix" (src/build/prepare.cppm, alongside any()/all()/not()).
35+
[target.'cfg(unix)'.dependencies.grpc]
36+
grpc = { version = "1.83.0", features = ["codegen"] }
37+
38+
[target.'cfg(unix)'.build]
39+
cxxflags = ["-DHAVE_GRPC=1"]
40+
41+
# windows carries the RULE but not gRPC itself, so build.mcpp compiles (its
42+
# `import grpcgen;` cannot be conditional) and then returns early. grpcgen is a
43+
# pure C++23 rule package — no openssl, no platform-limited dependency — which
44+
# is why it is available here while grpc is not.
45+
[target.'cfg(windows)'.dependencies.mcpplibs]
46+
grpcgen = { version = "1.83.0", host-module = true }

0 commit comments

Comments
 (0)