Files
nixpkgs/pkgs/development/compilers/swift/wrapper/wrapper.sh
Emily 809f7d037c swiftPackages.swift{,-unwrapped,-driver}: ignore $NIX_CC
Swift needs Clang to link with. The linker patch breaks linking
when using Swift with a GCC‐based standard environment.

Similarly, the internal Clang headers in the resource directory are
coupled to the corresponding version of Clang. The resource root patch
caused Swift’s Clang to use the resource directory from the version
of Clang used in the build environment, which is only compatible if
the versions match.

Instead, hard‐code the Clang path in the patches and wrappers.
2025-09-02 04:09:46 +01:00

311 lines
9.6 KiB
Bash

#! @shell@
# NOTE: This wrapper is derived from cc-wrapper.sh, and is hopefully somewhat
# diffable with the original, so changes can be merged if necessary.
set -eu -o pipefail +o posix
shopt -s nullglob
if (( "${NIX_DEBUG:-0}" >= 7 )); then
set -x
fi
cc_wrapper="@cc_wrapper@"
source $cc_wrapper/nix-support/utils.bash
source $cc_wrapper/nix-support/darwin-sdk-setup.bash
expandResponseParams "$@"
# Check if we should wrap this Swift invocation at all, and how. Specifically,
# there are some internal tools we don't wrap, plus swift-frontend doesn't link
# and doesn't understand linker flags. This follows logic in
# `lib/DriverTool/driver.cpp`.
prog=@prog@
progName="$(basename "$prog")"
firstArg="${params[0]:-}"
isFrontend=0
isRepl=0
# These checks follow `shouldRunAsSubcommand`.
if [[ "$progName" == swift ]]; then
case "$firstArg" in
"" | -* | *.* | */* | repl)
;;
*)
exec "swift-$firstArg" "${params[@]:1}"
;;
esac
fi
# These checks follow the first part of `run_driver`.
#
# NOTE: The original function short-circuits, but we can't here, because both
# paths must be wrapped. So we use an 'isFrontend' flag instead.
case "$firstArg" in
-frontend)
isFrontend=1
# Ensure this stays the first argument.
params=( "${params[@]:1}" )
extraBefore+=( "-frontend" )
;;
-modulewrap)
# Don't wrap this integrated tool.
exec "$prog" "${params[@]}"
;;
repl)
isRepl=1
params=( "${params[@]:1}" )
;;
--driver-mode=*)
;;
*)
if [[ "$progName" == swift-frontend ]]; then
isFrontend=1
fi
;;
esac
# For many tasks, Swift reinvokes swift-driver, the new driver implementation
# written in Swift. It needs some help finding the executable, though, and
# reimplementing the logic here is little effort. These checks follow
# `shouldDisallowNewDriver`.
if [[
$isFrontend = 0 &&
-n "@swiftDriver@" &&
-z "${SWIFT_USE_OLD_DRIVER:-}" &&
( "$progName" == "swift" || "$progName" == "swiftc" )
]]; then
prog=@swiftDriver@
# Driver mode must be the very first argument.
extraBefore+=( "--driver-mode=$progName" )
if [[ $isRepl = 1 ]]; then
extraBefore+=( "-repl" )
fi
# Ensure swift-driver invokes the unwrapped frontend (instead of finding
# the wrapped one via PATH), because we don't have to wrap a second time.
export SWIFT_DRIVER_SWIFT_FRONTEND_EXEC="@swift@/bin/swift-frontend"
# Ensure swift-driver can find the LLDB with Swift support for the REPL.
export SWIFT_DRIVER_LLDB_EXEC="@swift@/bin/lldb"
fi
path_backup="$PATH"
# That @-vars are substituted separately from bash evaluation makes
# shellcheck think this, and others like it, are useless conditionals.
# shellcheck disable=SC2157
if [[ -n "@coreutils_bin@" && -n "@gnugrep_bin@" ]]; then
PATH="@coreutils_bin@/bin:@gnugrep_bin@/bin"
fi
# Parse command line options and set several variables.
# For instance, figure out if linker flags should be passed.
# GCC prints annoying warnings when they are not needed.
isCxx=0
dontLink=$isFrontend
for p in "${params[@]}"; do
case "$p" in
-enable-cxx-interop | -enable-experimental-cxx-interop)
isCxx=1 ;;
esac
done
# NOTE: We don't modify these for Swift, but sourced scripts may use them.
cxxInclude=1
cxxLibrary=1
cInclude=1
linkType=$(checkLinkType "${params[@]}")
# Optionally filter out paths not refering to the store.
if [[ "${NIX_ENFORCE_PURITY:-}" = 1 && -n "$NIX_STORE" ]]; then
kept=()
nParams=${#params[@]}
declare -i n=0
while (( "$n" < "$nParams" )); do
p=${params[n]}
p2=${params[n+1]:-} # handle `p` being last one
n+=1
skipNext=false
path=""
case "$p" in
-[IL]/*) path=${p:2} ;;
-[IL]) path=$p2 skipNext=true ;;
esac
if [[ -n $path ]] && badPath "$path"; then
skip "$path"
$skipNext && n+=1
continue
fi
kept+=("$p")
done
# Old bash empty array hack
params=(${kept+"${kept[@]}"})
fi
# Flirting with a layer violation here.
if [ -z "${NIX_BINTOOLS_WRAPPER_FLAGS_SET_@suffixSalt@:-}" ]; then
source @bintools@/nix-support/add-flags.sh
fi
# Put this one second so libc ldflags take priority.
if [ -z "${NIX_CC_WRAPPER_FLAGS_SET_@suffixSalt@:-}" ]; then
source $cc_wrapper/nix-support/add-flags.sh
fi
# Only add darwin min version flag and set up `DEVELOPER_DIR` if a default darwin min version is set,
# which is a signal that we're targeting darwin. (Copied from add-flags in libc but tailored for Swift).
if [ "@darwinMinVersion@" ]; then
# Make sure the wrapped Swift compiler can find the overlays in the SDK.
NIX_SWIFTFLAGS_COMPILE+=" -I $SDKROOT/usr/lib/swift"
NIX_LDFLAGS_@suffixSalt@+=" -L $SDKROOT/usr/lib/swift"
fi
if [[ "$isCxx" = 1 ]]; then
if [[ "$cxxInclude" = 1 ]]; then
NIX_CFLAGS_COMPILE_@suffixSalt@+=" $NIX_CXXSTDLIB_COMPILE_@suffixSalt@"
fi
if [[ "$cxxLibrary" = 1 ]]; then
NIX_CFLAGS_LINK_@suffixSalt@+=" $NIX_CXXSTDLIB_LINK_@suffixSalt@"
fi
fi
source $cc_wrapper/nix-support/add-hardening.sh
# Add the flags for the C compiler proper.
addCFlagsToList() {
declare -n list="$1"
shift
for ((i = 1; i <= $#; i++)); do
local val="${!i}"
case "$val" in
# Pass through using -Xcc, but also convert to Swift -I.
# These have slightly different meaning for Clang, but Swift
# doesn't have exact equivalents.
-isystem | -idirafter)
i=$((i + 1))
list+=("-Xcc" "$val" "-Xcc" "${!i}" "-I" "${!i}")
;;
# Simple rename.
-iframework)
i=$((i + 1))
list+=("-Fsystem" "${!i}")
;;
# Pass through verbatim.
-I | -Fsystem)
i=$((i + 1))
list+=("${val}" "${!i}")
;;
-I* | -L* | -F*)
list+=("${val}")
;;
# Pass through using -Xcc.
*)
list+=("-Xcc" "$val")
;;
esac
done
}
for i in ${NIX_SWIFTFLAGS_COMPILE:-}; do
extraAfter+=("$i")
done
for i in ${NIX_SWIFTFLAGS_COMPILE_BEFORE:-}; do
extraBefore+=("$i")
done
addCFlagsToList extraAfter $NIX_CFLAGS_COMPILE_@suffixSalt@
addCFlagsToList extraBefore ${hardeningCFlags[@]+"${hardeningCFlags[@]}"} $NIX_CFLAGS_COMPILE_BEFORE_@suffixSalt@
if [ "$dontLink" != 1 ]; then
# Add the flags that should only be passed to the compiler when
# linking.
addCFlagsToList extraAfter $(filterRpathFlags "$linkType" $NIX_CFLAGS_LINK_@suffixSalt@)
# Add the flags that should be passed to the linker (and prevent
# `ld-wrapper' from adding NIX_LDFLAGS_@suffixSalt@ again).
for i in $(filterRpathFlags "$linkType" $NIX_LDFLAGS_BEFORE_@suffixSalt@); do
extraBefore+=("-Xlinker" "$i")
done
if [[ "$linkType" == dynamic && -n "$NIX_DYNAMIC_LINKER_@suffixSalt@" ]]; then
extraBefore+=("-Xlinker" "-dynamic-linker=$NIX_DYNAMIC_LINKER_@suffixSalt@")
fi
for i in $(filterRpathFlags "$linkType" $NIX_LDFLAGS_@suffixSalt@); do
if [ "${i:0:3}" = -L/ ]; then
extraAfter+=("$i")
else
extraAfter+=("-Xlinker" "$i")
fi
done
export NIX_LINK_TYPE_@suffixSalt@=$linkType
fi
# TODO: If we ever need to expand functionality of this hook, it may no longer
# be compatible with Swift. Right now, it is only used on Darwin to force
# -target, which also happens to work with Swift.
if [[ -e $cc_wrapper/nix-support/add-local-cc-cflags-before.sh ]]; then
source $cc_wrapper/nix-support/add-local-cc-cflags-before.sh
fi
for ((i=0; i < ${#extraBefore[@]}; i++));do
case "${extraBefore[i]}" in
-target)
i=$((i + 1))
# On Darwin only, need to change 'aarch64' to 'arm64'.
extraBefore[i]="${extraBefore[i]/aarch64-apple-/arm64-apple-}"
# On Darwin, Swift requires the triple to be annotated with a version.
# TODO: Assumes macOS.
extraBefore[i]="${extraBefore[i]/-apple-darwin/-apple-macosx${MACOSX_DEPLOYMENT_TARGET:-11.0}}"
;;
-march=*|-mcpu=*|-mfloat-abi=*|-mfpu=*|-mmode=*|-mthumb|-marm|-mtune=*)
[[ i -gt 0 && ${extraBefore[i-1]} == -Xcc ]] && continue
extraBefore=(
"${extraBefore[@]:0:i}"
-Xcc
"${extraBefore[@]:i:${#extraBefore[@]}}"
)
i=$((i + 1))
;;
esac
done
# As a very special hack, if the arguments are just `-v', then don't
# add anything. This is to prevent `gcc -v' (which normally prints
# out the version number and returns exit code 0) from printing out
# `No input files specified' and returning exit code 1.
if [ "$*" = -v ]; then
extraAfter=()
extraBefore=()
fi
# Optionally print debug info.
if (( "${NIX_DEBUG:-0}" >= 1 )); then
# Old bash workaround, see ld-wrapper for explanation.
echo "extra flags before to $prog:" >&2
printf " %q\n" ${extraBefore+"${extraBefore[@]}"} >&2
echo "original flags to $prog:" >&2
printf " %q\n" ${params+"${params[@]}"} >&2
echo "extra flags after to $prog:" >&2
printf " %q\n" ${extraAfter+"${extraAfter[@]}"} >&2
fi
PATH="$path_backup"
# Old bash workaround, see above.
if (( "${NIX_CC_USE_RESPONSE_FILE:-@use_response_file_by_default@}" >= 1 )); then
exec "$prog" @<(printf "%q\n" \
${extraBefore+"${extraBefore[@]}"} \
${params+"${params[@]}"} \
${extraAfter+"${extraAfter[@]}"})
else
exec "$prog" \
${extraBefore+"${extraBefore[@]}"} \
${params+"${params[@]}"} \
${extraAfter+"${extraAfter[@]}"}
fi