conda / conda/menuinst

macOS Intel bundles fail to launch: binary relocation strips /usr/lib/swift RPATH from appkit_launcher

Open
#507 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
50
Forks
49
Avg merge
1d 11h
Merged PRs (30d)
16

Description

## Summary

On Intel (x86_64) macOS, applications whose shortcut uses the Swift `appkit_launcher`
fail to start with:

```
dyld: Library not loaded: @rpath/libswiftCore.dylib
Referenced from: .../Contents/MacOS/
Reason: image not found
```

The cause is **not** in the launcher source. The prebuilt launcher in this repo has the
correct `/usr/lib/swift` RPATH, but **the conda package build (binary relocation) strips
that RPATH**, so the shipped launcher can no longer locate the OS Swift runtime on Intel.

Apple Silicon is unaffected (explained below), which is why this presents as Intel-only.

Discovered via the napari macOS installer (napari 0.7.0 and 0.7.1), but this affects any
Intel macOS bundle built from a conda-forge `menuinst` that uses the appkit launcher.

## Evidence

The `appkit_launcher` links three Swift runtime libs **non-weak** via `@rpath`
(`libswiftCore`, `libswiftos`, `libswiftFoundation`); the rest are weak. So at least
`libswiftCore` must be resolvable or the process never starts.

**1. This repo's prebuilt binary is correct** — it has `/usr/lib/swift`:

```
$ otool -l menuinst/data/appkit_launcher_x86_64 | grep -A2 LC_RPATH
path /usr/lib/swift
path @loader_path
path /Applications/Xcode.app/.../swift-5.5/macosx
```

**2. The conda-forge package has it stripped** (`menuinst-2.5.0-py311h52fad64_1`, osx-64):

```
$ otool -l /site-packages/menuinst/data/appkit_launcher_x86_64 | grep -A2 LC_RPATH
path @loader_path
path @loader_path/../../../..
# /usr/lib/swift and the Xcode toolchain path are gone
```

The same stripping happens to `appkit_launcher_arm64` in both osx-64 and osx-arm64
packages.

**3. Why Intel-only.** On arm64, dyld resolves `@rpath/libswiftCore.dylib` to
`/usr/lib/swift/libswiftCore.dylib` from the dyld shared cache **even without** a
`/usr/lib/swift` RPATH (verified on macOS 26, Apple Silicon — `DYLD_PRINT_LIBRARIES`
shows `/usr/lib/swift/libswiftCore.dylib` loading and no "Library not loaded" error).
x86_64 dyld has no such fallback, so the missing RPATH is fatal on Intel.

**4. Adding the RPATH back fixes the dyld error** (Intel, macOS 13.7.8):

```
install_name_tool -add_rpath /usr/lib/swift "/Contents/MacOS/"
codesign -f -s - "/Contents/MacOS/"
# "Library not loaded: @rpath/libswiftCore.dylib" no longer occurs; the app launches.
```

## Root cause

The launcher binaries under `menuinst/data/` are standalone `.app` *templates* that get
copied verbatim into the shortcuts menuinst creates. They are **not** linked into the
environment and should not be relocated. But conda package relocation (rattler-build /
conda-build) rewrites RPATHs on every Mach-O it finds and strips absolute RPATHs that
point outside the prefix — including the legitimate, stable system path `/usr/lib/swift`.

The recipe already deletes these launchers on Windows and Linux ("Apparently these files
make the post-build linkage analysis crash and we should not need them"), but on macOS
they are required and go through relocation, losing `/usr/lib/swift`.

## Fix

Disable binary relocation for the package in the conda-forge feedstock (menuinst is pure
Python; the launcher templates must keep their original RPATHs):

```yaml
# recipe/recipe.yaml
build:
dynamic_linking:
binary_relocation: false
```

Fix PR: conda-forge/menuinst-feedstock#62
Downstream report: napari/packaging#401

(A more surgical alternative would be `rpath_allowlist: [/usr/lib/swift]`, if that is
confirmed to prevent stripping rather than only suppressing the overlinking warning.)

## Environment

- Failing: macOS 13.7.8 (22H730), Intel (MacBookPro14,1), x86_64; napari 0.7.0 and 0.7.1
- Working (arm64 fallback verified): macOS 26, Apple Silicon
- menuinst 2.5.0 (conda-forge)

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with recipe/recipe.yaml in the conda-forge/menuinst-feedstock and review the referenced fix in conda-forge/menuinst-feedstock#62. Verify that the package build preserves /usr/lib/swift in the appkit_launcher RPATH, then confirm an Intel macOS bundle can launch without the libswiftCore.dylib error.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, swift
Domain
build-system, operating-systems
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.