Skip to content

macOS host: run from the Resources directory so staged foreign libraries resolve - #91

Open
turinglambdaai wants to merge 1 commit into
mainfrom
fix/macos-host-working-directory
Open

turinglambdaai wants to merge 1 commit into
mainfrom
fix/macos-host-working-directory

Conversation

@turinglambdaai

Copy link
Copy Markdown
Owner

Problem

A packaged macOS app whose embedded backend pulls in a collection with foreign dependencies dies at backend start:

ffi-lib: could not load foreign library
  path: <cwd>/runtime/lib/plt/generic/exts/ert/r0/libgmp.10.dylib.10

Reproduction: raco rivet new an app, make the backend (require rivet/distribution) (pulls crypto/all → gmp-lib), raco rivet package, launch the .app — the backend fails to load even though the libraries ship inside the bundle.

Root cause

raco ctool --runtime <dir> stages the foreign libraries under <dir>/lib/plt/generic/exts/..., and the embedded runtime resolves that path relative to the process working directory. For a double-clicked .app the working directory is /, so the staged libraries inside Contents/Resources/runtime/lib are never found.

Fix

Set the working directory to the chosen runtime root (Resources for packaged apps, the staged directory for raco rivet dev) before handing the configuration to the embedded runtime — 8 lines in the scaffold host, right where the runtime layout is validated.

Verification

With a packaged app whose backend requires rivet/distribution:

  • without the chdir: backend start fails with the ffi-lib error above (reproduced on macOS 26, arm64, Racket CS 9.3);
  • with the chdir: backend started, and vmmap shows libgmp/libcrypto/libssl mapped from inside Contents/Resources/runtime/lib.

The same fix is shipped and verified in a production app built on Rivet 0.5.0 (payback, turinglambdaai/payback).

…ies resolve

Packaged apps failed at backend start with

  ffi-lib: could not load foreign library
  path: <cwd>/runtime/lib/plt/generic/exts/ert/r0/libgmp.10.dylib.10

whenever the embedded backend pulled in a collection with foreign
dependencies (crypto via rivet/distribution, for example). The libraries
ARE staged — raco ctool places them under runtime/lib — but the embedded
runtime resolves that path relative to the process working directory,
which for a double-clicked .app is '/'.

Set the working directory to the chosen runtime root (Resources for
packaged apps, the staged directory for raco rivet dev) before handing
the configuration to the embedded runtime. Verified with a packaged app
whose backend requires rivet/distribution: without the chdir the backend
dies at module load; with it, backend start succeeds and the libraries
load from inside the bundle.
turinglambdaai added a commit to turinglambdaai/payback that referenced this pull request Sep 30, 2026
The /dev/urandom + dynamic-require split existed because the packaged
app could not resolve foreign libraries; with the host running from its
Resources directory (PR turinglambdaai/rivet#91) the standard idiom
loads fine in the packaged artifact, verified end to end.

This branch has not been deployed

No deployments
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.

1 participant