From b7d42258b4f6f8723aaaaa4c9058610900cfba0e Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Fri, 10 Apr 2026 14:53:32 -0700 Subject: [PATCH] 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