Skip to content

Commit 943f059

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 #543.
1 parent 283c024 commit 943f059

File tree

1 file changed

+59
-42
lines changed

1 file changed

+59
-42
lines changed

toolchain/cc_wrapper.sh.tpl

Lines changed: 59 additions & 42 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,16 +16,16 @@
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

27+
CLEANUP_FILES=""
28+
2929
trap cleanup EXIT
3030

3131
# See note in toolchain/internal/configure.bzl where we define
@@ -50,13 +50,13 @@ trap cleanup EXIT
5050
#
5151

5252
dirname_shim() {
53-
local path="$1"
53+
path="$1"
5454

5555
# Remove trailing slashes
5656
path="${path%/}"
5757

5858
# If there's no slash, return "."
59-
if [[ "${path}" != */* ]]; then
59+
if [ "${path}" != "*/*" ]; then
6060
echo "."
6161
return
6262
fi
@@ -68,74 +68,91 @@ dirname_shim() {
6868
echo "${path:-/}"
6969
}
7070

71-
script_dir=$(dirname_shim "${BASH_SOURCE[0]}")
71+
script_dir=$(dirname_shim "$0")
7272
toolchain_path_prefix="%{toolchain_path_prefix}"
7373

7474
# Sometimes this path may be an absolute path in which case we dont do anything because
7575
# This is using the host toolchain to build.
76-
if [[ ${toolchain_path_prefix} != /* ]]; then
77-
toolchain_path_prefix="${script_dir}/../../${toolchain_path_prefix#external/}"
78-
fi
76+
case "${toolchain_path_prefix}" in
77+
/*) ;;
78+
*) toolchain_path_prefix="${script_dir}/../../${toolchain_path_prefix#external/}" ;;
79+
esac
7980

80-
if [[ ! -f ${toolchain_path_prefix}bin/clang ]]; then
81+
if [ ! -f "${toolchain_path_prefix}bin/clang" ]; then
8182
echo >&2 "ERROR: could not find clang; PWD=\"${PWD}\"; PATH=\"${PATH}\"; toolchain_path_prefix=${toolchain_path_prefix}."
8283
exit 5
8384
fi
8485

8586
OUTPUT=
8687

87-
function parse_option() {
88-
local -r opt="$1"
89-
if [[ "${OUTPUT}" = "1" ]]; then
90-
OUTPUT=${opt}
91-
elif [[ "${opt}" = "-o" ]]; then
88+
parse_option() {
89+
po_opt="$1"
90+
if [ "${OUTPUT}" = "1" ]; then
91+
OUTPUT=${po_opt}
92+
elif [ "${po_opt}" = "-o" ]; then
9293
# output is coming
9394
OUTPUT=1
9495
fi
9596
}
9697

97-
function sanitize_option() {
98-
local -r opt=$1
99-
if [[ ${opt} == */cc_wrapper.sh ]]; then
100-
printf "%s" "${toolchain_path_prefix}bin/clang"
101-
elif [[ ${opt} =~ ^-fsanitize-(ignore|black)list=[^/] ]] && [[ ${script_dir} == /* ]]; then
102-
# shellcheck disable=SC2206
103-
parts=(${opt/=/ }) # Split flag name and value into array.
104-
printf "%s" "${parts[0]}=${script_dir}/../../../${parts[1]}"
105-
else
106-
printf "%s" "${opt}"
107-
fi
98+
sanitize_option() {
99+
so_opt="$1"
100+
case ${so_opt} in
101+
*/cc_wrapper.sh) printf "%s" "${toolchain_path_prefix}bin/clang" ;;
102+
*)
103+
if eval "case ${so_opt} in -fsanitize-ignorelist=*|-fsanitize-blacklist=*) [ ${script_dir} == /* ] ;; esac"; then
104+
# Split flag name and value.
105+
#
106+
# shellcheck disable=SC2206
107+
part0=$(echo "${so_opt}" | cut -d '=' -f 1)
108+
part1=$(echo "${so_opt}" | cut -d '=' -f 2)
109+
printf "%s" "${part0}=${script_dir}/../../../${part1}"
110+
else
111+
printf "%s" "${so_opt}"
112+
fi
113+
;;
114+
esac
108115
}
109116

110-
cmd=()
111-
for ((i = 0; i <= $#; i++)); do
112-
if [[ ${!i} == @* && -r "${i:1}" ]]; then
117+
COUNT=$#
118+
i=0
119+
while [ "${i}" -le "${COUNT}" ]; do
120+
temp=""
121+
eval "temp=\${${i}}"
122+
substr="${temp#?}"
123+
if eval "case ${temp} in @*) [ -r \"{substr}\" ] ;; esac"; then
113124
# Create a new, sanitized file.
114125
tmpfile=$(mktemp)
115-
CLEANUP_FILES+=("${tmpfile}")
126+
# POSIX shell does not support arrays, so we write the cleanup files as an
127+
# array-separated list. We do not need to worry about spaces in filenames,
128+
# because `mktemp` cannot use them when using the default template.
129+
CLEANUP_FILES="${CLEANUP_FILES} ${tmpfile}"
116130
while IFS= read -r opt; do
117131
opt="$(
118132
set -e
119133
sanitize_option "${opt}"
120134
)"
121135
parse_option "${opt}"
122136
echo "${opt}" >>"${tmpfile}"
123-
done <"${!i:1}"
124-
cmd+=("@${tmpfile}")
137+
done <"${substr}"
138+
cmd="${cmd} ${tmpfile}"
125139
else
126140
opt="$(
127141
set -e
128-
sanitize_option "${!i}"
142+
sanitize_option "${temp}"
129143
)"
130144
parse_option "${opt}"
131-
cmd+=("${opt}")
145+
# The items within $cmd also cannot contain spaces, because of how
146+
# `sanitize_option` behaves.
147+
cmd="${cmd} ${opt}"
132148
fi
149+
i=$((i + 1))
133150
done
134151

135152
# Call the C++ compiler.
136-
"${cmd[@]}"
153+
eval \""${cmd}"\"
137154

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

0 commit comments

Comments
 (0)