Skip to content

Commit 45e7611

Browse files
authored
feat(compat): the farm carries only what its runtime can reach, and a moved pin is carried down the chain (#383)
Three farms move to 2026.09.11 and the consumers that pin them move with them: compat.glfw 3.4.0.1, compat.opencl 2026.09.11, compat.vulkan 1.4.357.2, compat.sycl-runtime 2026.09.11. An installed copy records the pin it resolved with, so every link in sycl-runtime -> opencl -> opencl-runtime needs its own key or the farm at the end never arrives. `libnvidia-pkcs11*` leaves both farms, and the OpenSSL declaration it was the only reason for leaves with it. It is a PKCS#11 token module, loaded by an application's own configuration and by nothing in a GPU driver's dispatch; it was in the farm because its name matched `libnvidia*.so.*`. Measured with `LD_DEBUG=libs` AND A CONTROL: `pkcs11` appears zero times on both the Vulkan and the SYCL/OpenCL run, while `libnvidia-glvkspirv` appears six times and the OpenCL adapter twenty-three -- so the zero is a reading rather than a silence. An earlier criterion -- remove the member, see whether the example still runs -- measured nothing: removing glvkspirv left the example working too, because the binary under test and the farm being edited were different objects. Three defects that only appear when the code is executed: * `never_farm_patterns` was iterated and then ignored: the loop bound `pat` and passed a literal `libnvidia-gtk*`, so the table read like a list and behaved like one entry. Adding pkcs11 to it did nothing at all. * `readelf -d` is not transitive, so one round does not close the farm. The pass this replaced asked `ldd`, whose answer is the whole closure. Measured on glx-runtime's first real install: 52 members became 77 and were still nine sonames short, `libLLVM.so.20.1` and `libstdc++.so.6` among them. Now iterated to a fixed point, bounded so a cycle cannot spin. * a missing `readelf` returned an empty answer, which reads exactly like a closed farm. It warns now, and glx-runtime's tool lookup reaches the xim store before PATH. Measured on this host, with the driver: glx-runtime 86 members, 0 gaps, and NO direct host reach -- four entries route through xim:nvidia-gl-host-link, twenty-four through other xim payloads, the rest through the subos view. The SYCL example records members 49, walked 49, no findings; the Vulkan example 56, 56, no findings; both compute the right answer on an RTX 4080.
1 parent 12c61d0 commit 45e7611

8 files changed

Lines changed: 360 additions & 39 deletions

CHANGELOG.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,48 @@
77

88
## [Unreleased]
99

10+
### Changed
11+
12+
- **farm 只携带这个 runtime 够得到的东西,并且把「一个钉挪动」这件事在整条链上补齐。**
13+
三个 farm(`compat.glx-runtime` / `compat.opencl-runtime` / `compat.vulkan-runtime`)
14+
一起到 2026.09.11,消费者链 `compat.glfw` 3.4.0.1、`compat.opencl` 2026.09.11、
15+
`compat.vulkan` 1.4.357.2、`compat.sycl-runtime` 2026.09.11 同步。
16+
17+
**剔掉 `libnvidia-pkcs11*`,并撤回它带来的 OpenSSL 依赖。** 它是加密令牌模块,
18+
由应用自己的 PKCS#11 配置加载,不由任何 GPU 驱动派发;进 farm 只因为名字匹配
19+
`libnvidia*.so.*`。判据是 `LD_DEBUG=libs`(**带对照**):两条链上 `pkcs11` 出现
20+
**0 次**,而驱动确实够得到的 `libnvidia-glvkspirv` 出现 6 次、OpenCL adapter 出现
21+
23 次 —— 对照证明这个仪器分得开,所以 0 是读数不是沉默。它们也是 farm 里唯一需要
22+
`libcrypto` 的成员,随之消失的还有那条无解的 `libcrypto.so.1.1`(OpenSSL 1.1 上游
23+
已 EOL)。
24+
25+
⚠️⚠️ **一个更早的判据什么都没测到**:把成员删掉看示例还跑不跑 —— 删掉
26+
`libnvidia-glvkspirv` 示例照样跑。原因是被测二进制和被改的 farm 不是同一个
27+
(产物目录有两个,钉着不同版本)。**判据又一次指错了对象。**
28+
29+
### Fixed
30+
31+
- **三处只有真跑一遍才会现形的缺陷。**
32+
33+
⚠️⚠️ **排除循环遍历了模式表却把模式写死。** `compat.vulkan-runtime`
34+
`never_farm_patterns` 绑定了 `pat` 然后传了字面量 `libnvidia-gtk*`,于是这张表
35+
**看起来是列表、行为上只有一条**。往里加 `libnvidia-pkcs11` 毫无效果 —— farm 依旧
36+
81 个成员、两个 PKCS#11 都在,这是「排除」写完之后才发现的。
37+
38+
⚠️⚠️ **`readelf -d` 不是传递的,一趟补不完。** 上一版用 `ldd`(答案是整个传递闭包)
39+
所以一趟够;换成 `readelf` 是对的(它答**文件**说什么,而不是**这台机器**能不能解析),
40+
但这一轮补进来的库会带来自己的依赖。实测:`compat.glx-runtime` 第一次真安装,
41+
farm 从 52 涨到 77 **仍缺 9 条**,包括 `libLLVM.so.20.1``libstdc++.so.6`
42+
现在迭代到不动点(带上界防环),再测 **86 个成员、0 缺口、0 封条**
43+
44+
⚠️ 找不到 `readelf` 时那一趟静默返回空,读数与「已完全闭合」相同;现在明确告警,
45+
`compat.glx-runtime` 的工具查找也先查 store 再查 PATH。
46+
47+
实测(本机,真驱动):`compat.glx-runtime` 86 成员 / 0 缺口,**零直接宿主触达** ——
48+
4 条走 `xim:nvidia-gl-host-link`、24 条走其它 xim 载荷、其余走 subos 库视图。
49+
SYCL 示例 `members 49 / walked 49 / findings 无`,Vulkan 示例
50+
`members 56 / walked 56 / findings 无`,两者都在 RTX 4080 上跑出正确结果。
51+
1052
### Fixed
1153

1254
- **两处只有把 glx 那一版真正跑一遍才会现形的缺陷。** 上一轮我量了 opencl 和

pkgs/c/compat.glfw.lua

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,19 @@ package = {
99

1010
xpm = {
1111
linux = {
12+
-- A new version because this package's pin on its runtime farm
13+
-- moved. An installed copy RECORDS the pin it resolved with, so a
14+
-- moved pin does not reach a machine that already holds the old
15+
-- version -- and where a consumer also names the farm directly, the
16+
-- two disagree and the build stops. Measured on a CI runner with a
17+
-- warm ~/.mcpp; see the note on compat.vulkan 1.4.357.1.
18+
["3.4.0.1"] = {
19+
url = {
20+
GLOBAL = "https://github.com/glfw/glfw/archive/refs/tags/3.4.tar.gz",
21+
CN = "https://gitcode.com/mcpp-res/glfw/releases/download/3.4/glfw-3.4.tar.gz",
22+
},
23+
sha256 = "c038d34200234d071fae9345bc455e4a8f2f544ab60150765d7704e08f3dac01",
24+
},
1225
["3.4"] = {
1326
url = {
1427
GLOBAL = "https://github.com/glfw/glfw/archive/refs/tags/3.4.tar.gz",
@@ -18,6 +31,19 @@ package = {
1831
},
1932
},
2033
macosx = {
34+
-- A new version because this package's pin on its runtime farm
35+
-- moved. An installed copy RECORDS the pin it resolved with, so a
36+
-- moved pin does not reach a machine that already holds the old
37+
-- version -- and where a consumer also names the farm directly, the
38+
-- two disagree and the build stops. Measured on a CI runner with a
39+
-- warm ~/.mcpp; see the note on compat.vulkan 1.4.357.1.
40+
["3.4.0.1"] = {
41+
url = {
42+
GLOBAL = "https://github.com/glfw/glfw/archive/refs/tags/3.4.tar.gz",
43+
CN = "https://gitcode.com/mcpp-res/glfw/releases/download/3.4/glfw-3.4.tar.gz",
44+
},
45+
sha256 = "c038d34200234d071fae9345bc455e4a8f2f544ab60150765d7704e08f3dac01",
46+
},
2147
["3.4"] = {
2248
url = {
2349
GLOBAL = "https://github.com/glfw/glfw/archive/refs/tags/3.4.tar.gz",
@@ -27,6 +53,19 @@ package = {
2753
},
2854
},
2955
windows = {
56+
-- A new version because this package's pin on its runtime farm
57+
-- moved. An installed copy RECORDS the pin it resolved with, so a
58+
-- moved pin does not reach a machine that already holds the old
59+
-- version -- and where a consumer also names the farm directly, the
60+
-- two disagree and the build stops. Measured on a CI runner with a
61+
-- warm ~/.mcpp; see the note on compat.vulkan 1.4.357.1.
62+
["3.4.0.1"] = {
63+
url = {
64+
GLOBAL = "https://github.com/glfw/glfw/archive/refs/tags/3.4.tar.gz",
65+
CN = "https://gitcode.com/mcpp-res/glfw/releases/download/3.4/glfw-3.4.tar.gz",
66+
},
67+
sha256 = "c038d34200234d071fae9345bc455e4a8f2f544ab60150765d7704e08f3dac01",
68+
},
3069
["3.4"] = {
3170
url = {
3271
GLOBAL = "https://github.com/glfw/glfw/archive/refs/tags/3.4.tar.gz",
@@ -80,7 +119,7 @@ package = {
80119
"src/posix_module.c",
81120
},
82121
deps = {
83-
["compat.glx-runtime"] = "2026.09.10",
122+
["compat.glx-runtime"] = "2026.09.11",
84123
["compat.x11"] = "1.8.13",
85124
["compat.xcursor"] = "1.2.3",
86125
["compat.xext"] = "1.3.7",

pkgs/c/compat.glx-runtime.lua

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,18 @@ package = {
5656
-- well-formedness anchor and nothing more, and reusing it means no
5757
-- new mirror asset has to exist for a key that changes only
5858
-- install() behaviour.
59+
-- 2026.09.11: install() changed again after 2026.09.10 was
60+
-- published -- an absolute `DT_NEEDED` is no longer treated as a
61+
-- soname, and a missing `readelf` now says so instead of reading
62+
-- as "no gaps". Behaviour baked into an installed payload needs a
63+
-- key of its own, including when the previous key is hours old.
64+
["2026.09.11"] = {
65+
url = {
66+
GLOBAL = "https://raw.githubusercontent.com/KhronosGroup/OpenGL-Registry/a30033d3e812c9bf10094f1010374a6b15e192eb/README.adoc",
67+
CN = "https://gitcode.com/mcpp-res/glx-runtime/releases/download/2026.08.08/glx-runtime-2026.08.08.adoc",
68+
},
69+
sha256 = "ea68efce197e68413ebb62c51ab4bccfb2309a2fca776d31b49d972f59f3640e",
70+
},
5971
["2026.09.10"] = {
6072
url = {
6173
GLOBAL = "https://raw.githubusercontent.com/KhronosGroup/OpenGL-Registry/a30033d3e812c9bf10094f1010374a6b15e192eb/README.adoc",
@@ -369,7 +381,28 @@ local UNSERVED = {}
369381
local function close_farm(outdir)
370382
local filled, unserved, undeclared = {}, {}, {}
371383
local unserved_dir = path.join(path.directory(outdir), "unserved")
384+
-- ITERATED TO A FIXED POINT, because `readelf -d` reports DIRECT
385+
-- dependencies only.
386+
--
387+
-- The pass this replaced asked `ldd`, whose answer is the whole transitive
388+
-- closure, so one round was enough and the comment said so. `readelf` is
389+
-- the right instrument -- it answers what the FILE says instead of what
390+
-- this machine can resolve -- but it is not transitive, and a library
391+
-- filled in one round brings needs of its own. Measured on the first real
392+
-- install of this package: the farm went from 52 members to 77 and was
393+
-- still nine sonames short, `libLLVM.so.20.1` and `libstdc++.so.6` among
394+
-- them, every one of them reachable from something the same round had just
395+
-- added.
396+
--
397+
-- The bound is not a guess about depth; it is there so a cycle cannot spin.
398+
-- A round that adds nothing ends the loop, which is the normal exit.
399+
local seen = {}
400+
for _ = 1, 16 do
401+
local added = 0
372402
for _, soname in ipairs(unresolved_against_farm(outdir)) do
403+
if seen[soname] then goto next end
404+
seen[soname] = true
405+
added = added + 1
373406
local candidates = find_in_store(soname)
374407
local hit = candidates[#candidates]
375408
if hit then
@@ -385,6 +418,9 @@ local function close_farm(outdir)
385418
unserved[#unserved + 1] = soname
386419
if not UNSERVED[soname] then undeclared[#undeclared + 1] = soname end
387420
end
421+
::next::
422+
end
423+
if added == 0 then break end
388424
end
389425
return filled, unserved, undeclared
390426
end

pkgs/c/compat.opencl-runtime.lua

Lines changed: 81 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,19 @@ package = {
4242
-- PLATFORM LEVEL, NOT PER VERSION, matching compat.vulkan-runtime:
4343
-- a `deps` inside a version entry is not read.
4444
--
45-
-- `xim:openssl` is here because a farmed member needs
46-
-- `libcrypto.so.3` and this ecosystem publishes it. The rule this
47-
-- package follows is that anything xlings or this index can supply
48-
-- comes from there, and the host is reached for one class only --
49-
-- proprietary vendor userspace, which cannot be a package at all.
50-
-- A floor, not a pin: the soname is ABI-stable at 3.x.
45+
-- The rule this package follows is that anything xlings or this
46+
-- index can supply comes from there, and the host is reached
47+
-- through a named sentinel rather than by this package itself.
48+
-- `xim:nvidia-video-host-link` owns "where is the host's
49+
-- `libnvcuvid.so.1`", which two farmed members need.
50+
--
51+
-- OpenSSL was declared here for one release and is gone with the
52+
-- member that asked for it: the PKCS#11 provider the name pattern
53+
-- swept in and no OpenCL entry point reaches.
5154
deps = {
52-
runtime = { "xim:openssl@>=3", "xim:nvidia-video-host-link" },
55+
runtime = { "xim:nvidia-video-host-link" },
5356
},
54-
["latest"] = { ref = "2026.09.10" },
57+
["latest"] = { ref = "2026.09.11" },
5558
-- 2026.09.07: a soname carried by more than one installed payload
5659
-- is decided by symbol coverage rather than by which store path
5760
-- sorts last, and the ELF machine guard refuses a foreign payload.
@@ -64,6 +67,18 @@ package = {
6467
-- install() output is baked into the installed payload: without one
6568
-- a host that already holds the previous version keeps the open
6669
-- farm. The anchor is unchanged; only install() behaviour is.
70+
-- 2026.09.11: the farm carries only what this runtime can
71+
-- reach. `libnvidia-pkcs11*` is a PKCS#11 token module that matched
72+
-- the vendor name pattern and nothing else -- measured with
73+
-- LD_DEBUG on both examples, it is looked for zero times while a
74+
-- member the driver does reach appears six -- so it leaves, and the
75+
-- OpenSSL declaration it was the only reason for leaves with it.
76+
-- A new key because install() output is baked into the installed
77+
-- payload.
78+
["2026.09.11"] = {
79+
url = "https://raw.githubusercontent.com/KhronosGroup/OpenCL-ICD-Loader/v2026.05.29/README.md",
80+
sha256 = "b332515b9a0bc266ad94fe6e951f0ef7a988ccb9e933068faf0fd8ba3cfde805",
81+
},
6782
["2026.09.10"] = {
6883
url = "https://raw.githubusercontent.com/KhronosGroup/OpenCL-ICD-Loader/v2026.05.29/README.md",
6984
sha256 = "b332515b9a0bc266ad94fe6e951f0ef7a988ccb9e933068faf0fd8ba3cfde805",
@@ -199,6 +214,32 @@ local never_farm = {
199214
["libgcc_s.so.1"] = true, ["libOpenCL.so.1"] = true,
200215
}
201216

217+
-- WHAT THE PATTERN SWEEPS IN THAT THIS RUNTIME CANNOT REACH.
218+
--
219+
-- `libnvidia-gtk*` is the driver's settings GUI. `libnvidia-pkcs11*` is its
220+
-- PKCS#11 provider: a cryptographic token module, loaded by an application's
221+
-- own PKCS#11 configuration and by nothing in a GPU driver's dispatch. Both
222+
-- match `libnvidia*.so.*` by name alone.
223+
--
224+
-- MEASURED, WITH A CONTROL, before removing them. `LD_DEBUG=libs` on a run of
225+
-- each example says which files the process actually looked for:
226+
--
227+
-- pkcs11 0 occurrences (Vulkan and SYCL/OpenCL alike)
228+
-- libnvidia-glvkspirv 6 occurrences (Vulkan)
229+
-- libur_adapter_opencl / libOpenCL 23 (SYCL/OpenCL)
230+
--
231+
-- The last two are the control: this instrument does report a member the
232+
-- driver reaches, so a zero for `pkcs11` is a reading rather than a silence.
233+
-- An earlier attempt -- remove the member and see whether the example still
234+
-- runs -- could NOT tell the two apart: removing `libnvidia-glvkspirv` left the
235+
-- example working too, because the binary under test had been built against a
236+
-- different farm than the one being edited.
237+
--
238+
-- They are also the only members that need `libcrypto` at all, so removing them
239+
-- removes this package's reason to declare OpenSSL, and with it the
240+
-- `libcrypto.so.1.1` that no ecosystem package can serve: OpenSSL 1.1 is
241+
-- end-of-life upstream. A member that cannot be reached is not a capability
242+
-- being dropped -- it is a file the name pattern collected.
202243
-- Proprietary vendor userspace: linked from the host by design. `libnvidia-gtk*`
203244
-- is the driver's settings GUI and is not part of any driver.
204245
local host_opencl_patterns = { "libnvidia*.so.*" }
@@ -232,7 +273,6 @@ end
232273
-- /usr/lib. What a farmed member needs is answered in this order:
233274
--
234275
-- * an installed payload publishes it -> link the payload's copy.
235-
-- `xim:openssl` covers `libcrypto.so.3` and
236276
-- `xim:nvidia-video-host-link` covers `libnvcuvid.so.1`, which is
237277
-- what the two encode/optical-flow members need. Both are declared
238278
-- in `xpm.linux.deps` above, so the reach is visible in the
@@ -482,7 +522,7 @@ end
482522
-- SILENCE. Four classes, in the order they are tried:
483523
--
484524
-- * a package this ecosystem publishes -- declared in `xpm.linux.deps` and
485-
-- taken from the installed payload. `xim:openssl` covers `libcrypto.so.3`.
525+
-- taken from the installed payload.
486526
-- * proprietary vendor userspace -- also a package, and deliberately so:
487527
-- `xim:nvidia-video-host-link` owns the one question "where is the host's
488528
-- `libnvcuvid.so.1`". The library still comes from the host, because it is
@@ -496,18 +536,37 @@ end
496536
-- that quietly absorbs an unknown soname: the answer to "what does this
497537
-- farm take from outside the ecosystem" has to be a list somebody wrote,
498538
-- not a residue.
499-
local UNSERVED = {
500-
["libcrypto.so.1.1"] =
501-
"OpenSSL 1.1 is end-of-life upstream and this ecosystem publishes 3.x. "
502-
.. "The only member that asks for it is NVIDIA's PKCS#11 provider, "
503-
.. "which no OpenCL entry point reaches.",
504-
}
539+
-- Empty, and the table stays so that the day something lands here somebody has
540+
-- to write down why it cannot be a package. The warning below is what makes
541+
-- leaving it blank impossible to do by accident. `libcrypto.so.1.1` was the
542+
-- only entry and left with the PKCS#11 member that asked for it.
543+
local UNSERVED = {}
505544

506545
local function seal_unresolved(outdir)
507546
local filled, unserved, undeclared = {}, {}, {}
508-
local names = unresolved_against_farm(outdir)
509547
local unserved_dir = path.join(path.directory(outdir), "unserved")
510-
for _, soname in ipairs(names) do
548+
-- ITERATED TO A FIXED POINT, because `readelf -d` reports DIRECT
549+
-- dependencies only.
550+
--
551+
-- The pass this replaced asked `ldd`, whose answer is the whole transitive
552+
-- closure, so one round was enough and the comment said so. `readelf` is
553+
-- the right instrument -- it answers what the FILE says instead of what
554+
-- this machine can resolve -- but it is not transitive, and a library
555+
-- filled in one round brings needs of its own. Measured on the first real
556+
-- install of this package: the farm went from 52 members to 77 and was
557+
-- still nine sonames short, `libLLVM.so.20.1` and `libstdc++.so.6` among
558+
-- them, every one of them reachable from something the same round had just
559+
-- added.
560+
--
561+
-- The bound is not a guess about depth; it is there so a cycle cannot spin.
562+
-- A round that adds nothing ends the loop, which is the normal exit.
563+
local seen = {}
564+
for _ = 1, 16 do
565+
local added = 0
566+
for _, soname in ipairs(unresolved_against_farm(outdir)) do
567+
if seen[soname] then goto next end
568+
seen[soname] = true
569+
added = added + 1
511570
local candidates = find_in_store(soname)
512571
local hit = candidates[#candidates]
513572
if hit then
@@ -520,6 +579,9 @@ local function seal_unresolved(outdir)
520579
unserved[#unserved + 1] = soname
521580
if not UNSERVED[soname] then undeclared[#undeclared + 1] = soname end
522581
end
582+
::next::
583+
end
584+
if added == 0 then break end
523585
end
524586
return filled, unserved, undeclared
525587
end
@@ -607,7 +669,7 @@ local function link_runtime_libs(outdir)
607669
os.exec(
608670
"for lib in " .. sh_quote(dir) .. "/" .. pattern ..
609671
"; do [ -e \"$lib\" ] || continue; " ..
610-
"case \"$(basename \"$lib\")\" in libnvidia-gtk*) continue;; esac; " ..
672+
"case \"$(basename \"$lib\")\" in libnvidia-gtk*|libnvidia-pkcs11*) continue;; esac; " ..
611673
"ln -sf \"$lib\" " .. sh_quote(outdir) .. "/\"$(basename \"$lib\")\"; " ..
612674
"done"
613675
)

0 commit comments

Comments
 (0)