Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -642,8 +642,7 @@ The internal disk runs nearly full with the owner's own data, so builds go to th
external drive, one folder per project: `/Volumes/Scratch/<project>/`. For example
`dolphin-maps/` holds its checkout, `build/` (DerivedData, archives, result bundles:
`BUILD_DIR` in its scripts), `tours/` (screenshots) and `scratch/` (logs, helpers).
Simulator devices still live on the internal disk (CoreSimulator), so delete a tour's
simulator after use. Never write a project's files into `~/src` loose.
Never write a project's files into `~/src` loose.

Temporary files follow the same rule. Anything a session creates with `mktemp` (a test
run's DerivedData, a build's intermediates) lands in `TMPDIR`, which by default is on
Expand All @@ -654,6 +653,31 @@ its disk is mounted, for every zsh, non-interactive SSH sessions included; with
or the drive unplugged, the system default stays. On this Mac:
`ssh mac 'mkdir -p ~/.config/mac-setup && echo /Volumes/Scratch/tmp > ~/.config/mac-setup/tmpdir'`.

Xcode's DerivedData works the same way: when `~/.config/mac-setup/deriveddata` names a folder
on a mounted disk, `scripts/mac-setup.sh` sets Xcode's `IDECustomDerivedDataLocation` to it,
which every `xcodebuild` without `-derivedDataPath` then uses. On this Mac:
`ssh mac 'echo /Volumes/Scratch/DerivedData > ~/.config/mac-setup/deriveddata'`, then rerun
`scripts/mac-setup.sh`. With the drive unplugged, Xcode builds fail rather than fill the
internal disk.

Simulator devices are on the drive too: `~/Library/Developer/CoreSimulator/Devices` is a
symlink to `/Volumes/Scratch/CoreSimulator/Devices` (moved 2026-10-27, when they held 72 GB
of the internal disk; free space went from 18 GB to 88 GB). CoreSimulator needs two things
from the drive first, each a one-time step **(at the Mac)**, or it cannot create or read a
device there ("device remained in Creating state", Cocoa error 513):
- ownership on: `sudo diskutil enableOwnership /Volumes/Scratch`, then the drive's root back
to the user: `sudo chown "$(whoami)":staff /Volumes/Scratch`;
- Full Disk Access for the simulator service: System Settings > Privacy & Security > Full Disk
Access, add `/Library/Developer/PrivateFrameworks/CoreSimulator.framework/Versions/A/XPCServices/com.apple.CoreSimulator.CoreSimulatorService.xpc`.

Check it with a throwaway set before moving: `xcrun simctl --set /Volumes/Scratch/<dir>
create probe "iPhone 17" <runtime>` must list and boot. Then: `rsync -aH --delete` the folder
across while simulators run, `xcrun simctl shutdown all` and stop
`com.apple.CoreSimulator.CoreSimulatorService`, sync again, require identical listings, swap
in the symlink, and keep the old folder until `xcrun simctl list` shows the same device count.
(`ditto` folds `._` files into extended attributes, so its copy cannot be compared file for
file.) A tour's simulator is still deleted after use.

##### MacBook: Checks

```bash
Expand Down
16 changes: 16 additions & 0 deletions scripts/mac/install.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,22 @@ for t in swift xcodebuild xcrun; do
[ "$got" = "$bin/$t" ] || { echo "mac-setup: a non-interactive zsh finds $t at $got, not $bin/$t" >&2; exit 1; }
done

# Xcode's DerivedData on the disk ~/.config/mac-setup/deriveddata names, when that file exists and the disk is
# mounted; Xcode's default is ~/Library/Developer/Xcode/DerivedData, on the internal disk. It is a user default,
# so it applies to Xcode and to every xcodebuild run without -derivedDataPath.
dd_file=$HOME/.config/mac-setup/deriveddata
if [ -r "$dd_file" ]; then
dd=$(<"$dd_file")
if [ -n "$dd" ] && [ -d "${dd:h}" ] && mkdir -p "$dd"; then
if [ "$(defaults read com.apple.dt.Xcode IDECustomDerivedDataLocation 2>/dev/null)" != "$dd" ]; then
defaults write com.apple.dt.Xcode IDECustomDerivedDataLocation "$dd"
echo "mac-setup: Xcode's DerivedData now goes to $dd"
fi
else
echo "mac-setup: WARNING: $dd_file names $dd, whose disk is not mounted; DerivedData left where it is" >&2
fi
fi

# The pinned Peekaboo app and CLI, and its LaunchAgent (the wrapper above runs its CLI).
if [ "$update_peekaboo" = --update-peekaboo ]; then
/bin/sh "$src/peekaboo-install.sh" --update-running
Expand Down
Loading