94 lines
4.0 KiB
Bash
94 lines
4.0 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
# Single source of truth for the SwiftPM scratch (build) directory, keyed by where the
|
|
# build is running. Prints the flags to append to `swift build/run/test` — empty on the
|
|
# host, a `--scratch-path <dir>` redirect on the macOS VM.
|
|
#
|
|
# Why this exists
|
|
# ---------------
|
|
# SwiftPM and the SwiftBuild backend bake the repository's ABSOLUTE path into the build
|
|
# tree — build.db, the *.yaml manifests, manifest.pif, everything under
|
|
# .build/out/Intermediates.noindex/XCBuildData, and the per-file `.d` dependency lists all
|
|
# contain fully-qualified source paths. That is fine until the SAME checkout is reachable
|
|
# at more than one absolute path, which is exactly our situation:
|
|
#
|
|
# host / sandbox container : /Users/<user>/.nucleic/control/.../trunk
|
|
# per-session macOS VM : same /Users/... path (direct virtiofs mount)
|
|
#
|
|
# Both environments see one physical .build/ inside the shared trunk. The direct mount preserves the
|
|
# same absolute source path, but driving every object file
|
|
# through virtiofs is far slower than the guest's own disk, and SwiftPM binary-target extraction
|
|
# needs filesystem operations virtiofs does not provide.
|
|
#
|
|
# The fix
|
|
# -------
|
|
# Give each mount point its own scratch tree:
|
|
# * Host / container -> the default in-repo .build/ (this script prints nothing, so the
|
|
# existing `swift build` behaviour is untouched — zero risk).
|
|
# * macOS VM (virtiofs) -> a scratch tree on the GUEST's local disk under $HOME, keyed by a
|
|
# hash of the mount path so distinct shares/worktrees never collide.
|
|
#
|
|
# Keep generated artifacts on the filesystem whose semantics and performance they require, while
|
|
# source remains shared at one stable absolute path.
|
|
#
|
|
# Escape hatch: export NUCLEIC_SCRATCH_PATH=/some/dir to force a specific scratch directory
|
|
# (useful for a throwaway build, or to pin the VM tree somewhere other than $HOME).
|
|
#
|
|
# Usage
|
|
# SCRATCH_ARGS="$(bash scripts/lib/build-scratch.sh)" # "" or "--scratch-path /…/<hash>"
|
|
# swift build $SCRATCH_ARGS ... # leave $SCRATCH_ARGS UNQUOTED
|
|
# swift build $SCRATCH_ARGS --show-bin-path # …and pass it to --show-bin-path too
|
|
#
|
|
# Takes the repo/working root as $1 (defaults to $PWD). Emits nothing but the flags on
|
|
# stdout, so it is safe to capture in `$(...)`.
|
|
|
|
set -euo pipefail
|
|
|
|
root="${1:-$PWD}"
|
|
|
|
# Explicit override always wins.
|
|
if [ -n "${NUCLEIC_SCRATCH_PATH:-}" ]; then
|
|
printf -- '--scratch-path %s' "$NUCLEIC_SCRATCH_PATH"
|
|
exit 0
|
|
fi
|
|
|
|
# Resolve symlinks for legacy guests, then classify by the mounted filesystem as well as path.
|
|
# Directly mounted macOS shares keep their /Users/... spelling under pwd -P, so pathname-only
|
|
# detection would incorrectly leave SwiftPM artifacts on virtiofs.
|
|
resolved="$root"
|
|
if cd "$root" 2>/dev/null; then
|
|
resolved="$(pwd -P)"
|
|
fi
|
|
|
|
on_vm_share=false
|
|
case "$resolved" in
|
|
/Volumes/*) on_vm_share=true ;;
|
|
esac
|
|
|
|
# A custom-tagged macOS share is mounted directly at the original workdir. Find any enclosing
|
|
# virtiofs mount point from mount(8)'s "<source> on <path> (virtiofs, ...)" output. Process
|
|
# substitution keeps the flag in this shell rather than a pipeline subshell.
|
|
while IFS= read -r line; do
|
|
case "$line" in
|
|
*" (virtiofs"*)
|
|
mountpoint="${line#* on }"
|
|
mountpoint="${mountpoint% (*}"
|
|
case "$resolved/" in
|
|
"$mountpoint/"*) on_vm_share=true ;;
|
|
esac
|
|
;;
|
|
esac
|
|
done < <(/sbin/mount 2>/dev/null || mount 2>/dev/null || true)
|
|
|
|
if [ "$on_vm_share" = true ]; then
|
|
# Keep build products on the guest's private disk: virtiofs is slower and cannot support all
|
|
# clonefile/framework-symlink operations SwiftPM's binary-target extraction requires. Hash the
|
|
# spelling used by the build so independently mounted worktrees never share a scratch tree.
|
|
if command -v shasum >/dev/null 2>&1; then
|
|
tag="$(printf '%s' "$root" | shasum | cut -c1-12)"
|
|
else
|
|
tag="$(printf '%s' "$root" | sha1sum | cut -c1-12)"
|
|
fi
|
|
printf -- '--scratch-path %s/.nucleic-scratch/%s' "${HOME:-/tmp}" "$tag"
|
|
fi
|