1#! @shell@
2# NOTE: This wrapper is derived from cc-wrapper.sh, and is hopefully somewhat
3# diffable with the original, so changes can be merged if necessary.
4set -eu -o pipefail +o posix
5shopt -s nullglob
6
7if (( "${NIX_DEBUG:-0}" >= 7 )); then
8 set -x
9fi
10
11cc_wrapper="@cc_wrapper@"
12
13source $cc_wrapper/nix-support/utils.bash
14
15source $cc_wrapper/nix-support/darwin-sdk-setup.bash
16
17expandResponseParams "$@"
18
19# Check if we should wrap this Swift invocation at all, and how. Specifically,
20# there are some internal tools we don't wrap, plus swift-frontend doesn't link
21# and doesn't understand linker flags. This follows logic in
22# `lib/DriverTool/driver.cpp`.
23prog=@prog@
24progName="$(basename "$prog")"
25firstArg="${params[0]:-}"
26isFrontend=0
27isRepl=0
28
29# These checks follow `shouldRunAsSubcommand`.
30if [[ "$progName" == swift ]]; then
31 case "$firstArg" in
32 "" | -* | *.* | */* | repl)
33 ;;
34 *)
35 exec "swift-$firstArg" "${params[@]:1}"
36 ;;
37 esac
38fi
39
40# These checks follow the first part of `run_driver`.
41#
42# NOTE: The original function short-circuits, but we can't here, because both
43# paths must be wrapped. So we use an 'isFrontend' flag instead.
44case "$firstArg" in
45 -frontend)
46 isFrontend=1
47 # Ensure this stays the first argument.
48 params=( "${params[@]:1}" )
49 extraBefore+=( "-frontend" )
50 ;;
51 -modulewrap)
52 # Don't wrap this integrated tool.
53 exec "$prog" "${params[@]}"
54 ;;
55 repl)
56 isRepl=1
57 params=( "${params[@]:1}" )
58 ;;
59 --driver-mode=*)
60 ;;
61 *)
62 if [[ "$progName" == swift-frontend ]]; then
63 isFrontend=1
64 fi
65 ;;
66esac
67
68# For many tasks, Swift reinvokes swift-driver, the new driver implementation
69# written in Swift. It needs some help finding the executable, though, and
70# reimplementing the logic here is little effort. These checks follow
71# `shouldDisallowNewDriver`.
72if [[
73 $isFrontend = 0 &&
74 -n "@swiftDriver@" &&
75 -z "${SWIFT_USE_OLD_DRIVER:-}" &&
76 ( "$progName" == "swift" || "$progName" == "swiftc" )
77]]; then
78 prog=@swiftDriver@
79 # Driver mode must be the very first argument.
80 extraBefore+=( "--driver-mode=$progName" )
81 if [[ $isRepl = 1 ]]; then
82 extraBefore+=( "-repl" )
83 fi
84
85 # Ensure swift-driver invokes the unwrapped frontend (instead of finding
86 # the wrapped one via PATH), because we don't have to wrap a second time.
87 export SWIFT_DRIVER_SWIFT_FRONTEND_EXEC="@swift@/bin/swift-frontend"
88
89 # Ensure swift-driver can find the LLDB with Swift support for the REPL.
90 export SWIFT_DRIVER_LLDB_EXEC="@swift@/bin/lldb"
91fi
92
93path_backup="$PATH"
94
95# That @-vars are substituted separately from bash evaluation makes
96# shellcheck think this, and others like it, are useless conditionals.
97# shellcheck disable=SC2157
98if [[ -n "@coreutils_bin@" && -n "@gnugrep_bin@" ]]; then
99 PATH="@coreutils_bin@/bin:@gnugrep_bin@/bin"
100fi
101
102# Parse command line options and set several variables.
103# For instance, figure out if linker flags should be passed.
104# GCC prints annoying warnings when they are not needed.
105isCxx=0
106dontLink=$isFrontend
107
108for p in "${params[@]}"; do
109 case "$p" in
110 -enable-cxx-interop | -enable-experimental-cxx-interop)
111 isCxx=1 ;;
112 esac
113done
114
115# NOTE: We don't modify these for Swift, but sourced scripts may use them.
116cxxInclude=1
117cxxLibrary=1
118cInclude=1
119
120linkType=$(checkLinkType "${params[@]}")
121
122# Optionally filter out paths not refering to the store.
123if [[ "${NIX_ENFORCE_PURITY:-}" = 1 && -n "$NIX_STORE" ]]; then
124 kept=()
125 nParams=${#params[@]}
126 declare -i n=0
127 while (( "$n" < "$nParams" )); do
128 p=${params[n]}
129 p2=${params[n+1]:-} # handle `p` being last one
130 n+=1
131
132 skipNext=false
133 path=""
134 case "$p" in
135 -[IL]/*) path=${p:2} ;;
136 -[IL]) path=$p2 skipNext=true ;;
137 esac
138
139 if [[ -n $path ]] && badPath "$path"; then
140 skip "$path"
141 $skipNext && n+=1
142 continue
143 fi
144
145 kept+=("$p")
146 done
147 # Old bash empty array hack
148 params=(${kept+"${kept[@]}"})
149fi
150
151# Flirting with a layer violation here.
152if [ -z "${NIX_BINTOOLS_WRAPPER_FLAGS_SET_@suffixSalt@:-}" ]; then
153 source @bintools@/nix-support/add-flags.sh
154fi
155
156# Put this one second so libc ldflags take priority.
157if [ -z "${NIX_CC_WRAPPER_FLAGS_SET_@suffixSalt@:-}" ]; then
158 source $cc_wrapper/nix-support/add-flags.sh
159fi
160
161# Only add darwin min version flag and set up `DEVELOPER_DIR` if a default darwin min version is set,
162# which is a signal that we're targeting darwin. (Copied from add-flags in libc but tailored for Swift).
163if [ "@darwinMinVersion@" ]; then
164 # Make sure the wrapped Swift compiler can find the overlays in the SDK.
165 NIX_SWIFTFLAGS_COMPILE+=" -I $SDKROOT/usr/lib/swift"
166 NIX_LDFLAGS_@suffixSalt@+=" -L $SDKROOT/usr/lib/swift"
167fi
168
169if [[ "$isCxx" = 1 ]]; then
170 if [[ "$cxxInclude" = 1 ]]; then
171 NIX_CFLAGS_COMPILE_@suffixSalt@+=" $NIX_CXXSTDLIB_COMPILE_@suffixSalt@"
172 fi
173 if [[ "$cxxLibrary" = 1 ]]; then
174 NIX_CFLAGS_LINK_@suffixSalt@+=" $NIX_CXXSTDLIB_LINK_@suffixSalt@"
175 fi
176fi
177
178source $cc_wrapper/nix-support/add-hardening.sh
179
180# Add the flags for the C compiler proper.
181addCFlagsToList() {
182 declare -n list="$1"
183 shift
184
185 for ((i = 1; i <= $#; i++)); do
186 local val="${!i}"
187 case "$val" in
188 # Pass through using -Xcc, but also convert to Swift -I.
189 # These have slightly different meaning for Clang, but Swift
190 # doesn't have exact equivalents.
191 -isystem | -idirafter)
192 i=$((i + 1))
193 list+=("-Xcc" "$val" "-Xcc" "${!i}" "-I" "${!i}")
194 ;;
195 # Simple rename.
196 -iframework)
197 i=$((i + 1))
198 list+=("-Fsystem" "${!i}")
199 ;;
200 # Pass through verbatim.
201 -I | -Fsystem)
202 i=$((i + 1))
203 list+=("${val}" "${!i}")
204 ;;
205 -I* | -L* | -F*)
206 list+=("${val}")
207 ;;
208 # Pass through using -Xcc.
209 *)
210 list+=("-Xcc" "$val")
211 ;;
212 esac
213 done
214}
215for i in ${NIX_SWIFTFLAGS_COMPILE:-}; do
216 extraAfter+=("$i")
217done
218for i in ${NIX_SWIFTFLAGS_COMPILE_BEFORE:-}; do
219 extraBefore+=("$i")
220done
221addCFlagsToList extraAfter $NIX_CFLAGS_COMPILE_@suffixSalt@
222addCFlagsToList extraBefore ${hardeningCFlags[@]+"${hardeningCFlags[@]}"} $NIX_CFLAGS_COMPILE_BEFORE_@suffixSalt@
223
224if [ "$dontLink" != 1 ]; then
225
226 # Add the flags that should only be passed to the compiler when
227 # linking.
228 addCFlagsToList extraAfter $(filterRpathFlags "$linkType" $NIX_CFLAGS_LINK_@suffixSalt@)
229
230 # Add the flags that should be passed to the linker (and prevent
231 # `ld-wrapper' from adding NIX_LDFLAGS_@suffixSalt@ again).
232 for i in $(filterRpathFlags "$linkType" $NIX_LDFLAGS_BEFORE_@suffixSalt@); do
233 extraBefore+=("-Xlinker" "$i")
234 done
235 if [[ "$linkType" == dynamic && -n "$NIX_DYNAMIC_LINKER_@suffixSalt@" ]]; then
236 extraBefore+=("-Xlinker" "-dynamic-linker=$NIX_DYNAMIC_LINKER_@suffixSalt@")
237 fi
238 for i in $(filterRpathFlags "$linkType" $NIX_LDFLAGS_@suffixSalt@); do
239 if [ "${i:0:3}" = -L/ ]; then
240 extraAfter+=("$i")
241 else
242 extraAfter+=("-Xlinker" "$i")
243 fi
244 done
245 export NIX_LINK_TYPE_@suffixSalt@=$linkType
246fi
247
248# TODO: If we ever need to expand functionality of this hook, it may no longer
249# be compatible with Swift. Right now, it is only used on Darwin to force
250# -target, which also happens to work with Swift.
251if [[ -e $cc_wrapper/nix-support/add-local-cc-cflags-before.sh ]]; then
252 source $cc_wrapper/nix-support/add-local-cc-cflags-before.sh
253fi
254
255for ((i=0; i < ${#extraBefore[@]}; i++));do
256 case "${extraBefore[i]}" in
257 -target)
258 i=$((i + 1))
259 # On Darwin only, need to change 'aarch64' to 'arm64'.
260 extraBefore[i]="${extraBefore[i]/aarch64-apple-/arm64-apple-}"
261 # On Darwin, Swift requires the triple to be annotated with a version.
262 # TODO: Assumes macOS.
263 extraBefore[i]="${extraBefore[i]/-apple-darwin/-apple-macosx${MACOSX_DEPLOYMENT_TARGET:-11.0}}"
264 ;;
265 -march=*|-mcpu=*|-mfloat-abi=*|-mfpu=*|-mmode=*|-mthumb|-marm|-mtune=*)
266 [[ i -gt 0 && ${extraBefore[i-1]} == -Xcc ]] && continue
267 extraBefore=(
268 "${extraBefore[@]:0:i}"
269 -Xcc
270 "${extraBefore[@]:i:${#extraBefore[@]}}"
271 )
272 i=$((i + 1))
273 ;;
274 esac
275done
276
277# As a very special hack, if the arguments are just `-v', then don't
278# add anything. This is to prevent `gcc -v' (which normally prints
279# out the version number and returns exit code 0) from printing out
280# `No input files specified' and returning exit code 1.
281if [ "$*" = -v ]; then
282 extraAfter=()
283 extraBefore=()
284fi
285
286# Optionally print debug info.
287if (( "${NIX_DEBUG:-0}" >= 1 )); then
288 # Old bash workaround, see ld-wrapper for explanation.
289 echo "extra flags before to $prog:" >&2
290 printf " %q\n" ${extraBefore+"${extraBefore[@]}"} >&2
291 echo "original flags to $prog:" >&2
292 printf " %q\n" ${params+"${params[@]}"} >&2
293 echo "extra flags after to $prog:" >&2
294 printf " %q\n" ${extraAfter+"${extraAfter[@]}"} >&2
295fi
296
297PATH="$path_backup"
298# Old bash workaround, see above.
299
300if (( "${NIX_CC_USE_RESPONSE_FILE:-@use_response_file_by_default@}" >= 1 )); then
301 exec "$prog" @<(printf "%q\n" \
302 ${extraBefore+"${extraBefore[@]}"} \
303 ${params+"${params[@]}"} \
304 ${extraAfter+"${extraAfter[@]}"})
305else
306 exec "$prog" \
307 ${extraBefore+"${extraBefore[@]}"} \
308 ${params+"${params[@]}"} \
309 ${extraAfter+"${extraAfter[@]}"}
310fi