5b123afb9a
The Swift wrapper uses a hook directly from cc-wrapper to set the
`-target` flag appropriately. This works because Clang and Swift use the
same syntax for `-target`, but there was never a guarantee that this
compatibility would be true for every option set in the hook. Indeed,
commit 369cc5c66b (PR #445119) made
availability warnings into errors by setting the
`-Werror=unguarded-availability` flag in this hook, which Swift doesn't
accept at the top level. This caused all invocations of Swift to fail
with the error `unknown argument: '-Werror=unguarded-availability'` -
including the bootstrap Swift, which meant that `swiftPackages.swift`
would fail.
This commit adds all `-Werror` flags to the list of flags that need to
be prefixed with `-Xcc`. I could have just dropped the flag, since Swift
already makes this an error, but you can have C/C++ targets in Swift
packages and we'd want to pass this flag on to them. (I'm not sure
whether the clang used for those targets is already wrapped, but if it
is there is no harm done.)
314 lines
9.9 KiB
Bash
314 lines
9.9 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
|
|
-cxx-interoperability-mode=default | -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.
|
|
# As of 369cc5c66b1efdbca2f136aa0055fedca1117304 (#445119), this hook also sets
|
|
# the -Werror=unguarded-availability flag, which Swift can't accept. We prefix
|
|
# that flag with -Xcc in the for loop below
|
|
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=*|-Werror=*)
|
|
[[ 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
|