From c41035f7d801a45b337efa24e3052f069ff6ef56 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Sun, 27 Sep 2026 21:18:18 +0300 Subject: [PATCH] guix: mount the macOS SDK at a fixed path in the container Every container share whose value reaches the compiler is mapped to a fixed path: `--share="$PWD"=/dash` and `--share="$DISTSRC_BASE"=/distsrc-base` exist precisely so the build host's layout cannot end up in the outputs. SDK_PATH was the exception. It was shared with no target, so the SDK sat at the builder's own host path inside the container, and depends hands that path to the compiler as `-isysroot$(OSX_SDK)` (depends/hosts/darwin.mk). Anything that records the name of an SDK header therefore embedded a builder-specific path. What still does so is the debug output. dsymutil writes the include directory of every header it collected, so the darwin *-debug.tar.gz carries the SDK path tens of thousands of times over, and two builders who keep their SDK in different places do not agree on that archive. Resolve the SDK's parent directory host-side in the loop that already checks the SDK exists, and mount it at /macos-sdk, so the location on the build host cannot reach any output. Note this does not change an attested artifact. guix-attest filters apple-darwin-debug.tar out of both noncodesigned.SHA256SUMS and all.SHA256SUMS, and doc/release-process.md does not ship it, so nothing a release verifies depends on the SDK's location once the source_location leak it used to carry is fixed separately. This is reproducibility hygiene for a developer artifact, and it closes the one compiler-facing share that was not normalised. Resolving the path rather than testing whether SDK_PATH is set is what makes the default and an explicit setting converge: contrib/containers/guix/scripts/ guix-start exports SDK_PATH as "${WORKSPACE_PATH}/depends/SDKs", so the value already differed between builders who use the containerised workflow from different directories. Normalising only the explicitly-set case would have left two hash classes and fixed nothing. The share is made whenever HOSTS contains a darwin host, for every host's container in that run, which is what it did before this mapping existed. Only darwin's depends reads SDK_PATH. A build with no darwin host shares nothing, even if SDK_PATH happens to be exported, which it was not guaranteed to do before. Co-Authored-By: Claude Opus 5 --- contrib/guix/README.md | 4 ++++ contrib/guix/guix-build | 21 +++++++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/contrib/guix/README.md b/contrib/guix/README.md index 602ab1f2ea86..750d674034b8 100644 --- a/contrib/guix/README.md +++ b/contrib/guix/README.md @@ -251,6 +251,10 @@ details. the actual SDK (e.g. `SDK_PATH=$HOME/Downloads/macOS-SDKs` instead of `$HOME/Downloads/macOS-SDKs/Xcode-26.1.1-17B100-extracted-SDK-with-libcxx-headers`). + Where you keep the SDK does not affect the build outputs: the directory is + mounted at a fixed path inside the container. Its contents still have to match + what other builders use, as before. + The path that this environment variable points to **must be a directory**, and **NOT a symlink to a directory**. diff --git a/contrib/guix/guix-build b/contrib/guix/guix-build index 80b719eb29d8..c57764c72f51 100755 --- a/contrib/guix/guix-build +++ b/contrib/guix/guix-build @@ -137,6 +137,7 @@ for host in $HOSTS; do OSX_SDK="$(make -C "${PWD}/depends" --no-print-directory HOST="$host" print-OSX_SDK | sed 's@^[^=]\+=@@g')" if [ -e "$OSX_SDK" ]; then echo "Found macOS SDK at '${OSX_SDK}', using..." + HOST_SDK_PATH="$(make -C "${PWD}/depends" --no-print-directory HOST="$host" print-SDK_PATH | sed 's@^[^=]\+=@@g')" break else echo "macOS SDK does not exist at '${OSX_SDK}', please place the extracted, untarred SDK there to perform darwin builds, or define SDK_PATH environment variable. Exiting..." @@ -422,6 +423,22 @@ EOF # make the downloaded depends sources available to it. The sources # should have been downloaded prior to this invocation. # + # ${HOST_SDK_PATH:+--share="$HOST_SDK_PATH"=/macos-sdk} + # + # maps the directory holding the extracted macOS SDK + # to /macos-sdk inside the isolated container + # + # For the same reason we map $PWD to a fixed path: the SDK's location + # on the build host would otherwise be a source of irreproducibility. + # depends passes it to the compiler as -isysroot, so it reaches the + # outputs, and builders who keep their SDK in different places would + # not agree on the darwin hashes. '/macos-sdk' was chosen arbitrarily. + # + # Set whenever HOSTS contains a darwin host, so the share is made for + # every host's container in that run, as it was before this mapping + # existed. Only darwin's depends reads SDK_PATH, so the others ignore + # it. + # # --keep-failed keep build tree of failed builds # # When builds of the Guix environment itself (not Dash Core) @@ -449,7 +466,7 @@ EOF --expose="$(git rev-parse --git-common-dir)" \ ${SOURCES_PATH:+--share="$SOURCES_PATH"} \ ${BASE_CACHE:+--share="$BASE_CACHE"} \ - ${SDK_PATH:+--share="$SDK_PATH"} \ + ${HOST_SDK_PATH:+--share="$HOST_SDK_PATH"=/macos-sdk} \ --cores="$JOBS" \ --keep-failed \ --fallback \ @@ -465,7 +482,7 @@ EOF ${V:+V=1} \ ${SOURCES_PATH:+SOURCES_PATH="$SOURCES_PATH"} \ ${BASE_CACHE:+BASE_CACHE="$BASE_CACHE"} \ - ${SDK_PATH:+SDK_PATH="$SDK_PATH"} \ + ${HOST_SDK_PATH:+SDK_PATH=/macos-sdk} \ DISTSRC="$(DISTSRC_BASE=/distsrc-base && distsrc_for_host "$HOST")" \ OUTDIR="$(OUTDIR_BASE=/outdir-base && outdir_for_host "$HOST")" \ DIST_ARCHIVE_BASE=/outdir-base/dist-archive \