feat(compat): the driver farm enumerates the sentinel instead of naming a file - #375
Merged
Merged
Conversation
…ng a file `compat.sycl-runtime` and `compat.cuda-driver` built their driver farm from one hand-written name, `libcuda.so.1`, while enumerating every other directory they draw from. The hand-written half is the half that was wrong: `libur_adapter_cuda.so.0` has `libnvidia-ml.so.1` in DT_NEEDED as well, the farm did not carry it, the adapter did not load, the CUDA back end disappeared, and the program terminated with exit code 134 and no exception text (mcpp#596). Which driver libraries exist is the sentinel's question. A farm that reads its directory cannot disagree with it; a farm that names a file already had. Both recipes now link every versioned soname the sentinel publishes and pin `xim:libcuda-host-link@0.0.2`, the version at which it answers for a set. Old version keys are kept. What the new keys buy is a reinstall rather than a different recipe: there is one install() per file and neither reads pkginfo.version(), so an old pin installed today builds the current farm. `compat.sycl-runtime` also states, for the first time, that it does not serve `libOpenCL.so.1`. The payload ships an OpenCL adapter and `compat:opencl` would satisfy it in one line, but that package depends in turn on the host's proprietary OpenCL driver farm -- a machine-specific vendor surface in every SYCL project -- and it supplies `libnvidia-ml.so.1`, which made the farm above look correct while it was not. A project that wants the back end declares `compat:opencl` itself. The test is rewritten from three hand-written dlopens to a DT_NEEDED closure walk over every farm member. Three names against twenty-six members is why this criterion was green for the whole life of the defect. dlopen of every member is not enough either: it measures the process, whose search path holds more than this package put there, and measurement showed another farm supplying the missing soname. The walk reads the farm alone and separates three states -- resolved, present but dangling (a machine with no driver), absent (a packaging gap). Measured, all three legs: repaired farm, driver present PASSED 26 members, 26 walked NVML removed from the farm FAILED names the member and the soname driver links made dangling PASSED 24 of 26 walked, 2 noted
Sunrisepeak
added a commit
to openxlings/xim-pkgindex
that referenced
this pull request
Sep 9, 2026
…recorded beside the list (#798) `compat.cuda-driver` records a measurement that decided libnvidia-ptxjitcompiler is unnecessary, and mcpplibs/mcpp-index#375 says that result belongs beside the list that decides the set rather than beside one consumer of it. That sentence was true about where it should live and false about where it was: this is the half that moves it. A farm that mirrors this directory inherits both the additions and the omissions, so an omission whose reason lives in one consumer is an omission the next consumer re-litigates. Co-authored-by: sunrisepeak <x.d2learn.org@gmail.com>
Sunrisepeak
pushed a commit
to mcpp-community/mcpp
that referenced
this pull request
Sep 9, 2026
…er process (2026.9.10.1) A SYCL project built cleanly and then terminated with exit code 134 and no exception text (#596). The trigger was in the ecosystem -- an adapter's farm was missing one driver library -- but the reasons it presented as a silent abort are two independent gaps in mcpp, and both are repaired here. THE SURFACE NOTHING WALKED. `resolve_runtime_closure` is seeded with the artifact and follows DT_NEEDED. A library a package publishes through `runtime.library_dirs` exists precisely because something will dlopen it, so no link edge names it and it is outside that closure BY CONSTRUCTION. Measured: a farm of twenty-five libraries, two of which could not load at all, while the build reported nothing -- because nothing had asked. `inspect_dlopen_surface` reads each such library's own DT_NEEDED and resolves it against the search path the artifact actually carries, separating three states: resolved, present as a dangling link (the machine has no driver), and absent (a packaging gap). Only the third is reported, and it is a warning: a dangling link is the documented shape of a host driver that is not installed, and failing there would turn a supported configuration into a failed build. `runtime.dlopen_surface` in resolution.json carries the findings and both denominators -- a surface that failed to build enumerates nothing, and "no findings" must not read like "nothing was examined". TWO UNWINDERS IN ONE PROCESS. A lane whose device compiler is configured against libstdc++ puts libstdc++ on the link line while the artifact links libc++ statically. `hide_static_cxx_runtime` skipped executables on the premise that "ld exports only what a loaded object references, and mcpp passes no -rdynamic" -- a correct premise with a wrong conclusion, because a loaded libstdc++ DOES reference them. Measured: 89 exported symbols, 68 of them also defined by libstdc++ or libgcc_s. Ten of libgcc's eighteen `_Unwind_*` entry points came from the artifact and eight stayed in libgcc_s, including the accessors libstdc++'s personality routine calls. It read an LLVM libunwind context through libgcc's accessors, recovered a meaningless IP, found no landing pad, and `__cxa_call_terminate` ran past a handler three frames up; the verbose terminate handler's rethrow then terminated as well, which is why nothing was printed. Such a link now takes `--unwindlib=libgcc` and hides the static archives' symbols. libgcc_s is in the process either way -- libstdc++ needs it -- so this names a library rather than adding one, and the C++ runtime stays embedded. A link with no second runtime on it is byte-for-byte unchanged. Measured on one machine, same source, both legs: before exit 134, no output after `sycl: no usable device: ...` / `device unavailable`, exit 1 device `12 24 36 48` in both `-Wl,--exclude-libs` alone was written here as a prediction from the mechanism and then measured: exit 139 instead of 134. Hiding the exports makes libstdc++ bind to libgcc while the artifact's own libc++abi still calls its statically linked libunwind, so the mismatch reproduces in the other direction. The reason is recorded in the design record so the flag is not proposed again. The duplicate-symbol warning now states that consequence when the conflicting set includes the unwinder family, instead of describing it as one more copy that is never called. One documented claim was refuted along the way: the SYCL example states that a missing device image is the one failure its island cannot turn into a return code. Measured by compiling it for sm_90 and running on an sm_89 device -- it was not outside the catches; no catch worked. The example's comment and README are corrected. Design record: .agents/docs/2026-09-09-dlopen-surface-and-two-unwinders.md Ecosystem halves: openxlings/xim-pkgindex#796, mcpplibs/mcpp-index#375
Sunrisepeak
pushed a commit
to mcpp-community/mcpp
that referenced
this pull request
Sep 9, 2026
…er process (2026.9.10.1) A SYCL project built cleanly and then terminated with exit code 134 and no exception text (#596). The trigger was in the ecosystem -- an adapter's farm was missing one driver library -- but the reasons it presented as a silent abort are two independent gaps in mcpp, and both are repaired here. THE SURFACE NOTHING WALKED. `resolve_runtime_closure` is seeded with the artifact and follows DT_NEEDED. A library a package publishes through `runtime.library_dirs` exists precisely because something will dlopen it, so no link edge names it and it is outside that closure BY CONSTRUCTION. Measured: a farm of twenty-five libraries, two of which could not load at all, while the build reported nothing -- because nothing had asked. `inspect_dlopen_surface` reads each such library's own DT_NEEDED and resolves it against the search path the artifact actually carries, separating three states: resolved, present as a dangling link (the machine has no driver), and absent (a packaging gap). Only the third is reported, and it is a warning: a dangling link is the documented shape of a host driver that is not installed, and failing there would turn a supported configuration into a failed build. `runtime.dlopen_surface` in resolution.json carries the findings and both denominators -- a surface that failed to build enumerates nothing, and "no findings" must not read like "nothing was examined". TWO UNWINDERS IN ONE PROCESS. A lane whose device compiler is configured against libstdc++ puts libstdc++ on the link line while the artifact links libc++ statically. `hide_static_cxx_runtime` skipped executables on the premise that "ld exports only what a loaded object references, and mcpp passes no -rdynamic" -- a correct premise with a wrong conclusion, because a loaded libstdc++ DOES reference them. Measured: 89 exported symbols, 68 of them also defined by libstdc++ or libgcc_s. Ten of libgcc's eighteen `_Unwind_*` entry points came from the artifact and eight stayed in libgcc_s, including the accessors libstdc++'s personality routine calls. It read an LLVM libunwind context through libgcc's accessors, recovered a meaningless IP, found no landing pad, and `__cxa_call_terminate` ran past a handler three frames up; the verbose terminate handler's rethrow then terminated as well, which is why nothing was printed. Such a link now takes `--unwindlib=libgcc` and hides the static archives' symbols. libgcc_s is in the process either way -- libstdc++ needs it -- so this names a library rather than adding one, and the C++ runtime stays embedded. A link with no second runtime on it is byte-for-byte unchanged. Measured on one machine, same source, both legs: before exit 134, no output after `sycl: no usable device: ...` / `device unavailable`, exit 1 device `12 24 36 48` in both `-Wl,--exclude-libs` alone was written here as a prediction from the mechanism and then measured: exit 139 instead of 134. Hiding the exports makes libstdc++ bind to libgcc while the artifact's own libc++abi still calls its statically linked libunwind, so the mismatch reproduces in the other direction. The reason is recorded in the design record so the flag is not proposed again. The duplicate-symbol warning now states that consequence when the conflicting set includes the unwinder family, instead of describing it as one more copy that is never called. One documented claim was refuted along the way: the SYCL example states that a missing device image is the one failure its island cannot turn into a return code. Measured by compiling it for sm_90 and running on an sm_89 device -- it was not outside the catches; no catch worked. The example's comment and README are corrected. Design record: .agents/docs/2026-09-09-dlopen-surface-and-two-unwinders.md Ecosystem halves: openxlings/xim-pkgindex#796, mcpplibs/mcpp-index#375
Sunrisepeak
pushed a commit
to mcpp-community/mcpp
that referenced
this pull request
Sep 9, 2026
…er process (2026.9.10.1) A SYCL project built cleanly and then terminated with exit code 134 and no exception text (#596). The trigger was in the ecosystem -- an adapter's farm was missing one driver library -- but the reasons it presented as a silent abort are two independent gaps in mcpp, and both are repaired here. THE SURFACE NOTHING WALKED. `resolve_runtime_closure` is seeded with the artifact and follows DT_NEEDED. A library a package publishes through `runtime.library_dirs` exists precisely because something will dlopen it, so no link edge names it and it is outside that closure BY CONSTRUCTION. Measured: a farm of twenty-five libraries, two of which could not load at all, while the build reported nothing -- because nothing had asked. `inspect_dlopen_surface` reads each such library's own DT_NEEDED and resolves it against the search path the artifact actually carries, separating three states: resolved, present as a dangling link (the machine has no driver), and absent (a packaging gap). Only the third is reported, and it is a warning: a dangling link is the documented shape of a host driver that is not installed, and failing there would turn a supported configuration into a failed build. `runtime.dlopen_surface` in resolution.json carries the findings and both denominators -- a surface that failed to build enumerates nothing, and "no findings" must not read like "nothing was examined". TWO UNWINDERS IN ONE PROCESS. A lane whose device compiler is configured against libstdc++ puts libstdc++ on the link line while the artifact links libc++ statically. `hide_static_cxx_runtime` skipped executables on the premise that "ld exports only what a loaded object references, and mcpp passes no -rdynamic" -- a correct premise with a wrong conclusion, because a loaded libstdc++ DOES reference them. Measured: 89 exported symbols, 68 of them also defined by libstdc++ or libgcc_s. Ten of libgcc's eighteen `_Unwind_*` entry points came from the artifact and eight stayed in libgcc_s, including the accessors libstdc++'s personality routine calls. It read an LLVM libunwind context through libgcc's accessors, recovered a meaningless IP, found no landing pad, and `__cxa_call_terminate` ran past a handler three frames up; the verbose terminate handler's rethrow then terminated as well, which is why nothing was printed. Such a link now takes `--unwindlib=libgcc` and hides the static archives' symbols. libgcc_s is in the process either way -- libstdc++ needs it -- so this names a library rather than adding one, and the C++ runtime stays embedded. A link with no second runtime on it is byte-for-byte unchanged. Measured on one machine, same source, both legs: before exit 134, no output after `sycl: no usable device: ...` / `device unavailable`, exit 1 device `12 24 36 48` in both `-Wl,--exclude-libs` alone was written here as a prediction from the mechanism and then measured: exit 139 instead of 134. Hiding the exports makes libstdc++ bind to libgcc while the artifact's own libc++abi still calls its statically linked libunwind, so the mismatch reproduces in the other direction. The reason is recorded in the design record so the flag is not proposed again. The duplicate-symbol warning now states that consequence when the conflicting set includes the unwinder family, instead of describing it as one more copy that is never called. One documented claim was refuted along the way: the SYCL example states that a missing device image is the one failure its island cannot turn into a return code. Measured by compiling it for sm_90 and running on an sm_89 device -- it was not outside the catches; no catch worked. The example's comment and README are corrected. Design record: .agents/docs/2026-09-09-dlopen-surface-and-two-unwinders.md Ecosystem halves: openxlings/xim-pkgindex#796, mcpplibs/mcpp-index#375
Sunrisepeak
pushed a commit
to mcpp-community/mcpp
that referenced
this pull request
Sep 9, 2026
…er process (2026.9.10.1) A SYCL project built cleanly and then terminated with exit code 134 and no exception text (#596). The trigger was in the ecosystem -- an adapter's farm was missing one driver library -- but the reasons it presented as a silent abort are two independent gaps in mcpp, and both are repaired here. THE SURFACE NOTHING WALKED. `resolve_runtime_closure` is seeded with the artifact and follows DT_NEEDED. A library a package publishes through `runtime.library_dirs` exists precisely because something will dlopen it, so no link edge names it and it is outside that closure BY CONSTRUCTION. Measured: a farm of twenty-five libraries, two of which could not load at all, while the build reported nothing -- because nothing had asked. `inspect_dlopen_surface` reads each such library's own DT_NEEDED and resolves it against the search path the artifact actually carries, separating three states: resolved, present as a dangling link (the machine has no driver), and absent (a packaging gap). Only the third is reported, and it is a warning: a dangling link is the documented shape of a host driver that is not installed, and failing there would turn a supported configuration into a failed build. `runtime.dlopen_surface` in resolution.json carries the findings and both denominators -- a surface that failed to build enumerates nothing, and "no findings" must not read like "nothing was examined". WHAT "THE SEARCH PATH THE ARTIFACT ACTUALLY CARRIES" TURNED OUT TO MEAN. Three corrections, all of them false positives, none visible until a project with a shared dependency was measured: * `$ORIGIN` leads every artifact's DT_RPATH and a shared dependency is deployed BESIDE the executable. `runtime_search_dirs` cannot carry that -- `$ORIGIN` is a property of each artifact, not of the plan -- so the artifacts' own directories are added in `check_dlopen_surface`. * A plan that produces no program has no surface to judge. The adapter package is `kind = "lib"`; reporting a consumer's surface against an archive's non-existent search path named a library the consumer resolves. * A SONAME is not a filename. mcpp links `bin/libopencl.so` whose SONAME is `libOpenCL.so.1`, and the alias appears later; `mcpp test` calls the check twice and only the second call saw it. The SONAMEs this build produces are read from the objects and passed in. TWO UNWINDERS IN ONE PROCESS. A lane whose device compiler is configured against libstdc++ puts libstdc++ on the link line while the artifact links libc++ statically. `hide_static_cxx_runtime` skipped executables on the premise that "ld exports only what a loaded object references, and mcpp passes no -rdynamic" -- a correct premise with a wrong conclusion, because a loaded libstdc++ DOES reference them. Measured: 89 exported symbols, 68 of them also defined by libstdc++ or libgcc_s. Ten of libgcc's eighteen `_Unwind_*` entry points came from the artifact and eight stayed in libgcc_s, including the accessors libstdc++'s personality routine calls. It read an LLVM libunwind context through libgcc's accessors, recovered a meaningless IP, found no landing pad, and `__cxa_call_terminate` ran past a handler three frames up; the verbose terminate handler's rethrow then terminated as well, which is why nothing was printed. Such a link now takes `--unwindlib=libgcc` and hides the static archives' symbols. libgcc_s is in the process either way -- libstdc++ needs it -- so this names a library rather than adding one, and the C++ runtime stays embedded. A link with no second runtime on it is byte-for-byte unchanged. Measured on one machine, same source, both situations: before exit 134, no output after `sycl: no usable device: ...` / `device unavailable`, exit 1 device `12 24 36 48` in both `-Wl,--exclude-libs` alone was written here as a prediction from the mechanism and then measured: exit 139 instead of 134. Hiding the exports makes libstdc++ bind to libgcc while the artifact's own libc++abi still calls its statically linked libunwind, so the mismatch reproduces in the other direction. The reason is recorded in the design record so the flag is not proposed again. The duplicate-symbol warning now states that consequence when the conflicting set includes the unwinder family, instead of describing it as one more copy that is never called. One documented claim was refuted along the way: the SYCL example states that a missing device image is the one failure its island cannot turn into a return code. Measured by compiling it for sm_90 and running on an sm_89 device -- it was not outside the catches; no catch worked. The example's comment and README are corrected. Design record: .agents/docs/2026-09-09-dlopen-surface-and-two-unwinders.md Ecosystem halves: openxlings/xim-pkgindex#796 #798, mcpplibs/mcpp-index#375 #377 #378
Sunrisepeak
added a commit
to mcpp-community/mcpp
that referenced
this pull request
Sep 9, 2026
…er process (2026.9.10.1) (#598) * fix(runtime, build): the dlopen surface is walked, and one unwinder per process (2026.9.10.1) A SYCL project built cleanly and then terminated with exit code 134 and no exception text (#596). The trigger was in the ecosystem -- an adapter's farm was missing one driver library -- but the reasons it presented as a silent abort are two independent gaps in mcpp, and both are repaired here. THE SURFACE NOTHING WALKED. `resolve_runtime_closure` is seeded with the artifact and follows DT_NEEDED. A library a package publishes through `runtime.library_dirs` exists precisely because something will dlopen it, so no link edge names it and it is outside that closure BY CONSTRUCTION. Measured: a farm of twenty-five libraries, two of which could not load at all, while the build reported nothing -- because nothing had asked. `inspect_dlopen_surface` reads each such library's own DT_NEEDED and resolves it against the search path the artifact actually carries, separating three states: resolved, present as a dangling link (the machine has no driver), and absent (a packaging gap). Only the third is reported, and it is a warning: a dangling link is the documented shape of a host driver that is not installed, and failing there would turn a supported configuration into a failed build. `runtime.dlopen_surface` in resolution.json carries the findings and both denominators -- a surface that failed to build enumerates nothing, and "no findings" must not read like "nothing was examined". WHAT "THE SEARCH PATH THE ARTIFACT ACTUALLY CARRIES" TURNED OUT TO MEAN. Three corrections, all of them false positives, none visible until a project with a shared dependency was measured: * `$ORIGIN` leads every artifact's DT_RPATH and a shared dependency is deployed BESIDE the executable. `runtime_search_dirs` cannot carry that -- `$ORIGIN` is a property of each artifact, not of the plan -- so the artifacts' own directories are added in `check_dlopen_surface`. * A plan that produces no program has no surface to judge. The adapter package is `kind = "lib"`; reporting a consumer's surface against an archive's non-existent search path named a library the consumer resolves. * A SONAME is not a filename. mcpp links `bin/libopencl.so` whose SONAME is `libOpenCL.so.1`, and the alias appears later; `mcpp test` calls the check twice and only the second call saw it. The SONAMEs this build produces are read from the objects and passed in. TWO UNWINDERS IN ONE PROCESS. A lane whose device compiler is configured against libstdc++ puts libstdc++ on the link line while the artifact links libc++ statically. `hide_static_cxx_runtime` skipped executables on the premise that "ld exports only what a loaded object references, and mcpp passes no -rdynamic" -- a correct premise with a wrong conclusion, because a loaded libstdc++ DOES reference them. Measured: 89 exported symbols, 68 of them also defined by libstdc++ or libgcc_s. Ten of libgcc's eighteen `_Unwind_*` entry points came from the artifact and eight stayed in libgcc_s, including the accessors libstdc++'s personality routine calls. It read an LLVM libunwind context through libgcc's accessors, recovered a meaningless IP, found no landing pad, and `__cxa_call_terminate` ran past a handler three frames up; the verbose terminate handler's rethrow then terminated as well, which is why nothing was printed. Such a link now takes `--unwindlib=libgcc` and hides the static archives' symbols. libgcc_s is in the process either way -- libstdc++ needs it -- so this names a library rather than adding one, and the C++ runtime stays embedded. A link with no second runtime on it is byte-for-byte unchanged. Measured on one machine, same source, both situations: before exit 134, no output after `sycl: no usable device: ...` / `device unavailable`, exit 1 device `12 24 36 48` in both `-Wl,--exclude-libs` alone was written here as a prediction from the mechanism and then measured: exit 139 instead of 134. Hiding the exports makes libstdc++ bind to libgcc while the artifact's own libc++abi still calls its statically linked libunwind, so the mismatch reproduces in the other direction. The reason is recorded in the design record so the flag is not proposed again. The duplicate-symbol warning now states that consequence when the conflicting set includes the unwinder family, instead of describing it as one more copy that is never called. One documented claim was refuted along the way: the SYCL example states that a missing device image is the one failure its island cannot turn into a return code. Measured by compiling it for sm_90 and running on an sm_89 device -- it was not outside the catches; no catch worked. The example's comment and README are corrected. Design record: .agents/docs/2026-09-09-dlopen-surface-and-two-unwinders.md Ecosystem halves: openxlings/xim-pkgindex#796 #798, mcpplibs/mcpp-index#375 #377 #378 * fix(plan, symbol_provision): a build program's objects stay in this package's images, and vague linkage is not a second provider Two defects that serving the SYCL runtime's OpenCL adapter made active. Both were latent, neither is caused by #596, and both were found by the checks this branch sharpened rather than by reading. A BUILD PROGRAM'S OBJECTS REACHED A DEPENDENCY'S IMAGE. `role = "object"` with no named target attaches to "every linked image", and that read as "every link unit in this plan" -- which includes the shared library a dependency contributes. Measured: `compat:opencl`'s ICD loader, a C library, came out of the link carrying `saxpy_device` and thirty-seven `sycl::` instantiations, 193 dynamic symbols where its own API is 154, and the process held two copies of the device island. `LinkUnit::dependencyOwned` now separates the images this package produces from the ones a dependency contributes. After: 0 sycl symbols, 154 exports, all of them its own `cl*` entry points. Latent until a SYCL project first had a shared dependency, which is what declaring `compat:opencl` did. VAGUE LINKAGE IS NOT A SECOND PROVIDER. `DynamicSymbol` recorded the symbol's TYPE and not its BINDING, so template instantiations, inline functions and vtables -- which the C++ ABI emits into every image and expects the loader to unify -- were counted as a second provider. `hide_static_cxx_runtime` had already written that rule in a comment; nothing enforced it one layer up. The binding is recorded now, weak definitions are counted rather than reported, and the count is printed for the reason every denominator in this area is printed. Both were invisible while the same artifact still had 68 real findings on top of them. One test moved from positional to designated initialisation: adding a field to `Conflict` bound the provider list to a bool -- a string literal converts to one, so it compiled and the list silently became empty. * ci: an apt list this job does not use must not fail its setup Two cross-build jobs died in setup with E: Failed to fetch https://dl.google.com/linux/chrome-stable/deb/.../Packages.gz Hash Sum mismatch E: Some index files failed to download. before a single byte was compiled. The runner image carries third-party apt lists that these jobs never install from, and `apt-get update` fails the whole run when any one of them is transiently inconsistent -- so a red that says nothing about the change under test. The lists a job has no use for are removed before the update. What remains is Ubuntu's own, which is what `qemu-user-static`, `wine` and `build-essential` come from. Left alone: the two container-based jobs, whose images carry no third-party lists, and the `|| { ... }` fallback beside the wine dpkg path, which already continues past a failed update. * ci: remove the unused apt sources by content, not by filename The first attempt named `google-chrome.list`, and `apt-get update` failed on the same URL: on ubuntu-24.04 the runner writes deb822 `.sources` files, so the filename was a guess and the guess was wrong. Selected by what the file CONTAINS now. That is the same correction `libs/hostlib.lua` records for library directories: a layout you assume is a layout you are wrong about on some machine. --------- Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com>
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.
What
compat.sycl-runtimeandcompat.cuda-driverbuild their driver farm by enumerating the sentinel's directory instead of linking one hand-writtenlibcuda.so.1, and pinxim:libcuda-host-link@0.0.2-- the version at which that package answers for a set of sonames (openxlings/xim-pkgindex#796).New version keys
2026.09.10for both.compat.cuda-runtimeis untouched: its header states it receives no new versions.Why
libur_adapter_cuda.so.0haslibnvidia-ml.so.1inDT_NEEDEDbesidelibcuda.so.1. The farm did not carry it, an mcpp artifact's private loader consults no host directory, so the adapter did not load, the CUDA back end disappeared, and the program terminated with exit code 134 and no exception text: mcpp#596.Every directory this farm draws from was enumerated except the driver's, and the hand-written half is the half that was wrong. Which driver libraries exist is the sentinel's question; a farm that reads its directory cannot disagree with it.
The criterion, which was green for the whole life of the defect
tests/examples/sycl-runtime/tests/farm.cppasserted three hand-written sonames against a farm of twenty-five members. The two broken members were not among the three.Enumerating the members and
dlopening each is still not enough, and this was measured rather than reasoned:dlopenmeasures the process, whose search path holds more than this package put there. With an OpenCL dependency briefly declared,compat:opencl-runtime's farm suppliedlibnvidia-ml.so.1, so removing NVML from this farm changed nothing and the test passed on a farm that was missing it.The test now reads each member's
DT_NEEDEDdirectly and resolves it against the farm alone, separating three states:Both denominators are printed (
members,walked), because a farm that failed to build enumerates nothing and every per-member assertion then passes.Measured, all three legs on an RTX 4080 host:
libOpenCL.so.1compat.sycl-runtimenow states that it does not serve it. The payload ships an OpenCL adapter,compat:openclwould satisfy it in one line, and that line was written and then removed:compat:opencldepends in turn oncompat:opencl-runtime, so the edge puts the host's proprietary OpenCL driver farm into every SYCL project -- and it is what masked the defect above. A project that wants the back end declarescompat:openclin its own manifest.The omission was unstated before, which is the same condition that let the CUDA one break silently.