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