Skip to content

Commit acaae88

Browse files
committed
feat(compat.sycl-runtime): the OpenCL adapter the payload ships is served
The package declared it did not serve `libOpenCL.so.1`, and that decision was made from a real measurement and was still wrong. WHAT THE MEASUREMENT SAID. Declaring `compat:opencl` made the farm test pass with every member loading -- and pass with `libnvidia-ml.so.1` REMOVED from the farm. `compat:opencl` depends on `compat:opencl-runtime`, whose farm mirrors the host's NVIDIA OpenCL family and therefore carries NVML, so the new dependency was satisfying the need the rest of this change exists to satisfy, and the criterion could no longer fail. WHY THAT REASON EXPIRED. The masking was a property of a criterion that measured the PROCESS. `tests/farm.cpp` was rewritten -- because of that very measurement -- to read each member's DT_NEEDED against the farm alone. Once nothing on the search path can answer for the farm, the only objection left was the size of the surface, and a back end whose adapter the payload ships is not something a runtime adapter should leave permanently unreachable. Measured with the edge declared: the farm test passes, and with NVML removed it still fails naming `libur_adapter_cuda.so.0`. The decision is reversible because the criterion is no longer maskable. `libOpenCL.so.1` stays named in the test with its meaning changed: not "this package does not serve it" but "a declared dependency of this package provides it". mcpp deploys `compat:opencl`'s shared library beside the consumer's executable and `$ORIGIN` finds it there. Everything not on that short list must be in the farm, which is what keeps the self-sufficiency assertion exact without reopening the process to answer for it.
1 parent af00391 commit acaae88

2 files changed

Lines changed: 46 additions & 32 deletions

File tree

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

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -128,29 +128,34 @@ package = {
128128
c_standard = "c11",
129129
sources = { "mcpp_generated/sycl_runtime_empty.c" },
130130
targets = { ["sycl_runtime"] = { kind = "lib" } },
131-
-- THE OTHER BACK END THE PAYLOAD SHIPS AN ADAPTER FOR IS DELIBERATELY
132-
-- NOT SERVED HERE, and saying so is the point: it was unstated before,
133-
-- which is the same condition that let the CUDA one break silently.
131+
-- THE OTHER BACK END THE PAYLOAD SHIPS AN ADAPTER FOR.
134132
--
135-
-- `libur_adapter_opencl.so.0` has `libOpenCL.so.1` in its DT_NEEDED and
136-
-- nothing on an mcpp artifact's search path provides it, so the OpenCL
137-
-- back end of a SYCL program does not load. `compat:opencl` builds that
138-
-- loader and would fix it in one line here.
133+
-- `libur_adapter_opencl.so.0` has `libOpenCL.so.1` in its DT_NEEDED,
134+
-- and nothing on an mcpp artifact's search path provided it, so the
135+
-- OpenCL back end of a SYCL program did not load. That is the same
136+
-- defect as the missing driver soname one API over, and it was
137+
-- invisible for the same reason: an adapter that fails to load is
138+
-- reported by nothing.
139139
--
140-
-- MEASURED REASON FOR NOT WRITING THAT LINE. `compat:opencl` depends in
141-
-- turn on `compat:opencl-runtime`, a farm of the HOST's proprietary
142-
-- OpenCL driver family, so the edge would put a machine-specific vendor
143-
-- surface into every SYCL project. It also carries `libnvidia-ml.so.1`,
144-
-- and with the edge declared it satisfied the CUDA adapter's need for
145-
-- NVML -- which made the farm below look correct while it was not. A
146-
-- dependency that hides the defect the package next to it is fixing is
147-
-- the wrong dependency.
140+
-- A DEPENDENCY RATHER THAN A FARM ENTRY. Unlike the driver, this one is
141+
-- not a host file that may not be redistributed: `compat:opencl` builds
142+
-- the Khronos ICD loader from source with the canonical soname, and it
143+
-- reaches the machine's own drivers through `compat:opencl-runtime`.
144+
-- Farming a copy here would be a second answer to a question this index
145+
-- already answers.
148146
--
149-
-- A project that wants OpenCL devices from SYCL writes
150-
-- `[dependencies.compat] opencl = "2026.05.29"` in its own manifest,
151-
-- where the vendor surface is its choice. `tests/farm.cpp` records the
152-
-- adapter as expected-unserved so the omission stays visible.
153-
deps = {},
147+
-- WHAT WAS BRIEFLY WRITTEN HERE INSTEAD, AND WHY IT WAS WRONG. A draft
148+
-- declared the adapter unserved, on the ground that `compat:opencl`
149+
-- drags a vendor surface in and that its farm -- which carries
150+
-- `libnvidia-ml.so.1` -- made this package's own farm look correct
151+
-- while it was missing NVML. The second half was true of a criterion
152+
-- that measured the PROCESS: `tests/farm.cpp` now reads each member's
153+
-- DT_NEEDED against this farm alone, so nothing else on the search path
154+
-- can hide a gap in it. With that fixed, the remaining objection was
155+
-- only the size of the surface, and a back end the payload ships an
156+
-- adapter for is not something a runtime adapter should leave
157+
-- unreachable.
158+
deps = { ["compat.opencl"] = "2026.05.29" },
154159
runtime = {
155160
library_dirs = { "mcpp_generated/sycl_runtime/lib" },
156161
capabilities = { "sycl.runtime" },

‎tests/examples/sycl-runtime/tests/farm.cpp‎

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,15 @@
4444
// consumer. The entry is present, so the package did its part; the target
4545
// is the machine's answer.
4646
//
47-
// * A SONAME this package states it does not serve. Today that is
48-
// `libOpenCL.so.1`: the payload ships an OpenCL adapter, and serving it
49-
// would mean depending on `compat:opencl`, which drags the host's
50-
// proprietary OpenCL driver farm into every SYCL project. The recipe
51-
// records that decision; this list is the half that makes it visible, and
52-
// a project that wants the back end declares `compat:opencl` itself.
47+
// * A SONAME this package gets from a DECLARED DEPENDENCY rather than from
48+
// its own farm. Today that is `libOpenCL.so.1`: `compat:sycl-runtime`
49+
// depends on `compat:opencl`, whose shared library is deployed beside the
50+
// consumer's executable and is found there through `$ORIGIN`. The name is
51+
// listed here rather than resolved through the process, because resolving
52+
// through the process is what let another farm answer for
53+
// `libnvidia-ml.so.1` and hide the gap this test exists to catch. A short
54+
// list that a reader can check is the price of a criterion that cannot be
55+
// masked.
5356
//
5457
// Which devices exist is deliberately NOT asserted: that is the machine's
5558
// answer, not this package's.
@@ -83,9 +86,14 @@ bool provided_by_the_artifact(const std::string& soname) {
8386
|| soname.rfind("ld-linux", 0) == 0;
8487
}
8588

86-
// Stated, not served. See the header for the reason and for what a project
87-
// that wants it writes instead.
88-
bool declared_unserved(const std::string& soname) {
89+
// Served by a declared dependency of this package, not by its farm.
90+
//
91+
// `compat:opencl` builds the Khronos ICD loader with the canonical soname and
92+
// mcpp deploys it beside the consumer's executable, where `$ORIGIN` finds it.
93+
// Naming it here keeps the farm's self-sufficiency assertion exact: everything
94+
// NOT on this list must be in the farm, and no other directory on the search
95+
// path can answer for it.
96+
bool served_by_a_declared_dependency(const std::string& soname) {
8997
return soname == "libOpenCL.so.1";
9098
}
9199

@@ -258,9 +266,10 @@ int main() {
258266
name.c_str(), soname.c_str());
259267
continue;
260268
}
261-
if (declared_unserved(soname)) {
262-
std::printf("note %s needs %s, which this package states it "
263-
"does not serve\n", name.c_str(), soname.c_str());
269+
if (served_by_a_declared_dependency(soname)) {
270+
std::printf("note %s needs %s, which a declared dependency of "
271+
"this package provides\n",
272+
name.c_str(), soname.c_str());
264273
continue;
265274
}
266275
std::printf("FAIL %s needs %s, which the farm does not carry\n",

0 commit comments

Comments
 (0)