nixpkgs-suyu/pkgs/build-support/cc-wrapper/cc-wrapper.sh
Manuel Mendez e91b5670e3 cc-wrapper: Use case statements instead of bunch of if/elif checks
Makes for easier to read code imo, case-in-point there was a duplicate test for
`$p = -E` before. While doing this little bit of refactor I changed rest ->
kept because that makes more sense, rest sounds like its the rest of params
while kept says these are the params that we've kept.

I tested for no change in behavior using the following bash script:

```
reset() {
	cInclude=1
	cxxInclude=1
	cxxLibrary=1
	dontLink=0
	isCxx=0
	nonFlagArgs=0
	params=()
}

parseParams() {
	declare -i n=0
	nParams=${#params[@]}
	while (("$n" < "$nParams")); do
		p=${params[n]}
		p2=${params[n + 1]:-} # handle `p` being last one

		case "$p" in
		-[cSEM] | -MM) dontLink=1 ;;
		-cc1) cc1=1 ;;
		-nostdinc) cInclude=0 cxxInclude=0 ;;
		-nostdinc++) cxxInclude=0 ;;
		-nostdlib) cxxLibrary=0 ;;
		-x)
			case "$p2" in
			*-header) dontLink=1 ;;
			c++*) isCxx=1 ;;
			esac
			;;
		-?*) ;;
		*) nonFlagArgs=1 ;; # Includes a solitary dash (`-`) which signifies standard input; it is not a flag
		esac
		n+=1
	done
}

for p in c S E M MM; do
	reset
	params=-$p
	parseParams
	[[ $dontLink != 1 ]] && echo "expected dontLink=1 for params:${params[@]}" >&2 && exit 1
done

reset
params=(-x foo-header)
parseParams
[[ $dontLink != 1 ]] && echo "expected dontLink=1 for params:${params[@]}" >&2 && exit 1

reset
params=(-x c++-foo)
parseParams
[[ $isCxx != 1 ]] && echo "expected isCxx=1 for params:${params[@]}" >&2 && exit 1

reset
params=-nostdlib
parseParams
[[ $cxxLibrary != 0 ]] && echo "expected cxxLibrary=0 for params:${params[@]}" >&2 && exit 1

reset
params=-nostdinc
parseParams
[[ $cInclude != 0 ]] && echo "expected cInclude=0 for params:${params[@]}" >&2 && exit 1
[[ $cxxInclude != 0 ]] && echo "expected cxxInclude=0 for params:${params[@]}" >&2 && exit 1

reset
params=-nostdinc++
parseParams
[[ $cxxInclude != 0 ]] && echo "expected cxxInclude=0 for params:${params[@]}" >&2 && exit 1

reset
params=-cc1
parseParams
[[ $cc1 != 1 ]] && echo "expected cc1=1 for params:${params[@]}" >&2 && exit 1

reset
params=-
parseParams
[[ $nonFlagArgs != 1 ]] && echo "expected nonFlagArgs=1 for params:${params[@]}" >&2 && exit 1

reset
params=bleh
parseParams
[[ $nonFlagArgs != 1 ]] && echo "expected nonFlagArgs=1 for params:${params[@]}" >&2 && exit 1

reset
params=-?
parseParams
[[ $nonFlagArgs != 0 ]] && echo "expected nonFlagArgs=0 for params:${params[@]}" >&2 && exit 1

exit 0
```
2022-06-09 16:57:15 -04:00

203 lines
5.9 KiB
Bash

#! @shell@
set -eu -o pipefail +o posix
shopt -s nullglob
if (( "${NIX_DEBUG:-0}" >= 7 )); then
set -x
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
source @out@/nix-support/utils.bash
# 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.
dontLink=0
nonFlagArgs=0
cc1=0
# shellcheck disable=SC2193
[[ "@prog@" = *++ ]] && isCxx=1 || isCxx=0
cxxInclude=1
cxxLibrary=1
cInclude=1
expandResponseParams "$@"
linkType=$(checkLinkType "${params[@]}")
declare -i n=0
nParams=${#params[@]}
while (( "$n" < "$nParams" )); do
p=${params[n]}
p2=${params[n+1]:-} # handle `p` being last one
n+=1
case "$p" in
-[cSEM] | -MM) dontLink=1 ;;
-cc1) cc1=1 ;;
-nostdinc) cInclude=0 cxxInclude=0 ;;
-nostdinc++) cxxInclude=0 ;;
-nostdlib) cxxLibrary=0 ;;
-x)
case "$p2" in
*-header) dontLink=1 ;;
c++*) isCxx=1 ;;
esac
;;
-?*) ;;
*) nonFlagArgs=1 ;; # Includes a solitary dash (`-`) which signifies standard input; it is not a flag
esac
done
# If we pass a flag like -Wl, then gcc will call the linker unless it
# can figure out that it has to do something else (e.g., because of a
# "-c" flag). So if no non-flag arguments are given, don't pass any
# linker flags. This catches cases like "gcc" (should just print
# "gcc: no input files") and "gcc -v" (should print the version).
if [ "$nonFlagArgs" = 0 ]; then
dontLink=1
fi
# 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] | -isystem) 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 @out@/nix-support/add-flags.sh
fi
# Clear march/mtune=native -- they bring impurity.
if [ "$NIX_ENFORCE_NO_NATIVE_@suffixSalt@" = 1 ]; then
kept=()
# Old bash empty array hack
for p in ${params+"${params[@]}"}; do
if [[ "$p" = -m*=native ]]; then
skip "$p"
else
kept+=("$p")
fi
done
# Old bash empty array hack
params=(${kept+"${kept[@]}"})
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 @out@/nix-support/add-hardening.sh
# Add the flags for the C compiler proper.
extraAfter=($NIX_CFLAGS_COMPILE_@suffixSalt@)
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.
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+=("-Wl,$i")
done
if [[ "$linkType" == dynamic && -n "$NIX_DYNAMIC_LINKER_@suffixSalt@" ]]; then
extraBefore+=("-Wl,-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+=("-Wl,$i")
fi
done
export NIX_LINK_TYPE_@suffixSalt@=$linkType
fi
# 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
# clang's -cc1 mode is not compatible with most options
# that we would pass. Rather than trying to pass only
# options that would work, let's just remove all of them.
if [ "$cc1" = 1 ]; 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