Skip to content

compat.sycl-runtime: a SYCL artifact can reach its runtime - #354

Merged
Sunrisepeak merged 2 commits into
mainfrom
feat/heterogeneous-round4
Sep 5, 2026
Merged

compat.sycl-runtime: a SYCL artifact can reach its runtime#354
Sunrisepeak merged 2 commits into
mainfrom
feat/heterogeneous-round4

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

An mcpp binary on Linux runs under mcpp's own loader, so a soname that is not
on its runtime search path is not found at all. A program whose device half was
compiled by the xim:dpcpp payload links -lsycl, which the rule package
satisfies at link time from the payload's own directory, and then fails mcpp's
runtime closure check:

libsycl.so.9 not found on the search path this artifact will actually use.
Its PT_INTERP is a private loader, so the host's /usr/lib is NOT consulted

This is the same shape compat.cuda-driver and compat.vulkan-runtime have, for
the same class of library: one a program reaches through the loader rather than
through a header. It declares the payload as an install-time edge, reads the
directory back, and links the versioned sonames into a package-owned farm that
runtime.library_dirs puts on the artifact's search path.

Three things it does that the CUDA adapter does not, each measured rather than
assumed:

EVERY VERSIONED SONAME, NOT JUST libsycl. SYCL's device support is a chain of
dlopens -- libsycl.so.9 loads libur_loader.so.0, which loads one
libur_adapter_*.so.0 per back end, and those need libumf.so.1. The loader
finds an adapter beside ITSELF, and $ORIGIN is the symlink's directory rather
than the target's, so a farm holding libsycl.so.9 alone loads and then
enumerates nothing -- the failure that reads as "this machine has no GPU".

THE C++ RUNTIME IS FARMED, WHICH compat.cudart DELIBERATELY DOES NOT DO. Its
comment says libstdc++ is already loaded on the executable's own behalf by the
time the component asks, and for a CUDA program that is true. It is not true
here: libsycl.so.9 needs libstdc++ itself and an mcpp artifact links libc++,
so unless the consumer named libstdc++ on its own link line nothing has loaded
it and the farm's RUNPATH is the only place the loader looks. Measured, before
the fix: FAIL libsycl.so.9: libstdc++.so.6: cannot open shared object file.
Farming it is safe for the reason farming libc would not be -- there is exactly
one libstdc++ in this ecosystem and a consumer that also links it resolves the
same file under the same soname.

THE STUB SEARCH STARTS FROM THE PAYLOAD, NOT FROM THE ENVIRONMENT. This package
installs into a PROJECT-LOCAL store while its payload resolves from the shared
registry, and $HOME may be remapped, so install_dir's grandparent holds this
package alone. With the environment-derived roots alone the search found
nothing and the program died on libdl.so.2 with a farm that otherwise looked
complete. The payload's own directory cannot be wrong: glibc is its sibling by
construction.

Verified by a new workspace member, tests/examples/sycl-runtime, which
asserts what this package is responsible for and not what the machine answers:
the runtime loads by soname and carries __sycl_register_lib, and so do
libur_loader.so.0 and libumf.so.1 -- the leaf that separates "the farm has
libsycl" from "the farm has the chain". Which devices exist is the machine's
answer and is not asserted.

speak-agent and others added 2 commits September 6, 2026 05:13
An mcpp binary on Linux runs under mcpp's own loader, so a soname that is not
on its runtime search path is not found at all. A program whose device half was
compiled by the `xim:dpcpp` payload links `-lsycl`, which the rule package
satisfies at link time from the payload's own directory, and then fails mcpp's
runtime closure check:

  libsycl.so.9 not found on the search path this artifact will actually use.
  Its PT_INTERP is a private loader, so the host's /usr/lib is NOT consulted

This is the same shape compat.cuda-driver and compat.vulkan-runtime have, for
the same class of library: one a program reaches through the loader rather than
through a header. It declares the payload as an install-time edge, reads the
directory back, and links the versioned sonames into a package-owned farm that
`runtime.library_dirs` puts on the artifact's search path.

Three things it does that the CUDA adapter does not, each measured rather than
assumed:

EVERY VERSIONED SONAME, NOT JUST libsycl. SYCL's device support is a chain of
dlopens -- `libsycl.so.9` loads `libur_loader.so.0`, which loads one
`libur_adapter_*.so.0` per back end, and those need `libumf.so.1`. The loader
finds an adapter beside ITSELF, and `$ORIGIN` is the symlink's directory rather
than the target's, so a farm holding `libsycl.so.9` alone loads and then
enumerates nothing -- the failure that reads as "this machine has no GPU".

THE C++ RUNTIME IS FARMED, WHICH compat.cudart DELIBERATELY DOES NOT DO. Its
comment says libstdc++ is already loaded on the executable's own behalf by the
time the component asks, and for a CUDA program that is true. It is not true
here: `libsycl.so.9` needs libstdc++ itself and an mcpp artifact links libc++,
so unless the consumer named libstdc++ on its own link line nothing has loaded
it and the farm's RUNPATH is the only place the loader looks. Measured, before
the fix: `FAIL libsycl.so.9: libstdc++.so.6: cannot open shared object file`.
Farming it is safe for the reason farming libc would not be -- there is exactly
one libstdc++ in this ecosystem and a consumer that also links it resolves the
same file under the same soname.

THE STUB SEARCH STARTS FROM THE PAYLOAD, NOT FROM THE ENVIRONMENT. This package
installs into a PROJECT-LOCAL store while its payload resolves from the shared
registry, and $HOME may be remapped, so `install_dir`'s grandparent holds this
package alone. With the environment-derived roots alone the search found
nothing and the program died on `libdl.so.2` with a farm that otherwise looked
complete. The payload's own directory cannot be wrong: glibc is its sibling by
construction.

Verified by a new workspace member, `tests/examples/sycl-runtime`, which
asserts what this package is responsible for and not what the machine answers:
the runtime loads by soname and carries `__sycl_register_lib`, and so do
`libur_loader.so.0` and `libumf.so.1` -- the leaf that separates "the farm has
libsycl" from "the farm has the chain". Which devices exist is the machine's
answer and is not asserted.
…ine had it

CI reported what this machine could not: `libur_loader.so.0` needs
`libz.so.1`, the payload does not carry it, and the farm's RUNPATH is the only
place the loader looks. On a machine with zlib installed for unrelated reasons
the omission was invisible; on a fresh runner every library in the chain failed
on it.

`xim:zlib` is declared and farmed, and the stub search now tries `lib/` as well
as `lib64/` because zlib ships under the former.
@Sunrisepeak
Sunrisepeak merged commit e17fc88 into main Sep 5, 2026
11 checks passed
@Sunrisepeak
Sunrisepeak deleted the feat/heterogeneous-round4 branch September 5, 2026 21:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants