diff --git a/CHANGELOG.md b/CHANGELOG.md index d8a1c97..d896d38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,26 @@ ## [Unreleased] +### Fixed + +- **两处只有把 glx 那一版真正跑一遍才会现形的缺陷。** 上一轮我量了 opencl 和 + vulkan,`compat.glx-runtime` 的新逻辑**从头到尾没有被执行过**。 + + ⚠️⚠️ **`DT_NEEDED` 里可以是绝对路径。** 这个 farm 的四个 glvnd 厂商入口 + (`libEGL_nvidia`、`libGLESv1_CM_nvidia`、`libGLESv2_nvidia`、`libGLX_nvidia`) + 直接写着 `/lib/x86_64-linux-gnu/...`。loader 对这类条目直接打开、**完全不走 + 搜索路径**,所以 farm 既服务不了它也不该为它封 unserved —— 而把它当 soname 会 + 去查一个带斜杠的名字,并且造出一个**名字是路径**的 unserved 链接。三个包一并 + 跳过这类条目。 + + ⚠️ **找不到 `readelf` 时那一趟静默返回空**,读数与「farm 已完全闭合」一模一样。 + 这正是这批改动要消灭的那种混淆,只是掉到了工具查找这一层。现在会明确告警, + 并且 `compat.glx-runtime` 的工具查找也和另外两个一样**先查 store 再查 PATH** + —— 这个包跑在从未被要求装工具链的机器上。 + + 实测(本机,对着已装的 glx farm 走同一套逻辑):52 个成员、跳过 4 条绝对路径、 + 19 条需补,**19 条全部来自生态载荷,0 条 unserved**,没有路径形状的条目。 + ### Changed - **`compat.vulkan` 1.4.357.1 —— 移动一个钉,需要一个新版本。** diff --git a/pkgs/c/compat.glx-runtime.lua b/pkgs/c/compat.glx-runtime.lua index 793fa1b..18a8533 100644 --- a/pkgs/c/compat.glx-runtime.lua +++ b/pkgs/c/compat.glx-runtime.lua @@ -278,7 +278,21 @@ end -- the host, cannot load it. `readelf -d` answers what the FILE says, and -- membership is decided against this directory alone, which is the question -- mcpp asks of it. +-- The store first, PATH second. Under xlings a payload's own binutils is the +-- one that matches the objects being read, and a host `readelf` may simply not +-- be installed -- this package runs on machines that were never asked to have a +-- toolchain. compat.opencl-runtime and compat.vulkan-runtime look the same way. local function find_tool(name) + for _, root in ipairs(xim_store_roots()) do + local f = io.popen(string.format( + [[ls -1 "%s"/xim-x-binutils/*/bin/%s "%s"/xim-x-gcc/*/bin/%s 2>/dev/null | sort -V | tail -1]], + root, name, root, name)) + if f then + local hit = (f:read("l") or ""):gsub("[\r\n]+$", "") + f:close() + if hit ~= "" then return hit end + end + end local f = io.popen(string.format([[command -v %s 2>/dev/null]], name)) if f then local hit = (f:read("l") or ""):gsub("[\r\n]+$", "") @@ -290,7 +304,20 @@ end local function unresolved_against_farm(outdir) local readelf = find_tool("readelf") - if not readelf then return {} end + -- A MISSING TOOL IS NOT AN EMPTY ANSWER. + -- + -- Returning `{}` here would report "no member needs anything this farm + -- lacks", which is the reading a fully closed farm produces -- so the one + -- environment where this pass cannot run would be indistinguishable from + -- the one where it ran and found nothing. That is the confusion this whole + -- change exists to remove, one layer down, in the tool lookup. + if not readelf then + log.warn("compat.glx-runtime: readelf was not found, so the farm's own members were " + .. "not checked. This is NOT the same as finding no gaps: " + .. "install xim:binutils, or read HOST-SURFACE.txt with the " + .. "knowledge that it is incomplete.") + return {} + end local have, members = {}, {} local lsf = io.popen(string.format([[ls -1 "%s" 2>/dev/null]], outdir)) if not lsf then return {} end @@ -307,10 +334,26 @@ local function unresolved_against_farm(outdir) if f then for line in f:lines() do local n = line:gsub("[\r\n]+$", "") + -- AN ABSOLUTE `DT_NEEDED` NEVER GOES THROUGH A SEARCH PATH. + -- + -- The loader opens it directly, so this farm can neither serve + -- it nor honestly record it as unserved -- and treating it as a + -- soname produces a lookup for a name with slashes in it and, + -- worse, an `unserved` link whose name is a path. Measured on + -- this farm: four members -- the glvnd vendor entries + -- `libEGL_nvidia`, `libGLESv1_CM_nvidia`, `libGLESv2_nvidia` + -- and `libGLX_nvidia` -- name `/lib/x86_64-linux-gnu/...` + -- outright. They are a host reach that bypasses everything this + -- package arranges, which is worth knowing and is not this + -- pass's to answer. + if n:sub(1, 1) == "/" then + goto continue + end if n ~= "" and not have[n] and not never_farm[n] and not seen[n] then seen[n] = true out[#out + 1] = n end + ::continue:: end f:close() end diff --git a/pkgs/c/compat.opencl-runtime.lua b/pkgs/c/compat.opencl-runtime.lua index e07fab9..ff5e4c5 100644 --- a/pkgs/c/compat.opencl-runtime.lua +++ b/pkgs/c/compat.opencl-runtime.lua @@ -402,7 +402,20 @@ end -- one is how a farm's own check passes while its consumer's does not. local function unresolved_against_farm(outdir) local readelf = find_tool("readelf") - if not readelf then return {} end + -- A MISSING TOOL IS NOT AN EMPTY ANSWER. + -- + -- Returning `{}` here would report "no member needs anything this farm + -- lacks", which is the reading a fully closed farm produces -- so the one + -- environment where this pass cannot run would be indistinguishable from + -- the one where it ran and found nothing. That is the confusion this whole + -- change exists to remove, one layer down, in the tool lookup. + if not readelf then + log.warn("compat.opencl-runtime: readelf was not found, so the farm's own members were " + .. "not checked. This is NOT the same as finding no gaps: " + .. "install xim:binutils, or read HOST-SURFACE.txt with the " + .. "knowledge that it is incomplete.") + return {} + end local have, members = {}, {} local lsf = io.popen(string.format([[ls -1 "%s" 2>/dev/null]], outdir)) if not lsf then return {} end @@ -419,10 +432,26 @@ local function unresolved_against_farm(outdir) if f then for line in f:lines() do local n = line:gsub("[\r\n]+$", "") + -- AN ABSOLUTE `DT_NEEDED` NEVER GOES THROUGH A SEARCH PATH. + -- + -- The loader opens it directly, so this farm can neither serve + -- it nor honestly record it as unserved -- and treating it as a + -- soname produces a lookup for a name with slashes in it and, + -- worse, an `unserved` link whose name is a path. Measured on + -- this farm: four members -- the glvnd vendor entries + -- `libEGL_nvidia`, `libGLESv1_CM_nvidia`, `libGLESv2_nvidia` + -- and `libGLX_nvidia` -- name `/lib/x86_64-linux-gnu/...` + -- outright. They are a host reach that bypasses everything this + -- package arranges, which is worth knowing and is not this + -- pass's to answer. + if n:sub(1, 1) == "/" then + goto continue + end if n ~= "" and not have[n] and not never_farm[n] and not seen[n] then seen[n] = true out[#out + 1] = n end + ::continue:: end f:close() end diff --git a/pkgs/c/compat.vulkan-runtime.lua b/pkgs/c/compat.vulkan-runtime.lua index 381924f..114c75f 100644 --- a/pkgs/c/compat.vulkan-runtime.lua +++ b/pkgs/c/compat.vulkan-runtime.lua @@ -817,7 +817,20 @@ end -- one is how a farm's own check passes while its consumer's does not. local function unresolved_against_farm(outdir) local readelf = find_tool("readelf") - if not readelf then return {} end + -- A MISSING TOOL IS NOT AN EMPTY ANSWER. + -- + -- Returning `{}` here would report "no member needs anything this farm + -- lacks", which is the reading a fully closed farm produces -- so the one + -- environment where this pass cannot run would be indistinguishable from + -- the one where it ran and found nothing. That is the confusion this whole + -- change exists to remove, one layer down, in the tool lookup. + if not readelf then + log.warn("compat.vulkan-runtime: readelf was not found, so the farm's own members were " + .. "not checked. This is NOT the same as finding no gaps: " + .. "install xim:binutils, or read HOST-SURFACE.txt with the " + .. "knowledge that it is incomplete.") + return {} + end local have, members = {}, {} local lsf = io.popen(string.format([[ls -1 "%s" 2>/dev/null]], outdir)) if not lsf then return {} end @@ -834,10 +847,26 @@ local function unresolved_against_farm(outdir) if f then for line in f:lines() do local n = line:gsub("[\r\n]+$", "") + -- AN ABSOLUTE `DT_NEEDED` NEVER GOES THROUGH A SEARCH PATH. + -- + -- The loader opens it directly, so this farm can neither serve + -- it nor honestly record it as unserved -- and treating it as a + -- soname produces a lookup for a name with slashes in it and, + -- worse, an `unserved` link whose name is a path. Measured on + -- this farm: four members -- the glvnd vendor entries + -- `libEGL_nvidia`, `libGLESv1_CM_nvidia`, `libGLESv2_nvidia` + -- and `libGLX_nvidia` -- name `/lib/x86_64-linux-gnu/...` + -- outright. They are a host reach that bypasses everything this + -- package arranges, which is worth knowing and is not this + -- pass's to answer. + if n:sub(1, 1) == "/" then + goto continue + end if n ~= "" and not have[n] and not never_farm[n] and not seen[n] then seen[n] = true out[#out + 1] = n end + ::continue:: end f:close() end