chore: pin mcpp 0.0.109, hoist the compat index redirect, fix compat.openssl - #125
Merged
Sunrisepeak merged 4 commits intoJul 27, 2026
Merged
Conversation
…openssl ## mcpp 0.0.109 (MCPP_VERSION + index.toml floor) 0.0.109 makes a bare dependency take BOTH halves of its wire address from the descriptor the identity gate accepted (mcpp#286). That is the client-side other half of the SPEC-001 short-name migration (#120): mcpp used to take the name from the descriptor and the namespace from the request, so a bare `gtest = "1.15.2"` addressed `mcpplibs:gtest`, a key no index has. It survived only on a hardcoded `compat.<short>` retry that the short names removed — leaving every bare request against this index broken on 0.0.108. min_mcpp moves with the pin so consumers get a client that can address the index they are handed. ## [indices]: hoisted to the workspace root The 13 members that consume `compat` no longer repeat `[indices] compat = { path = "../../.." }`; the root declares it once and they inherit it, with the relative path resolved against the workspace root (mcpp#224, 0.0.97). Exactly one entry, and `compat` specifically, because the table is keyed by NAMESPACE: * declared under a name no dependency asks for, the index is never registered and resolution silently falls through to the published remote index — the checkout under test is then not what is being tested; * declared under several namespaces it registers N separate project repos, and every lookup afterwards fails with an N-way ambiguity between what is physically one descriptor (mcpp#238 / xlings#374). Members needing another namespace keep their own declaration, which REPLACES the inherited table rather than merging — which is what holds each member to one project index repo. mcpp.toml and index.toml also join the workflow's paths filter; a change to either can break every member and neither gated a run before. ## compat.openssl `name`: `compat.openssl` -> `openssl`. It was the index's last legacy fully-qualified spelling (SPEC-001 §3.2). `./config` now passes `--libdir=lib`. Unset, OpenSSL derives the install libdir as `lib$target{multilib}` and `linux-x86_64` declares `multilib => "64"`, so the archives landed in $prefix/lib64 while `-Llib` and the post-build check looked at $prefix/lib. linux-aarch64 and both darwin64 targets declare no multilib and resolve to plain `lib` — which is how this validated on an arm64 Mac while being broken for every x86_64 Linux consumer. Reproduced against the published descriptor before fixing: the install tree came out as bin/ include/ lib64/ and install() failed its own archive check. Also: linux links `-l:libssl.a -l:libcrypto.a` (naming the archive rather than letting the driver resolve a name a shared object would win — one stray -L ahead of ours and the consumer picks up the host libssl.so.3) plus `-ldl -lpthread` for musl and pre-2.34 glibc; the build log moved into the install prefix, since the old spot was deleted mid-build by the very os.tryrm that preceded install; `RANLIB=/usr/bin/ranlib` is confined to macOS, the platform whose llvm-ranlib rejects `-c`; a redundant `os.cd` that would have broken the relative-srcroot fallback is gone; and install() probes for `perl` up front, since OpenSSL's ./config IS a Perl script and no xim:perl exists to declare. ## Two members for it `tests/examples/openssl` — direct dependency, inherits the root `compat` redirect, so the descriptor in this checkout is what gets built. Asserts both archives really link (SSL_CTX_new + EVP sha256) and the binary carries no dynamic ssl/crypto dependency. `tests/examples/asio-ssl` — the asio `ssl` feature end-to-end, a real TLS handshake over loopback. It declares no member-level [indices] on purpose: inheriting `compat` means asio resolves from the published index while its feature dep, compat.openssl, comes from this checkout — which is how an unmerged compat descriptor can be exercised through a published consumer. The test moved out of asio-module, where it had been guarded by MCPP_FEATURE_SSL. A feature's `defines` apply to the package's own TUs, not to consumers, so that file compiled to nothing and passed while asserting nothing — the reason the libdir bug reached main green. It now keys off HAVE_ASIO_SSL, which the member sets in its own cfg-gated cxxflags. ## Docs docs/package-types.md still taught `name = "compat.<lib>"`. README, the repository/schema doc (new "索引重定向" section, corrected `features` row) and the openssl design spec are updated to match what the code does.
…ailure
The macOS workspace job failed on both new members ~43s after the tarball
landed — far too early for a compile, and with nothing to go on: install()
writes everything to an on-disk log (xim's interface mode swallows subprocess
stdout) and xlings surfaces the failure as a bare
`E_INTERNAL: [openssl] failed:`.
Two changes, one for the likely cause and one so the next failure says what it
was.
macosx now declares `deps = { "xim:make@latest" }`. The previous comment
claimed it was unnecessary because "macOS ships GNU Make at /usr/bin/make" —
it ships GNU Make **3.81**, the last GPLv2 release, frozen in 2006, and
OpenSSL 3.x's generated Makefile does not build with it. That matches the
timing exactly: ~30s of Perl Configure, then make failing on sight.
compat.openblas already declares this dep on macosx.
Each build step now runs through a helper that, on failure, names the step and
prints the last 40 lines of the log. The log also opens with `make --version`,
because 3.81-vs-4.x is precisely the distinction that is invisible after the
fact. The tail is passed as one pre-formatted argument rather than a format
string — build output contains `%` often enough that formatting it is its own
failure mode.
Verified on linux (cold): log opens with "GNU Make 4.3", openssl and asio-ssl
members both pass.
…d logs in CI
`xim:make` has no macOS build — xim-pkgindex's pkgs/m/make.lua declares only an
`xpm.linux` block — so yesterday's macosx dep failed resolution outright with
`E_INVALID_INPUT: package 'xim:make@latest' not found`, before install() ran.
Reverted, with the finding written down. compat.openblas declares the same dep
on macosx and is broken identically; nobody has noticed because that package is
Windows-only in the test suite, so its macOS path is never taken.
That leaves the original macOS failure — 43s after download, no message —
still undiagnosed, so this stops guessing at it:
* The workspace job gains an `if: failure()` step that finds every
`mcpp_*_build.log` under the members and the registry and prints its tail.
install()-driven packages build through their own Make/Configure system,
xim's interface mode swallows that output, and xlings reports only
`E_INTERNAL: [<pkg>] failed:` — so a platform-specific break otherwise
costs one full CI round-trip per hypothesis.
* The log now opens with make/cc/perl versions, not just make's.
And one likely cause addressed while here: OpenSSL is configured and built
outside mcpp's compile rules, so it inherits none of the resolved toolchain's
flags — it just runs `cc`. On macOS the `cc` in PATH is xim's llvm, which has
no macOS SDK wired up, so every compile would fail on <stdio.h>. macOS now
builds with `CC=/usr/bin/cc`, Apple's driver, which finds the SDK itself
(same spirit as the RANLIB pin, which is already macOS-only). resolve_make()
also prefers a Homebrew gmake when one exists, since /usr/bin/make is GNU Make
3.81.
If the SDK guess is wrong, the log tail now says what is.
Verified on linux (cold): log opens with GNU Make 4.3 / gcc 16.1.0, openssl
member passes.
…nv var
The macOS build now gets all the way through configure and compile — the CC
pin was the missing piece there — and dies in `make install_sw`, one line after
copying libcrypto.a into place:
install libcrypto.a -> .../3.5.1/lib/libcrypto.a
llvm-ranlib: error: Invalid option: '-c'
make: *** [install_dev] Error 1
which is precisely what the RANLIB override exists to prevent. OpenSSL's
`darwin-common` sets `ranlib => "ranlib -c"` (Configurations/10-main.conf:1844)
and PATH resolves `ranlib` to the toolchain's llvm-ranlib, which rejects `-c`.
The override was not taking effect, and that is a regression I introduced when
confining it to macOS: I moved it from `make RANLIB=… install_sw` to
`RANLIB=… make install_sw`. The first is a command-line assignment and beats
the Makefile's own definition; the second is only an environment variable,
which a Makefile assignment overrides absent `make -e` — so it silently did
nothing and the build failed exactly as if it were not there. Restored to the
command-line form, with a comment saying why the position matters.
Also confirmed from the same log that `--libdir=lib` does its job on macOS:
the archive installs to `3.5.1/lib/`, not `lib64/`.
Verified on linux (cold): openssl member passes.
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.
基于 mcpp 0.0.109 的一次规范/机制对齐:CI pin 与 index floor 上移、
compat索引重定向提到 workspace 根、compat.openssl的身份与实现修正,以及为它补上两个真正跑得起来的成员。1. mcpp 0.0.109
0.0.109 让裸名依赖的 wire 地址从被身份闸门接受的那份描述符里同时取两半(mcpp#286)。
这是 SPEC-001 短名迁移(#120)的客户端另一半:此前 mcpp 从描述符取 name、从请求取 namespace,于是裸写的
gtest = "1.15.2"寻址成mcpplibs:gtest—— 任何索引都没有这个 key。它一直能用只是因为迁移前package.name字面值是
compat.gtest,被硬编码的compat.<short>重试接住了;短名把这个巧合拿掉,于是 0.0.108 上对本索引的每一个裸名请求都是坏的。
index.toml的min_mcpp/latest_mcpp随 pin 一起走到 0.0.109,让拿到本索引的消费者手里的客户端能寻址它。
2.
[indices]提到 workspace 根13 个消费
compat的成员不再各写一遍[indices] compat = { path = "../../.." }—— 根级声明一次由成员继承,相对路径按 workspace 根解析(mcpp#224,0.0.97 修复)。
只放一条、且只能是
compat,原因是这张表按命名空间取键:此时被测的根本不是这个 checkout(实测:根级用
mcpp-index = { path = "." }时,xlings 只看到1 index repo configured [mcpplibs -> github.com/mcpplibs/mcpp-index.git]);(mcpp#238 / xlings#374;
0.4.69 后由静默 exit 1 变为响亮报错)。
需要其他命名空间的成员保留自己的声明,该声明替换继承来的根级表而非合并 —— 这正是每个成员只保留一个项目
索引 repo 的机制。
mcpp.toml/index.toml也加进了 workflow 的paths过滤:两者的改动都可能影响全部成员,此前却都不会触发 CI。
3.
compat.opensslname:compat.openssl→openssl。这是索引里最后一个 legacy 完全限定拼写(SPEC-001 §3.2)。./config补--libdir=lib—— 这是一个真 bug。不传时 OpenSSL 把安装 libdir 推导为lib$target{multilib}(Configurations/unix-Makefile.tmpl),而10-main.conf给linux-x86_64的是multilib => "64":产物落到$prefix/lib64,而-Llib和 install() 的自检看的是$prefix/lib。linux-aarch64与两个darwin64目标都没有 multilib、解析成lib—— 这就是它能在 arm64 Mac 上验证通过、却对每一个 x86_64 Linux 消费者都是坏的原因。修之前先对着已发布的描述符复现过:安装树确实是
bin/ include/ lib64/,install() 卡在自己的归档检查上。同时:
-l:libssl.a -l:libcrypto.a(直接点名归档,而不是让驱动去解析一个共享库会赢的名字 ——只要有一个
-L排在我们前面,消费者就会拿到 host 的libssl.so.3),并补-ldl -lpthread(musl 与glibc < 2.34);
os.tryrm删掉的位置,失败时正好没有;RANLIB=/usr/bin/ranlib收敛到 macOS(llvm-ranlib 不认-c的只有它),Linux 精简容器不再因为没有/usr/bin/ranlib而白白失败;os.cd,它会让相对 srcroot 的回退分支必然失败;perl—— OpenSSL 的./config本身就是 Perl 脚本,而没有xim:perl可声明为build dep,失败时给一句能读懂的话而不是让
./config死在 shell 报错里。4. 两个成员
tests/examples/openssl—— 直接依赖,继承根级compat,所以被构建和链接的就是本 checkout 的描述符。断言两个归档真的都链上了(
SSL_CTX_new+ EVP sha256),且产物没有动态 ssl/crypto 依赖。tests/examples/asio-ssl—— asiosslfeature 的端到端,loopback 上跑真实 TLS 握手。它有意不写成员级[indices]:继承compat意味着 asio 走已发布索引、而它的 feature 依赖compat.openssl来自本 checkout ——这正是未合并的 compat 描述符可以通过一个已发布的消费者被验证的路径。
这个测试是从
asio-module挪过来的,原先整体被MCPP_FEATURE_SSL包住。feature 的defines只作用于包自身的 TU、不传播给消费者,所以那个文件编译成了空的 —— 它在什么都没断言的情况下"通过",这也正是上面那个
libdir bug 能绿着进 main 的原因。现在它 key 在
HAVE_ASIO_SSL上,由成员自己的 cfg 门控 cxxflags 声明(与 openblas 成员同款写法)。
asio-module相应从 6 个测试变回 5 个(第 6 个本来就是 no-op)。5. 文档
docs/package-types.md还在教name = "compat.<lib>"。README、仓库/schema 文档(新增「索引重定向」一节、修正
features行对defines作用域的描述)与 openssl 设计文档(§0 修订说明)都对齐到代码的实际行为。本地验证(mcpp 0.0.109,gcc@16.1.0,linux-x86_64)
mcpp xpkg parse全部 49 个描述符:通过mcpp test -p:opensslasio-ssleigencjsonspdlogarchivefmtlib.fmtnlohmann.jsonmarzer.tomlplusplustinyhttpscoreimguiimgui-windowopenblasspdlog-compiledasio-module—— 全绿compat-x-openssl/3.5.1/lib/{libssl.a,libcrypto.a}存在,ldd无动态 ssl/crypto 依赖CI:三平台全量 workspace 全绿(
Workspace all 24 member(s) passed× linux / macOS / windows,ssl ... ok+tls ... ok均实跑非跳过),lint 与 mirror-cn-reachable 通过。macOS 上多花的三轮,以及各自的真因
macOS 的 OpenSSL 源码构建连挂三轮,过程本身值得记一笔 —— 三次症状完全不同,前两次的判断都是错的:
cc是 xim 的 llvm,没有配 macOS SDKE_INVALID_INPUT: package 'xim:make@latest' not foundllvm-ranlib: error: Invalid option: '-c'关键的结构性问题是第 1 轮根本无法诊断:这类 install() 驱动的包在自己的 Make/Configure 里构建,输出被
xim 的 interface mode 吞掉,xlings 只报
E_INTERNAL: [openssl] failed:。所以第 2 轮起加了if: failure()步骤把所有mcpp_*_build.log的尾部打出来,并在日志开头记 make / cc / perl 版本 ——第 3 轮的真因就是它直接给出来的。这个步骤对 openblas 等同类包同样生效。
第 3 轮那个是我自己引入的回归:
RANLIB=… make install_sw是环境变量,打不过 Makefile 里的赋值(除非
make -e);make RANLIB=… install_sw才是命令行赋值。#124 原本的写法是对的,我在把 RANLIB收敛到 macOS 时挪错了位置。根因在 OpenSSL 源码里坐实:
darwin-common设ranlib => "ranlib -c"(
Configurations/10-main.conf:1844),而 PATH 上的ranlib解析到不认-c的 llvm-ranlib。顺带发现:
compat.openblas的 macosx 也声明了xim:make@latest,同样是坏的 —— 只是它在测试面里是Windows-only,macOS 路径从没被走到,所以一直没暴露。已写进 openssl 描述符的注释,未在本 PR 顺手改
(不在范围内,且要验证它需要给 openblas 自己的 macOS 覆盖)。
已知边界
compat.openssl仍无 windows(需要预编译 MSVC 归档),两个成员在 windows 上都退化为 no-op main()。asio-ssl验证的是本地 openssl + 已发布 asio;本地 asio 描述符由asio-module覆盖。一个成员没法同时从本 checkout 解析两个命名空间,这是上面那条歧义约束的直接后果。
该路径由 mcpp 上游的 e2e 165 覆盖。