Skip to content

Commit a420fd6

Browse files
author
Ryan Torok
committed
[wrapper] Make cc_wrapper.sh POSIX-compliant and use /bin/sh
Some Linux distributions, such as NixOS, do not provide /bin/bash. This commit aims to make the LLVM toolchain compatible with these platforms by only using POSIX-compatible features in the shell script and replacing the shebang with #!/bin/sh . This commit does not update the corresponding MacOS script, as all MacOS builds should have /bin/bash. Supercedes bazel-contrib#543.
1 parent 283c024 commit a420fd6

File tree

1 file changed

+45
-36
lines changed

1 file changed

+45
-36
lines changed

toolchain/cc_wrapper.sh.tpl

Lines changed: 45 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/bin/bash
1+
#!/bin/sh
22
#
33
# Copyright 2021 The Bazel Authors. All rights reserved.
44
#
@@ -16,14 +16,12 @@
1616

1717
# shellcheck disable=SC1083
1818

19-
set -euo pipefail
19+
set -euo
2020

21-
CLEANUP_FILES=()
22-
23-
function cleanup() {
24-
if [[ ${#CLEANUP_FILES[@]} -gt 0 ]]; then
25-
rm -f "${CLEANUP_FILES[@]}"
26-
fi
21+
cleanup() {
22+
while read -r f; do
23+
rm -f "${f}";
24+
done < "${CLEANUP_FILES}"
2725
}
2826

2927
trap cleanup EXIT
@@ -50,13 +48,13 @@ trap cleanup EXIT
5048
#
5149

5250
dirname_shim() {
53-
local path="$1"
51+
path="$1"
5452

5553
# Remove trailing slashes
5654
path="${path%/}"
5755

5856
# If there's no slash, return "."
59-
if [[ "${path}" != */* ]]; then
57+
if [ "${path}" != "*/*" ]; then
6058
echo "."
6159
return
6260
fi
@@ -68,74 +66,85 @@ dirname_shim() {
6866
echo "${path:-/}"
6967
}
7068

71-
script_dir=$(dirname_shim "${BASH_SOURCE[0]}")
69+
script_dir=$(dirname_shim "$0")
7270
toolchain_path_prefix="%{toolchain_path_prefix}"
7371

7472
# Sometimes this path may be an absolute path in which case we dont do anything because
7573
# This is using the host toolchain to build.
76-
if [[ ${toolchain_path_prefix} != /* ]]; then
74+
if [ "${toolchain_path_prefix}" != "/*" ]; then
7775
toolchain_path_prefix="${script_dir}/../../${toolchain_path_prefix#external/}"
7876
fi
7977

80-
if [[ ! -f ${toolchain_path_prefix}bin/clang ]]; then
78+
if [ ! -f "${toolchain_path_prefix}bin/clang" ]; then
8179
echo >&2 "ERROR: could not find clang; PWD=\"${PWD}\"; PATH=\"${PATH}\"; toolchain_path_prefix=${toolchain_path_prefix}."
8280
exit 5
8381
fi
8482

8583
OUTPUT=
8684

87-
function parse_option() {
88-
local -r opt="$1"
89-
if [[ "${OUTPUT}" = "1" ]]; then
90-
OUTPUT=${opt}
91-
elif [[ "${opt}" = "-o" ]]; then
85+
parse_option() {
86+
po_opt="$1"
87+
if [ "${OUTPUT}" = "1" ]; then
88+
OUTPUT=${po_opt}
89+
elif [ "${po_opt}" = "-o" ]; then
9290
# output is coming
9391
OUTPUT=1
9492
fi
9593
}
9694

97-
function sanitize_option() {
98-
local -r opt=$1
99-
if [[ ${opt} == */cc_wrapper.sh ]]; then
95+
sanitize_option() {
96+
so_opt="$1"
97+
if [ "${so_opt}" = "*/cc_wrapper.sh" ]; then
10098
printf "%s" "${toolchain_path_prefix}bin/clang"
101-
elif [[ ${opt} =~ ^-fsanitize-(ignore|black)list=[^/] ]] && [[ ${script_dir} == /* ]]; then
99+
elif eval "case $so_opt in *^-fsanitize-(ignore|black)list=[^/]*) [ $script_dir == /* ] ;; esac"; then
100+
# Split flag name and value.
101+
#
102102
# shellcheck disable=SC2206
103-
parts=(${opt/=/ }) # Split flag name and value into array.
104-
printf "%s" "${parts[0]}=${script_dir}/../../../${parts[1]}"
103+
part0=$(echo "$so_opt" | cut -d '=' -f 1)
104+
part1=$(echo "$so_opt" | cut -d '=' -f 2)
105+
printf "%s" "${part0}=${script_dir}/../../../${part1}"
105106
else
106-
printf "%s" "${opt}"
107+
printf "%s" "${so_opt}"
107108
fi
108109
}
109110

110-
cmd=()
111-
for ((i = 0; i <= $#; i++)); do
112-
if [[ ${!i} == @* && -r "${i:1}" ]]; then
111+
COUNT=$#
112+
i=0
113+
while [ $i -le $COUNT ]; do
114+
temp=""
115+
eval "temp=\${$i}"
116+
substr="${temp#?}"
117+
if eval "case $temp in @*) [ -r $substr ] ;; esac"; then
113118
# Create a new, sanitized file.
114119
tmpfile=$(mktemp)
115-
CLEANUP_FILES+=("${tmpfile}")
120+
# POSIX shell does not support arrays, so we write the cleanup files as an
121+
# array-separated list. We do not need to worry about spaces in filenames,
122+
# because `mktemp` cannot use them when using the default template.
123+
CLEANUP_FILES="${CLEANUP_FILES} ${tmpfile}"
116124
while IFS= read -r opt; do
117125
opt="$(
118126
set -e
119127
sanitize_option "${opt}"
120128
)"
121129
parse_option "${opt}"
122130
echo "${opt}" >>"${tmpfile}"
123-
done <"${!i:1}"
124-
cmd+=("@${tmpfile}")
131+
done <"$substr"
132+
cmd="${cmd} ${tmpfile}"
125133
else
126134
opt="$(
127135
set -e
128-
sanitize_option "${!i}"
136+
sanitize_option "${temp}"
129137
)"
130138
parse_option "${opt}"
131-
cmd+=("${opt}")
139+
cmd="$cmd ${opt}"
132140
fi
141+
i=$(( i + 1 ))
133142
done
134143

135144
# Call the C++ compiler.
136-
"${cmd[@]}"
145+
${cmd}
137146

138147
# Generate an empty file if header processing succeeded.
139-
if [[ "${OUTPUT}" == *.h.processed ]]; then
140-
echo -n >"${OUTPUT}"
148+
if [ "${OUTPUT}" = "*.h.processed" ]; then
149+
true >"${OUTPUT}"
141150
fi

0 commit comments

Comments
 (0)