|
1 | | -#!/bin/bash |
| 1 | +#!/bin/sh |
2 | 2 | # |
3 | 3 | # Copyright 2021 The Bazel Authors. All rights reserved. |
4 | 4 | # |
|
14 | 14 | # See the License for the specific language governing permissions and |
15 | 15 | # limitations under the License. |
16 | 16 |
|
17 | | -# shellcheck disable=SC1083 |
| 17 | +SCRIPT_DIR=$(dirname "$0") |
18 | 18 |
|
19 | | -set -euo pipefail |
| 19 | +# Search for `bash` on the system, and then execute cc_wrapper_inner.sh with |
| 20 | +# it. |
20 | 21 |
|
21 | | -CLEANUP_FILES=() |
| 22 | +# Attempt #1: /bin/bash -- present on FHS-compliant systems, but notably absent |
| 23 | +# on others, including NixOS. |
| 24 | +test -e /bin/bash && exec /bin/bash "${SCRIPT_DIR}"/cc_wrapper_inner.sh "$@" |
22 | 25 |
|
23 | | -function cleanup() { |
24 | | - if [[ ${#CLEANUP_FILES[@]} -gt 0 ]]; then |
25 | | - rm -f "${CLEANUP_FILES[@]}" |
26 | | - fi |
27 | | -} |
| 26 | +# Attempt #2: /usr/bin/env bash -- /usr/bin/env is required by POSIX, but some |
| 27 | +# callers to the LLVM toolchain, such as rules_rust, clear $PATH and leave |
| 28 | +# nothing for /usr/bin/env to search for. |
| 29 | +test -e /usr/bin/env && test /usr/bin/env bash true && |
| 30 | + exec /usr/bin/env bash "${SCRIPT_DIR}"/cc_wrapper_inner.sh "$@" |
28 | 31 |
|
29 | | -trap cleanup EXIT |
| 32 | +# Attempt #3: Try `command -v`. |
| 33 | +command -v bash && exec $(command -v bash) "${SCRIPT_DIR}"/cc_wrapper_inner.sh "$@" |
30 | 34 |
|
31 | | -# See note in toolchain/internal/configure.bzl where we define |
32 | | -# `wrapper_bin_prefix` for why this wrapper is needed. |
33 | | - |
34 | | -# this script is located at either |
35 | | -# - <execroot>/external/<repo_name>/bin/cc_wrapper.sh |
36 | | -# - <runfiles>/<repo_name>/bin/cc_wrapper.sh |
37 | | -# The clang is located at |
38 | | -# - <execroot>/external/<repo_name2>/bin/clang |
39 | | -# - <runfiles>/<repo_name2>/bin/clang |
40 | | -# |
41 | | -# In both cases, getting to clang can be done via |
42 | | -# Finding the current dir of this script, |
43 | | -# - <execroot>/external/<repo_name>/bin/ |
44 | | -# - <runfiles>/<repo_name>/bin/ |
45 | | -# going back 2 directories |
46 | | -# - <execroot>/external |
47 | | -# - <runfiles> |
48 | | -# |
49 | | -# Going into %{toolchain_path_prefix} without the `external/` prefix + `bin/clang` |
50 | | -# |
51 | | - |
52 | | -dirname_shim() { |
53 | | - local path="$1" |
54 | | - |
55 | | - # Remove trailing slashes |
56 | | - path="${path%/}" |
57 | | - |
58 | | - # If there's no slash, return "." |
59 | | - if [[ "${path}" != */* ]]; then |
60 | | - echo "." |
61 | | - return |
62 | | - fi |
63 | | - |
64 | | - # Remove the last component after the final slash |
65 | | - path="${path%/*}" |
66 | | - |
67 | | - # If it becomes empty, it means root "/" |
68 | | - echo "${path:-/}" |
69 | | -} |
70 | | - |
71 | | -script_dir=$(dirname_shim "${BASH_SOURCE[0]}") |
72 | | -toolchain_path_prefix="%{toolchain_path_prefix}" |
73 | | - |
74 | | -# Sometimes this path may be an absolute path in which case we dont do anything because |
75 | | -# 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 |
79 | | - |
80 | | -if [[ ! -f ${toolchain_path_prefix}bin/clang ]]; then |
81 | | - echo >&2 "ERROR: could not find clang; PWD=\"${PWD}\"; PATH=\"${PATH}\"; toolchain_path_prefix=${toolchain_path_prefix}." |
82 | | - exit 5 |
83 | | -fi |
84 | | - |
85 | | -OUTPUT= |
86 | | - |
87 | | -function parse_option() { |
88 | | - local -r opt="$1" |
89 | | - if [[ "${OUTPUT}" = "1" ]]; then |
90 | | - OUTPUT=${opt} |
91 | | - elif [[ "${opt}" = "-o" ]]; then |
92 | | - # output is coming |
93 | | - OUTPUT=1 |
94 | | - fi |
95 | | -} |
96 | | - |
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 |
108 | | -} |
109 | | - |
110 | | -cmd=() |
111 | | -for ((i = 0; i <= $#; i++)); do |
112 | | - if [[ ${!i} == @* && -r "${i:1}" ]]; then |
113 | | - # Create a new, sanitized file. |
114 | | - tmpfile=$(mktemp) |
115 | | - CLEANUP_FILES+=("${tmpfile}") |
116 | | - while IFS= read -r opt; do |
117 | | - opt="$( |
118 | | - set -e |
119 | | - sanitize_option "${opt}" |
120 | | - )" |
121 | | - parse_option "${opt}" |
122 | | - echo "${opt}" >>"${tmpfile}" |
123 | | - done <"${!i:1}" |
124 | | - cmd+=("@${tmpfile}") |
125 | | - else |
126 | | - opt="$( |
127 | | - set -e |
128 | | - sanitize_option "${!i}" |
129 | | - )" |
130 | | - parse_option "${opt}" |
131 | | - cmd+=("${opt}") |
132 | | - fi |
133 | | -done |
134 | | - |
135 | | -# Call the C++ compiler. |
136 | | -"${cmd[@]}" |
137 | | - |
138 | | -# Generate an empty file if header processing succeeded. |
139 | | -if [[ "${OUTPUT}" == *.h.processed ]]; then |
140 | | - echo -n >"${OUTPUT}" |
141 | | -fi |
| 35 | +echo >&2 'Failed to find bash at /bin/bash or in PATH.' |
| 36 | +exit 1 |
0 commit comments