vulkan_devices() flattened every apiVersion and check_vulkan() accepted any
timelineSemaphore = true, so a host with an old fast device and a new device
without timeline semaphores could pass without a usable device. Each GPUn
block is now one record, and one device must report both.
The full dump supplies the features and --summary the versions, matched by
GPU index. A dump without feature sections still gets the version check, and a
summary that lists no device is a required failure.
Adds three tests: a second device satisfies both, requirements are not
combined across devices, and no reported device.
- an installed vulkaninfo that errors or times out is now a required failure
with an actionable line; a missing one still only warns
- llvm_tools runs llvm-config with a 30 second timeout and reports it instead
of hanging the preflight or the build
- RCLOL_PREFLIGHT_SOURCE overrides the prepared checkout, so the tests never
scan (or fail on) a real build/darling-src
Adds four tests: missing vs broken vulkaninfo, and the two timeout paths.
setup failures reported in #137, #138 and #143 happened only after the long
fetch/build or at Riot startup. scripts/preflight.py now runs from
scripts/build.sh (before configure.py, so an old interpreter gets this message
and not a traceback) and from scripts/install-runtime.sh, and checks the host
once:
- python 3.10+, cmake 3.20+ (the bundled indium CMakeLists requires it),
git-lfs 2.13+, kernel 5.14+ and LLVM 16+ exit nonzero with one actionable
line each. RCLOL_SKIP_PREFLIGHT=1 bypasses the gate.
- llvm-objdump and llvm-nm are required, and unresolved names are explained.
- Vulkan 1.3 and timeline semaphores are required when vulkaninfo is
installed; they only warn when it is not, because a missing tool does not
mean a missing driver.
- the X display is probed with xdpyinfo in the environment Darling inherits.
It only warns: a build does not need a display.
- a prepared build/darling-src is scanned for small .dylib/.a/.so/.o files
that still contain Git LFS pointer text, which links but crashes the guest.
- --json prints the same report for the diagnostic tools.
The installers no longer call hashlib.file_digest (Python 3.11+), so Ubuntu
22.04's Python 3.10 works instead of failing after the overlays are built
(#137). A streaming tools/file_digest.py replaces it.
LLVM command line tools are resolved by tools/llvm_tools.py: an unversioned
name on PATH first, then the highest llvm-<tool>-<N>, then llvm-config
--bindir. Debian/Ubuntu install llvm-objdump and llvm-nm only under
/usr/lib/llvm-<N>/bin, which broke the runtime validation (#138). Six tools
now use it. The LLVM 16 floor also stops the LLVM 15 runtime abort from #139
before anything is built.
Two test helpers used APIs added after Python 3.10; they are shimmed so the
same suite runs on 3.10, 3.11 and 3.14.
Adds tests/test_preflight.py (24 tests, fake host tools only).
Moving the checkout to another path or account left three kinds of stale
state behind (issue #142):
- configure.py kept the previous home's default prefix. A saved prefix that
was exactly <previous home>/.darling now follows the current host home; a
user-chosen prefix is kept, and one inside the previous home is reported
with the --prefix escape hatch.
- build/runtime/build was an absolute symlink, so it dangled after a move and
the "not link.exists()" guard treated the dangling entry as absent. It is
now a relative link and an absolute or dangling leftover is replaced. A
real directory at that path is reported and left untouched.
- A CMake cache generated for another source directory made the build fail
with permission errors against the old path. configure.py now reports the
cache and the exact directory to remove, and never deletes it itself.
Patches are rendered at prepare.py time, so the report also points at the
re-render path. Documents the moved-checkout steps and the opt-in RenderDoc
diagnostic, which still expects files no setup script creates.
Adds 7 tests to tests/test_setup_portability.py.
Signed-off-by: zero <zero@localhost>
Children whose parent dies are reparented to the guest launchd, and its job
manager only reaps PIDs it has a job record for, so every leftover mldr/CEF
process from a killed client tree stayed a zombie until shutdown. Reap zombies
that launchd owns but does not track on a 5 second timer; tracked jobs keep
their exit status for job_reap(). proc_listpids() is not implemented in Darling
yet, so the scan enumerates the guest PID namespace through /proc.
recover-stale-client now signals the stale tree deepest-first so a live parent
can still reap its own children, and prepare.py repairs interrupted checkouts
and missing Git LFS objects instead of publishing pointer text as a library.
Use a project-owned identity for the visible desktop entry while keeping the existing binary, package and window-matching identifiers working. The helper now copies the project's original icon instead of extracting one from the client, and the old game-named entry and icons it created are removed. Extend the packaging check to assert the neutral fields.
When install-runtime.sh creates the prefix (first-time setup, regular or
Nix), it now runs configure-darling-platform.py --provision --write once
the runtime is stopped, so each new install gets its own synthetic serial,
MLB, UUID and ROM. A prefix counts as new the same way Darling decides it:
the directory did not exist before the first `darling shell`. Existing
prefixes keep their identity on reinstall and update.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Older setups shipped serial C02ZL0GVMD6N and UUID
6F3B2A1E-8C4D-4E5F-9A7B-1D2C3E4F5A6B to every install. After installing,
update.sh now runs configure-darling-platform.py --replace-known-defaults,
which provisions the prefix only when its saved identity still has one of
those values. Other custom values (imported serials/UUIDs, model, board,
manufacturer, ROM, MLB) are kept; prefixes with no saved identity or only
custom values are not touched.
provision() also drops a standalone system-id or provisioning_UDID derived
from the shared UUID instead of keeping it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Stage a cross-filesystem copy in a private directory instead of deleting a
pre-existing PATH.partial, reject destinations inside the overlay work
directory, save the new path before deleting the old prefix, and verify that
the target keeps user.* xattrs before and after copying. Add tests.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
The prefix holds the installed clients and game (about 40 GB). The Nix
launcher always exported DPREFIX=${DPREFIX:-~/.darling}, so the prefix saved
in build/config.json was never used and the only way to move it was an
environment variable in every launch context.
- The launcher uses DPREFIX if set, then the saved prefix, then ~/.darling.
- darling-lol --set-prefix PATH runs scripts/nix-prefix.py in the namespace,
whose root owns the prefix files, so cp -a keeps their owners and xattrs.
It renames the prefix when possible; across filesystems it copies to
PATH.partial and removes the old prefix and its overlay work directory
only after the copy completes. A PATH that already holds a Darling prefix
is used as it is. It refuses non-empty directories that are not prefixes,
nested paths and paths with commas or colons (overlayfs separators), then
saves the path with configure.py --prefix.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
After the clients quit, the session kept Darling running: Riot and League
crash handlers never exit under Darling, and the idle check counted them as
clients. Ctrl+C or closing the terminal killed bubblewrap, whose
--die-with-parent then killed nix-lifecycle.py before it could shut Darling
down, which left a live server marker behind.
- nix-idle.py ignores crash handlers when deciding whether a client still
uses the prefix.
- The launcher starts bubblewrap with INT, QUIT, HUP and TERM ignored, and
env restores them inside. The supervisor turns them into a stop request.
- nix-lifecycle.py polls for a signal or stop request and then shuts Darling
down without waiting for clients. It stops retrying a failed shutdown once
the server is gone, and waits for or kills its own command afterwards.
- darling-lol --stop makes the stop request and waits for the session. If
the session does not exit within 30 seconds, or no session holds the lock,
it kills the prefix's darlingserver and launchd like darling shutdown,
after checking that the marker PID is this user's darlingserver for this
prefix.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Security reads the system trust domain from
/System/Library/Keychains/SystemRootCertificates.keychain and
SystemTrustSettings.plist (TrustSettingsSchema.h). Darling ships neither, so
SecTrustSettingsCopyCertificates(kSecTrustSettingsDomainSystem) returns
errSecNoTrustSettings (-25263); Chromium's known_roots_mac and Riot's
CertBundle then report that they cannot read the system roots.
ensure-darling-root-certificates.py parses each host root with a minimal DER
walker and writes the trust record keyed by the uppercase SHA-1, with the
encoded issuer Name, the serial INTEGER's content octets, modDate and an
empty (unrestricted) trustSettings array. The keychain is built with the
guest security tool in one darling shell, in a private temporary directory,
and published from inside the guest so a running Darling sees it, falling
back to the host when the guest cannot write the directory. A digest stamp
skips later runs without starting Darling. The launcher warns and continues
on failure; install-runtime.sh runs it before stopping Darling.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Riot's CDN has no live.lan.zip, live.las.zip or live.oce.zip (HTTP 404);
the installers are published as la1, la2 and oc1. installer.sh now maps
the friendly names to those codes and accepts the codes directly.
Refs #30
Co-Authored-By: Claude Opus 5.5 <[email protected]>
After a pull that changed a patch, prepare.py stopped: the patch neither
applied nor reverse-applied to a tree holding its earlier version. Now
it looks for the earlier version applied in that component -- the copy
it records in build/applied-patches, or a version from this
repository's history -- reverts exactly it and applies the new one.
It never resets a repository; when nothing matches it stops and names
the repository with other edits, and it restores the earlier version
if the new one does not apply.
scripts/update.sh runs build.sh, the base install and
install-runtime.sh, and refuses to start while a Riot Client or League
process is open, since the install steps stop Darling.
Checked on a sandbox Indium checkout holding the previous patch: the
result matches a clean apply, a second run is a no-op, an unrelated
local edit survives and a conflicting one stops with the error.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Riot's installer puts the client in /Users/Shared/Riot Games and exits;
its LaunchServices hand-off to that client does not start it under
Darling, so the window just closes. The installer wrapper now launches
the installed client itself, and the runner links it to
/Applications/Riot Client.app when that link is missing.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The pinned src/external/swift/.lfsconfig points lfs.url at the retired
git-lfs.darlinghq.org, so a fresh `git submodule update --init --recursive`
blocks with no output right after src/external/sqlite is checked out: swift is
the next submodule in sorted order and its checkout waits on that host.
Override lfs.url to GitHub's endpoint, which still serves the objects (verified
44 objects / 16 MB, real Mach-O dylibs), and print explicit submodule progress so
the last completed submodule is not mistaken for the stalled one.
Preserve floating-point arguments in GL resolvers, retain presentation across differently sized windows, export AppKit click and URL fixes, and guard nullable LaunchServices errors. Include compiler/build and installer corrections for the new PC.
Reuse server receive buffers with descriptor-safe exception cleanup and avoid disabled debug-string allocation. Translate Darwin free/reuse memory hints, add atomic server/library installers with separate user-owned memory backups, and preserve active processes until a manual namespace restart.
Remove automatic inspectors, client helpers and forced unlimited UI frames from normal launches. Retain historical hooks with offline mocks and document their exclusion, unresolved installer handoff, activation requirements and unmeasured FPS/RAM benefits.
Validation: all 29 pinned patches apply; all 461 exported source files match; host receive and memory checks, launcher and JavaScript mocks, syntax and documentation-link checks pass. No live client/game was controlled or restarted.