Skip to content

Commit 08253a6

Browse files
committed
fix(compat): an absolute DT_NEEDED is not a soname, and a missing tool is not an empty answer
Two defects that only appear when `compat.glx-runtime`'s new pass is actually executed. The previous change measured the opencl and vulkan farms; the glx one had never been run. AN ABSOLUTE `DT_NEEDED` NEVER GOES THROUGH A SEARCH PATH. Four members of this farm -- the glvnd vendor entries `libEGL_nvidia`, `libGLESv1_CM_nvidia`, `libGLESv2_nvidia` and `libGLX_nvidia` -- name `/lib/x86_64-linux-gnu/...` outright. The loader opens those directly, so the farm can neither serve them nor honestly record them as unserved. Treating one as a soname looks up a name with slashes in it and then writes an `unserved` link whose NAME is a path. All three recipes skip them. A MISSING TOOL IS NOT AN EMPTY ANSWER. With `readelf` absent the pass returned `{}`, which reads exactly like a farm with no gaps -- the confusion this whole batch exists to remove, one layer down in the tool lookup. It now warns, and `compat.glx-runtime`'s lookup reaches the xim store before PATH like the other two, because this package runs on machines that were never asked to have a toolchain. Measured against the installed glx farm with the same logic: 52 members, 4 absolute entries skipped, 19 sonames needed, all 19 filled from ecosystem payloads, 0 unserved, and no path-shaped entry.
1 parent 698c60d commit 08253a6

4 files changed

Lines changed: 124 additions & 3 deletions

File tree

‎CHANGELOG.md‎

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

88
## [Unreleased]
99

10+
### Fixed
11+
12+
- **两处只有把 glx 那一版真正跑一遍才会现形的缺陷。** 上一轮我量了 opencl 和
13+
vulkan,`compat.glx-runtime` 的新逻辑**从头到尾没有被执行过**。
14+
15+
⚠️⚠️ **`DT_NEEDED` 里可以是绝对路径。** 这个 farm 的四个 glvnd 厂商入口
16+
(`libEGL_nvidia`、`libGLESv1_CM_nvidia`、`libGLESv2_nvidia`、`libGLX_nvidia`)
17+
直接写着 `/lib/x86_64-linux-gnu/...`。loader 对这类条目直接打开、**完全不走
18+
搜索路径**,所以 farm 既服务不了它也不该为它封 unserved —— 而把它当 soname 会
19+
去查一个带斜杠的名字,并且造出一个**名字是路径**的 unserved 链接。三个包一并
20+
跳过这类条目。
21+
22+
⚠️ **找不到 `readelf` 时那一趟静默返回空**,读数与「farm 已完全闭合」一模一样。
23+
这正是这批改动要消灭的那种混淆,只是掉到了工具查找这一层。现在会明确告警,
24+
并且 `compat.glx-runtime` 的工具查找也和另外两个一样**先查 store 再查 PATH**
25+
—— 这个包跑在从未被要求装工具链的机器上。
26+
27+
实测(本机,对着已装的 glx farm 走同一套逻辑):52 个成员、跳过 4 条绝对路径、
28+
19 条需补,**19 条全部来自生态载荷,0 条 unserved**,没有路径形状的条目。
29+
1030
### Changed
1131

1232
- **`compat.vulkan` 1.4.357.1 —— 移动一个钉,需要一个新版本。**

‎pkgs/c/compat.glx-runtime.lua‎

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,21 @@ end
278278
-- the host, cannot load it. `readelf -d` answers what the FILE says, and
279279
-- membership is decided against this directory alone, which is the question
280280
-- mcpp asks of it.
281+
-- The store first, PATH second. Under xlings a payload's own binutils is the
282+
-- one that matches the objects being read, and a host `readelf` may simply not
283+
-- be installed -- this package runs on machines that were never asked to have a
284+
-- toolchain. compat.opencl-runtime and compat.vulkan-runtime look the same way.
281285
local function find_tool(name)
286+
for _, root in ipairs(xim_store_roots()) do
287+
local f = io.popen(string.format(
288+
[[ls -1 "%s"/xim-x-binutils/*/bin/%s "%s"/xim-x-gcc/*/bin/%s 2>/dev/null | sort -V | tail -1]],
289+
root, name, root, name))
290+
if f then
291+
local hit = (f:read("l") or ""):gsub("[\r\n]+$", "")
292+
f:close()
293+
if hit ~= "" then return hit end
294+
end
295+
end
282296
local f = io.popen(string.format([[command -v %s 2>/dev/null]], name))
283297
if f then
284298
local hit = (f:read("l") or ""):gsub("[\r\n]+$", "")
@@ -290,7 +304,20 @@ end
290304

291305
local function unresolved_against_farm(outdir)
292306
local readelf = find_tool("readelf")
293-
if not readelf then return {} end
307+
-- A MISSING TOOL IS NOT AN EMPTY ANSWER.
308+
--
309+
-- Returning `{}` here would report "no member needs anything this farm
310+
-- lacks", which is the reading a fully closed farm produces -- so the one
311+
-- environment where this pass cannot run would be indistinguishable from
312+
-- the one where it ran and found nothing. That is the confusion this whole
313+
-- change exists to remove, one layer down, in the tool lookup.
314+
if not readelf then
315+
log.warn("compat.glx-runtime: readelf was not found, so the farm's own members were "
316+
.. "not checked. This is NOT the same as finding no gaps: "
317+
.. "install xim:binutils, or read HOST-SURFACE.txt with the "
318+
.. "knowledge that it is incomplete.")
319+
return {}
320+
end
294321
local have, members = {}, {}
295322
local lsf = io.popen(string.format([[ls -1 "%s" 2>/dev/null]], outdir))
296323
if not lsf then return {} end
@@ -307,10 +334,26 @@ local function unresolved_against_farm(outdir)
307334
if f then
308335
for line in f:lines() do
309336
local n = line:gsub("[\r\n]+$", "")
337+
-- AN ABSOLUTE `DT_NEEDED` NEVER GOES THROUGH A SEARCH PATH.
338+
--
339+
-- The loader opens it directly, so this farm can neither serve
340+
-- it nor honestly record it as unserved -- and treating it as a
341+
-- soname produces a lookup for a name with slashes in it and,
342+
-- worse, an `unserved` link whose name is a path. Measured on
343+
-- this farm: four members -- the glvnd vendor entries
344+
-- `libEGL_nvidia`, `libGLESv1_CM_nvidia`, `libGLESv2_nvidia`
345+
-- and `libGLX_nvidia` -- name `/lib/x86_64-linux-gnu/...`
346+
-- outright. They are a host reach that bypasses everything this
347+
-- package arranges, which is worth knowing and is not this
348+
-- pass's to answer.
349+
if n:sub(1, 1) == "/" then
350+
goto continue
351+
end
310352
if n ~= "" and not have[n] and not never_farm[n] and not seen[n] then
311353
seen[n] = true
312354
out[#out + 1] = n
313355
end
356+
::continue::
314357
end
315358
f:close()
316359
end

‎pkgs/c/compat.opencl-runtime.lua‎

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,20 @@ end
402402
-- one is how a farm's own check passes while its consumer's does not.
403403
local function unresolved_against_farm(outdir)
404404
local readelf = find_tool("readelf")
405-
if not readelf then return {} end
405+
-- A MISSING TOOL IS NOT AN EMPTY ANSWER.
406+
--
407+
-- Returning `{}` here would report "no member needs anything this farm
408+
-- lacks", which is the reading a fully closed farm produces -- so the one
409+
-- environment where this pass cannot run would be indistinguishable from
410+
-- the one where it ran and found nothing. That is the confusion this whole
411+
-- change exists to remove, one layer down, in the tool lookup.
412+
if not readelf then
413+
log.warn("compat.opencl-runtime: readelf was not found, so the farm's own members were "
414+
.. "not checked. This is NOT the same as finding no gaps: "
415+
.. "install xim:binutils, or read HOST-SURFACE.txt with the "
416+
.. "knowledge that it is incomplete.")
417+
return {}
418+
end
406419
local have, members = {}, {}
407420
local lsf = io.popen(string.format([[ls -1 "%s" 2>/dev/null]], outdir))
408421
if not lsf then return {} end
@@ -419,10 +432,26 @@ local function unresolved_against_farm(outdir)
419432
if f then
420433
for line in f:lines() do
421434
local n = line:gsub("[\r\n]+$", "")
435+
-- AN ABSOLUTE `DT_NEEDED` NEVER GOES THROUGH A SEARCH PATH.
436+
--
437+
-- The loader opens it directly, so this farm can neither serve
438+
-- it nor honestly record it as unserved -- and treating it as a
439+
-- soname produces a lookup for a name with slashes in it and,
440+
-- worse, an `unserved` link whose name is a path. Measured on
441+
-- this farm: four members -- the glvnd vendor entries
442+
-- `libEGL_nvidia`, `libGLESv1_CM_nvidia`, `libGLESv2_nvidia`
443+
-- and `libGLX_nvidia` -- name `/lib/x86_64-linux-gnu/...`
444+
-- outright. They are a host reach that bypasses everything this
445+
-- package arranges, which is worth knowing and is not this
446+
-- pass's to answer.
447+
if n:sub(1, 1) == "/" then
448+
goto continue
449+
end
422450
if n ~= "" and not have[n] and not never_farm[n] and not seen[n] then
423451
seen[n] = true
424452
out[#out + 1] = n
425453
end
454+
::continue::
426455
end
427456
f:close()
428457
end

‎pkgs/c/compat.vulkan-runtime.lua‎

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -817,7 +817,20 @@ end
817817
-- one is how a farm's own check passes while its consumer's does not.
818818
local function unresolved_against_farm(outdir)
819819
local readelf = find_tool("readelf")
820-
if not readelf then return {} end
820+
-- A MISSING TOOL IS NOT AN EMPTY ANSWER.
821+
--
822+
-- Returning `{}` here would report "no member needs anything this farm
823+
-- lacks", which is the reading a fully closed farm produces -- so the one
824+
-- environment where this pass cannot run would be indistinguishable from
825+
-- the one where it ran and found nothing. That is the confusion this whole
826+
-- change exists to remove, one layer down, in the tool lookup.
827+
if not readelf then
828+
log.warn("compat.vulkan-runtime: readelf was not found, so the farm's own members were "
829+
.. "not checked. This is NOT the same as finding no gaps: "
830+
.. "install xim:binutils, or read HOST-SURFACE.txt with the "
831+
.. "knowledge that it is incomplete.")
832+
return {}
833+
end
821834
local have, members = {}, {}
822835
local lsf = io.popen(string.format([[ls -1 "%s" 2>/dev/null]], outdir))
823836
if not lsf then return {} end
@@ -834,10 +847,26 @@ local function unresolved_against_farm(outdir)
834847
if f then
835848
for line in f:lines() do
836849
local n = line:gsub("[\r\n]+$", "")
850+
-- AN ABSOLUTE `DT_NEEDED` NEVER GOES THROUGH A SEARCH PATH.
851+
--
852+
-- The loader opens it directly, so this farm can neither serve
853+
-- it nor honestly record it as unserved -- and treating it as a
854+
-- soname produces a lookup for a name with slashes in it and,
855+
-- worse, an `unserved` link whose name is a path. Measured on
856+
-- this farm: four members -- the glvnd vendor entries
857+
-- `libEGL_nvidia`, `libGLESv1_CM_nvidia`, `libGLESv2_nvidia`
858+
-- and `libGLX_nvidia` -- name `/lib/x86_64-linux-gnu/...`
859+
-- outright. They are a host reach that bypasses everything this
860+
-- package arranges, which is worth knowing and is not this
861+
-- pass's to answer.
862+
if n:sub(1, 1) == "/" then
863+
goto continue
864+
end
837865
if n ~= "" and not have[n] and not never_farm[n] and not seen[n] then
838866
seen[n] = true
839867
out[#out + 1] = n
840868
end
869+
::continue::
841870
end
842871
f:close()
843872
end

0 commit comments

Comments
 (0)