Skip to content

build: gate SwiftPM build system behind KEYPATH_BUILD_SYSTEM env var#925

Merged
malpern merged 1 commit into
masterfrom
build-system-env-gate
Jun 20, 2026
Merged

build: gate SwiftPM build system behind KEYPATH_BUILD_SYSTEM env var#925
malpern merged 1 commit into
masterfrom
build-system-env-gate

Conversation

@malpern

@malpern malpern commented Jun 20, 2026

Copy link
Copy Markdown
Owner

Why

On macOS 27 beta with Xcode-beta, SwiftPM defaults to the new swiftbuild build system, which:

  • Fails the KeyPath build with error: unable to open dependencies file (...KeyPathCore-primary.d)
  • Writes artifacts to .build/out/... instead of the .build/arm64-apple-macosx/release layout these scripts already assume

The build scripts were written for the classic native build system (see the hardcoded path in build-and-sign.sh). A toolchain flipping the default to swiftbuild silently breaks the pipeline.

What

Gate the build system behind an optional KEYPATH_BUILD_SYSTEM env var in the three scripts that invoke swift build:

  • Scripts/build-and-sign.sh
  • Scripts/build-helper.sh
  • Scripts/quick-deploy.sh

When the var is unset, behavior is unchanged (no --build-system flag passed) — safe for CI and any toolchain that doesn't recognize the flag. On affected machines, set export KEYPATH_BUILD_SYSTEM=native.

Test

  • bash -n passes on all three scripts
  • Full ./build.sh (build → sign → notarize → staple → deploy → launch) verified end-to-end on macOS 27 beta with KEYPATH_BUILD_SYSTEM=native

🤖 Generated with Claude Code

Xcode-beta / macOS 27 beta default SwiftPM to the new "swiftbuild" build
system, which fails with "unable to open dependencies file" and writes
artifacts to .build/out/... instead of the .build/arm64-apple-macosx/release
layout these scripts assume. Allow forcing the system per-machine via
KEYPATH_BUILD_SYSTEM (e.g. =native) while leaving the default behavior
unchanged when the var is unset — safe for CI and toolchains that don't
recognize --build-system.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@claude

claude Bot commented Jun 20, 2026

Copy link
Copy Markdown

Code Review

Overview

This PR adds a KEYPATH_BUILD_SYSTEM env var guard to the three main build scripts so that users on macOS 27 beta (where SwiftPM defaults to the new swiftbuild build system) can opt back into the native build system. The change is entirely backwards-compatible: unset = no flag passed = existing behavior preserved.

The motivation is solid and the risk profile is low.


Issues & Suggestions

1. Two Scripts May Be Missing — run-tests-safe.sh and test-ci-locally.sh

The swiftbuild default affects any swift build invocation, not just release builds. Two non-archive scripts call it without the guard:

  • Scripts/run-tests-safe.sh:429swift build --build-tests --scratch-path "$SCRATCH_PATH" "${MODULE_CACHE_FLAGS[@]}" (the build-tests step in the full gate)
  • Scripts/test-ci-locally.sh:18 — bare swift build

On an affected machine, running ./Scripts/test-full.sh would still fail even after this PR. Worth considering whether these should also get the guard, or at least calling it out in the PR body as a known gap.

2. Inconsistent Implementation Style Across the Three Scripts

build-and-sign.sh and build-helper.sh use inline parameter expansion:

swift build ${KEYPATH_BUILD_SYSTEM:+--build-system "$KEYPATH_BUILD_SYSTEM"} ...

quick-deploy.sh uses an explicit array:

BUILD_SYSTEM_FLAGS=()
if [[ -n "${KEYPATH_BUILD_SYSTEM:-}" ]]; then
    BUILD_SYSTEM_FLAGS=(--build-system "$KEYPATH_BUILD_SYSTEM")
fi
swift build "${BUILD_SYSTEM_FLAGS[@]}" ...

Both are correct. The array form (already used in quick-deploy.sh for MODULE_CACHE_FLAGS) is more readable and safer for future extension (e.g. if you ever need multiple flags). The inline form is terse and works fine for a single-word value, but a reader has to think about whether the inner "$KEYPATH_BUILD_SYSTEM" quoting survives the outer word-split correctly (it does — the quotes inside ${VAR:+word} are interpreted as quoting — but it's subtle). Picking one style for all three would reduce cognitive overhead.

3. Comment in quick-deploy.sh Violates CLAUDE.md Style

CLAUDE.md says: "Default to writing no comments. Only add one when the WHY is non-obvious."

The WHY here IS non-obvious (macOS 27 beta / swiftbuild default flip), so a comment is warranted. But the added comment is 2 lines where 1 would do, and the other two scripts get no comment at all. Either trim to one line and add a similar one-liner to build-and-sign.sh / build-helper.sh for consistency, or drop it if the env var name is self-explanatory enough.

4. KEYPATH_BUILD_SYSTEM Not Documented in CLAUDE.md

The Build & Deploy section of CLAUDE.md documents scripts and flags used in the project. A new contributor or a future agent has no way to discover this workaround without reading git history. A one-line mention like:

# For macOS 27+ beta (swiftbuild default): export KEYPATH_BUILD_SYSTEM=native

under the build section would make this discoverable.


Positives

  • Zero regression risk: the unset-is-unchanged design is the right call for CI and all stable toolchains.
  • Minimal scope: touches exactly the scripts that form the production build pipeline.
  • Good PR description: clearly explains the problem, the fix, and what was tested.
  • End-to-end verified on the affected platform.

Summary

Approve with the following suggestions (in priority order):

  1. (Medium) Check whether run-tests-safe.sh and test-ci-locally.sh also need the guard.
  2. (Low) Align implementation style across all three scripts (prefer the array form).
  3. (Low) Add a one-line note to CLAUDE.md Build section so the env var is discoverable.
  4. (Nit) Trim the quick-deploy.sh comment to one line or add matching one-liners to the other scripts.

@malpern malpern merged commit 00209ee into master Jun 20, 2026
3 checks passed
@malpern malpern deleted the build-system-env-gate branch June 20, 2026 13:58
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