Skip to content

Commit dd35164

Browse files
laltensiddharthab
andauthored
New attribute extra_compiler_files (#245)
This helps inject files into the compiler action sandbox. The files can then be used in the compiler command line, e.g. the sanitizer ignore list. --------- Co-authored-by: Siddhartha Bagaria <[email protected]>
1 parent 2b54ee4 commit dd35164

File tree

4 files changed

+118
-51
lines changed

4 files changed

+118
-51
lines changed

toolchain/cc_wrapper.sh.tpl

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,55 @@
2727

2828
# shellcheck disable=SC1083
2929

30-
set -eu
30+
set -euo pipefail
3131

3232
# See note in toolchain/internal/configure.bzl where we define
3333
# `wrapper_bin_prefix` for why this wrapper is needed.
3434

35-
# Call the C++ compiler.
3635
if [[ -f %{toolchain_path_prefix}bin/clang ]]; then
37-
exec %{toolchain_path_prefix}bin/clang "$@"
36+
execroot_path=""
3837
elif [[ ${BASH_SOURCE[0]} == "/"* ]]; then
3938
# Some consumers of `CcToolchainConfigInfo` (e.g. `cmake` from rules_foreign_cc)
4039
# change CWD and call $CC (this script) with its absolute path.
41-
# the execroot (i.e. `cmake` from `rules_foreign_cc`) and call CC . For cases like this,
42-
# we'll try to find `clang` relative to this script.
43-
# This script is at _execroot_/external/_repo_name_/bin/clang_wrapper.sh
44-
execroot_path="${BASH_SOURCE[0]%/*/*/*/*}"
45-
clang="${execroot_path}/%{toolchain_path_prefix}bin/clang"
46-
exec "${clang}" "${@}"
40+
# For cases like this, we'll try to find `clang` through an absolute path.
41+
# This script is at _execroot_/external/_repo_name_/bin/cc_wrapper.sh
42+
execroot_path="${BASH_SOURCE[0]%/*/*/*/*}/"
4743
else
4844
echo >&2 "ERROR: could not find clang; PWD=\"${PWD}\"; PATH=\"${PATH}\"."
4945
exit 5
5046
fi
47+
48+
function sanitize_option() {
49+
local -r opt=$1
50+
if [[ ${opt} == */cc_wrapper.sh ]]; then
51+
printf "%s" "${execroot_path}%{toolchain_path_prefix}bin/clang"
52+
elif [[ ${opt} =~ ^-fsanitize-(ignore|black)list=[^/] ]]; then
53+
# shellcheck disable=SC2206
54+
parts=(${opt/=/ }) # Split flag name and value into array.
55+
printf "%s" "${parts[0]}=${execroot_path}${parts[1]}"
56+
else
57+
printf "%s" "${opt}"
58+
fi
59+
}
60+
61+
cmd=()
62+
for ((i = 0; i <= $#; i++)); do
63+
if [[ ${!i} == @* ]]; then
64+
while IFS= read -r opt; do
65+
opt="$(
66+
set -e
67+
sanitize_option "${opt}"
68+
)"
69+
cmd+=("${opt}")
70+
done <"${!i:1}"
71+
else
72+
opt="$(
73+
set -e
74+
sanitize_option "${!i}"
75+
)"
76+
cmd+=("${opt}")
77+
fi
78+
done
79+
80+
# Call the C++ compiler.
81+
exec "${cmd[@]}"

toolchain/internal/configure.bzl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ def llvm_config_impl(rctx):
159159
coverage_link_flags_dict = rctx.attr.coverage_link_flags,
160160
unfiltered_compile_flags_dict = rctx.attr.unfiltered_compile_flags,
161161
llvm_version = llvm_version,
162+
extra_compiler_files = rctx.attr.extra_compiler_files,
162163
)
163164
host_dl_ext = "dylib" if os == "darwin" else "so"
164165
host_tools_info = dict([
@@ -412,7 +413,10 @@ filegroup(
412413
template = template + """
413414
filegroup(
414415
name = "compiler-components-{suffix}",
415-
srcs = [":sysroot-components-{suffix}"],
416+
srcs = [
417+
":sysroot-components-{suffix}",
418+
{extra_compiler_files}
419+
],
416420
)
417421
418422
filegroup(
@@ -445,6 +449,7 @@ filegroup(
445449
"{llvm_dist_label_prefix}clang",
446450
"{llvm_dist_label_prefix}include",
447451
":sysroot-components-{suffix}",
452+
{extra_compiler_files}
448453
],
449454
)
450455
@@ -541,6 +546,7 @@ cc_toolchain(
541546
extra_files_str = extra_files_str,
542547
host_tools_info = host_tools_info,
543548
cxx_builtin_include_directories = _list_to_string(cxx_builtin_include_directories),
549+
extra_compiler_files = ("\"%s\"," % str(toolchain_info.extra_compiler_files)) if toolchain_info.extra_compiler_files else "",
544550
)
545551

546552
def _convenience_targets_str(rctx, use_absolute_paths, llvm_dist_rel_path, llvm_dist_label_prefix, host_dl_ext):

toolchain/internal/repo.bzl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,12 @@ _compiler_configuration_attrs = {
233233
mandatory = False,
234234
doc = ("Override the toolchain's `target_settings` attribute."),
235235
),
236+
"extra_compiler_files": attr.label(
237+
mandatory = False,
238+
doc = ("Files to be made available in the sandbox for compile actions. " +
239+
"Mostly useful for providing files containing lists of flags, e.g. " +
240+
"sanitizer ignorelists."),
241+
),
236242
}
237243

238244
llvm_config_attrs = dict(common_attrs)

toolchain/osx_cc_wrapper.sh.tpl

Lines changed: 65 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@
2525
# See https://blogs.oracle.com/dipol/entry/dynamic_libraries_rpath_and_mac
2626
# on how to set those paths for Mach-O binaries.
2727

28-
# shellcheck disable=all
28+
# shellcheck disable=SC1083
2929

30-
set -eu
30+
set -euo pipefail
3131

3232
INSTALL_NAME_TOOL="/usr/bin/install_name_tool"
3333

@@ -39,29 +39,65 @@ OUTPUT=
3939
function parse_option() {
4040
local -r opt="$1"
4141
if [[ ${OUTPUT} == "1" ]]; then
42-
OUTPUT=$opt
43-
elif [[ $opt =~ ^-l(.*)$ ]]; then
44-
LIBS="${BASH_REMATCH[1]} $LIBS"
45-
elif [[ $opt =~ ^-L(.*)$ ]]; then
46-
LIB_DIRS="${BASH_REMATCH[1]} $LIB_DIRS"
47-
elif [[ $opt =~ ^\@loader_path/(.*)$ ]]; then
42+
OUTPUT=${opt}
43+
elif [[ ${opt} =~ ^-l(.*)$ ]]; then
44+
LIBS="${BASH_REMATCH[1]} ${LIBS}"
45+
elif [[ ${opt} =~ ^-L(.*)$ ]]; then
46+
LIB_DIRS="${BASH_REMATCH[1]} ${LIB_DIRS}"
47+
elif [[ ${opt} =~ ^\@loader_path/(.*)$ ]]; then
4848
RPATHS="${BASH_REMATCH[1]} ${RPATHS}"
49-
elif [[ $opt =~ ^-Wl,-rpath,\@loader_path/(.*)$ ]]; then
49+
elif [[ ${opt} =~ ^-Wl,-rpath,\@loader_path/(.*)$ ]]; then
5050
RPATHS="${BASH_REMATCH[1]} ${RPATHS}"
51-
elif [[ $opt == "-o" ]]; then
51+
elif [[ ${opt} == "-o" ]]; then
5252
# output is coming
5353
OUTPUT=1
5454
fi
5555
}
5656

57-
# let parse the option list
58-
for i in "$@"; do
59-
if [[ $i == @* ]]; then
57+
if [[ -f %{toolchain_path_prefix}bin/clang ]]; then
58+
execroot_path=""
59+
elif [[ ${BASH_SOURCE[0]} == "/"* ]]; then
60+
# Some consumers of `CcToolchainConfigInfo` (e.g. `cmake` from rules_foreign_cc)
61+
# change CWD and call $CC (this script) with its absolute path.
62+
# For cases like this, we'll try to find `clang` through an absolute path.
63+
# This script is at _execroot_/external/_repo_name_/bin/cc_wrapper.sh
64+
execroot_path="${BASH_SOURCE[0]%/*/*/*/*}/"
65+
else
66+
echo >&2 "ERROR: could not find clang; PWD=\"${PWD}\"; PATH=\"${PATH}\"."
67+
exit 5
68+
fi
69+
70+
function sanitize_option() {
71+
local -r opt=$1
72+
if [[ ${opt} == */cc_wrapper.sh ]]; then
73+
printf "%s" "${execroot_path}%{toolchain_path_prefix}bin/clang"
74+
elif [[ ${opt} =~ ^-fsanitize-(ignore|black)list=[^/] ]]; then
75+
# shellcheck disable=SC2206
76+
parts=(${opt/=/ }) # Split flag name and value into array.
77+
printf "%s" "${parts[0]}=${execroot_path}${parts[1]}"
78+
else
79+
printf "%s" "${opt}"
80+
fi
81+
}
82+
83+
cmd=()
84+
for ((i = 0; i <= $#; i++)); do
85+
if [[ ${!i} == @* ]]; then
6086
while IFS= read -r opt; do
61-
parse_option "$opt"
62-
done <"${i:1}" || exit 1
87+
opt="$(
88+
set -e
89+
sanitize_option "${opt}"
90+
)"
91+
parse_option "${opt}"
92+
cmd+=("${opt}")
93+
done <"${!i:1}"
6394
else
64-
parse_option "$i"
95+
opt="$(
96+
set -e
97+
sanitize_option "${!i}"
98+
)"
99+
parse_option "${opt}"
100+
cmd+=("${opt}")
65101
fi
66102
done
67103

@@ -86,27 +122,13 @@ if [[ ":${PATH}:" != *":/usr/bin:"* ]]; then
86122
fi
87123

88124
# Call the C++ compiler.
89-
if [[ -f %{toolchain_path_prefix}bin/clang ]]; then
90-
%{toolchain_path_prefix}bin/clang "$@"
91-
elif [[ ${BASH_SOURCE[0]} == "/"* ]]; then
92-
# Some consumers of `CcToolchainConfigInfo` (e.g. `cmake` from rules_foreign_cc)
93-
# change CWD and call $CC (this script) with its absolute path.
94-
# the execroot (i.e. `cmake` from `rules_foreign_cc`) and call CC . For cases like this,
95-
# we'll try to find `clang` relative to this script.
96-
# This script is at _execroot_/external/_repo_name_/bin/cc_wrapper.sh
97-
execroot_path="${BASH_SOURCE[0]%/*/*/*/*}"
98-
clang="${execroot_path}/%{toolchain_path_prefix}bin/clang"
99-
"${clang}" "${@}"
100-
else
101-
echo >&2 "ERROR: could not find clang; PWD=\"$(pwd)\"; PATH=\"${PATH}\"."
102-
exit 5
103-
fi
125+
"${cmd[@]}"
104126

105127
function get_library_path() {
106128
for libdir in ${LIB_DIRS}; do
107-
if [ -f ${libdir}/lib$1.so ]; then
129+
if [[ -f "${libdir}/lib$1".so ]]; then
108130
echo "${libdir}/lib$1.so"
109-
elif [ -f ${libdir}/lib$1.dylib ]; then
131+
elif [[ -f "${libdir}"/lib"$1".dylib ]]; then
110132
echo "${libdir}/lib$1.dylib"
111133
fi
112134
done
@@ -116,8 +138,9 @@ function get_library_path() {
116138
# and multi-level symlinks.
117139
function get_realpath() {
118140
local previous="$1"
119-
local next=$(readlink "${previous}")
120-
while [ -n "${next}" ]; do
141+
local next
142+
next="$(readlink "${previous}")"
143+
while [[ -n ${next} ]]; do
121144
previous="${next}"
122145
next=$(readlink "${previous}")
123146
done
@@ -127,24 +150,25 @@ function get_realpath() {
127150
# Get the path of a lib inside a tool
128151
function get_otool_path() {
129152
# the lib path is the path of the original lib relative to the workspace
130-
get_realpath $1 | sed 's|^.*/bazel-out/|bazel-out/|'
153+
get_realpath "$1" | sed 's|^.*/bazel-out/|bazel-out/|'
131154
}
132155

133156
# Do replacements in the output
134157
for rpath in ${RPATHS}; do
135158
for lib in ${LIBS}; do
136159
unset libname
137-
if [ -f "$(dirname ${OUTPUT})/${rpath}/lib${lib}.so" ]; then
160+
if [[ -f "$(dirname "${OUTPUT}")/${rpath}/lib${lib}.so" ]]; then
138161
libname="lib${lib}.so"
139-
elif [ -f "$(dirname ${OUTPUT})/${rpath}/lib${lib}.dylib" ]; then
162+
elif [[ -f "$(dirname "${OUTPUT}")/${rpath}/lib${lib}.dylib" ]]; then
140163
libname="lib${lib}.dylib"
141164
fi
142165
# ${libname-} --> return $libname if defined, or undefined otherwise. This is to make
143166
# this set -e friendly
144167
if [[ -n ${libname-} ]]; then
145-
libpath=$(get_library_path ${lib})
146-
if [ -n "${libpath}" ]; then
147-
${INSTALL_NAME_TOOL} -change $(get_otool_path "${libpath}") \
168+
libpath="$(get_library_path "${lib}")"
169+
if [[ -n ${libpath} ]]; then
170+
otool_path="$(get_otool_path "${libpath}")"
171+
"${INSTALL_NAME_TOOL}" -change "${otool_path}" \
148172
"@loader_path/${rpath}/${libname}" "${OUTPUT}"
149173
fi
150174
fi

0 commit comments

Comments
 (0)