From b7d42258b4f6f8723aaaaa4c9058610900cfba0e Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Fri, 10 Apr 2026 14:53:32 -0700 Subject: [PATCH 1/5] fix: resolve race condition in nsld.sh with parallel linker invocations Xcode can invoke nsld.sh concurrently for different architectures during incremental builds. All invocations shared a single Swift-Modules directory, causing EINVAL errors on APFS when one process deletes the directory while another is writing module.modulemap. Use per-architecture directories (Swift-Modules-$TARGET_ARCH) so parallel invocations no longer collide. Export the arch-specific path into HEADER_SEARCH_PATHS so the metadata generator can still locate the modulemap. --- project-template-ios/internal/nsld.sh | 19 +++++++++++-------- project-template-vision/internal/nsld.sh | 19 +++++++++++-------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/project-template-ios/internal/nsld.sh b/project-template-ios/internal/nsld.sh index 04cd96a5..6b42a322 100755 --- a/project-template-ios/internal/nsld.sh +++ b/project-template-ios/internal/nsld.sh @@ -1,12 +1,6 @@ #!/usr/bin/env bash source ./.build_env_vars.sh -MODULES_DIR="$SRCROOT/internal/Swift-Modules" - -function DELETE_SWIFT_MODULES_DIR() { - rm -rf "$MODULES_DIR" -} - function getArch() { while [[ $# -gt 0 ]] do @@ -24,6 +18,16 @@ function getArch() { done } +# Workaround for ARCH being set to `undefined_arch` here. Extract it from command line arguments. +TARGET_ARCH=$(getArch "$@") + +# Use per-architecture directory to avoid race conditions with parallel linker invocations +MODULES_DIR="$SRCROOT/internal/Swift-Modules-$TARGET_ARCH" + +function DELETE_SWIFT_MODULES_DIR() { + rm -rf "$MODULES_DIR" +} + function GEN_MODULEMAP() { ARCH_ARG=$1 SWIFT_HEADER_DIR=$PER_VARIANT_OBJECT_FILE_DIR/$ARCH_ARG @@ -52,9 +56,8 @@ function GEN_METADATA() { popd } -# Workaround for ARCH being set to `undefined_arch` here. Extract it from command line arguments. -TARGET_ARCH=$(getArch "$@") GEN_MODULEMAP $TARGET_ARCH +export HEADER_SEARCH_PATHS="$HEADER_SEARCH_PATHS $MODULES_DIR" printf "Generating metadata..." GEN_METADATA $TARGET_ARCH DELETE_SWIFT_MODULES_DIR diff --git a/project-template-vision/internal/nsld.sh b/project-template-vision/internal/nsld.sh index 01dbdec9..4b0eb891 100755 --- a/project-template-vision/internal/nsld.sh +++ b/project-template-vision/internal/nsld.sh @@ -1,12 +1,6 @@ #!/usr/bin/env bash source ./.build_env_vars.sh -MODULES_DIR="$SRCROOT/internal/Swift-Modules" - -function DELETE_SWIFT_MODULES_DIR() { - rm -rf "$MODULES_DIR" -} - function getArch() { while [[ $# -gt 0 ]] do @@ -24,6 +18,16 @@ function getArch() { done } +# Workaround for ARCH being set to `undefined_arch` here. Extract it from command line arguments. +TARGET_ARCH=$(getArch "$@") + +# Use per-architecture directory to avoid race conditions with parallel linker invocations +MODULES_DIR="$SRCROOT/internal/Swift-Modules-$TARGET_ARCH" + +function DELETE_SWIFT_MODULES_DIR() { + rm -rf "$MODULES_DIR" +} + function GEN_MODULEMAP() { ARCH_ARG=$1 SWIFT_HEADER_DIR=$PER_VARIANT_OBJECT_FILE_DIR/$ARCH_ARG @@ -52,9 +56,8 @@ function GEN_METADATA() { popd } -# Workaround for ARCH being set to `undefined_arch` here. Extract it from command line arguments. -TARGET_ARCH=$(getArch "$@") GEN_MODULEMAP $TARGET_ARCH +export HEADER_SEARCH_PATHS="$HEADER_SEARCH_PATHS $MODULES_DIR" printf "Generating metadata..." GEN_METADATA $TARGET_ARCH DELETE_SWIFT_MODULES_DIR From fc553a13d8bd4d5219fb36c27120f3c6c878d97c Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Tue, 14 Apr 2026 10:05:54 -0700 Subject: [PATCH 2/5] chore: support spaces in paths Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- project-template-ios/internal/nsld.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project-template-ios/internal/nsld.sh b/project-template-ios/internal/nsld.sh index 6b42a322..ed74266a 100755 --- a/project-template-ios/internal/nsld.sh +++ b/project-template-ios/internal/nsld.sh @@ -57,7 +57,7 @@ function GEN_METADATA() { } GEN_MODULEMAP $TARGET_ARCH -export HEADER_SEARCH_PATHS="$HEADER_SEARCH_PATHS $MODULES_DIR" +export HEADER_SEARCH_PATHS="$HEADER_SEARCH_PATHS \"$MODULES_DIR\"" printf "Generating metadata..." GEN_METADATA $TARGET_ARCH DELETE_SWIFT_MODULES_DIR From 0c81bcdb4b9beb9a22569f56c7047bff12322165 Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Tue, 14 Apr 2026 13:32:10 -0700 Subject: [PATCH 3/5] fix: spaces in paths Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- project-template-vision/internal/nsld.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project-template-vision/internal/nsld.sh b/project-template-vision/internal/nsld.sh index 4b0eb891..d4d76512 100755 --- a/project-template-vision/internal/nsld.sh +++ b/project-template-vision/internal/nsld.sh @@ -57,7 +57,7 @@ function GEN_METADATA() { } GEN_MODULEMAP $TARGET_ARCH -export HEADER_SEARCH_PATHS="$HEADER_SEARCH_PATHS $MODULES_DIR" +export HEADER_SEARCH_PATHS="${HEADER_SEARCH_PATHS:+$HEADER_SEARCH_PATHS }\"$MODULES_DIR\"" printf "Generating metadata..." GEN_METADATA $TARGET_ARCH DELETE_SWIFT_MODULES_DIR From 4db24742b576497924e7280bc98cd14f3fc5fd4d Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Tue, 14 Apr 2026 13:33:33 -0700 Subject: [PATCH 4/5] fix: improve error handling if arch not found Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- project-template-ios/internal/nsld.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/project-template-ios/internal/nsld.sh b/project-template-ios/internal/nsld.sh index ed74266a..e73c7bda 100755 --- a/project-template-ios/internal/nsld.sh +++ b/project-template-ios/internal/nsld.sh @@ -21,6 +21,11 @@ function getArch() { # Workaround for ARCH being set to `undefined_arch` here. Extract it from command line arguments. TARGET_ARCH=$(getArch "$@") +if [ -z "$TARGET_ARCH" ]; then + printf '%s\n' "NSLD: Unable to determine target architecture from arguments: $*" >&2 + exit 1 +fi + # Use per-architecture directory to avoid race conditions with parallel linker invocations MODULES_DIR="$SRCROOT/internal/Swift-Modules-$TARGET_ARCH" From 051c07b13fdbadf95b03efa5c05be70c02225f61 Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Tue, 14 Apr 2026 13:33:49 -0700 Subject: [PATCH 5/5] fix: improve error handling if arch not found Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- project-template-vision/internal/nsld.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/project-template-vision/internal/nsld.sh b/project-template-vision/internal/nsld.sh index d4d76512..e07521a8 100755 --- a/project-template-vision/internal/nsld.sh +++ b/project-template-vision/internal/nsld.sh @@ -21,6 +21,11 @@ function getArch() { # Workaround for ARCH being set to `undefined_arch` here. Extract it from command line arguments. TARGET_ARCH=$(getArch "$@") +if [ -z "$TARGET_ARCH" ]; then + echo "NSLD: Failed to determine target architecture from arguments: $*" >&2 + exit 1 +fi + # Use per-architecture directory to avoid race conditions with parallel linker invocations MODULES_DIR="$SRCROOT/internal/Swift-Modules-$TARGET_ARCH"