diff --git a/toolchain/cc_wrapper.sh.tpl b/toolchain/cc_wrapper.sh.tpl index b3cb2338..16c24eff 100644 --- a/toolchain/cc_wrapper.sh.tpl +++ b/toolchain/cc_wrapper.sh.tpl @@ -14,17 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# OS X relpath is not really working. This is a wrapper script around gcc -# to simulate relpath behavior. -# -# This wrapper uses install_name_tool to replace all paths in the binary -# (bazel-out/.../path/to/original/library.so) by the paths relative to -# the binary. It parses the command line to behave as rpath is supposed -# to work. -# -# See https://blogs.oracle.com/dipol/entry/dynamic_libraries_rpath_and_mac -# on how to set those paths for Mach-O binaries. - # shellcheck disable=SC1083 set -euo pipefail @@ -42,27 +31,65 @@ trap cleanup EXIT # See note in toolchain/internal/configure.bzl where we define # `wrapper_bin_prefix` for why this wrapper is needed. -if [[ -f %{toolchain_path_prefix}bin/clang ]]; then - execroot_path="" -elif [[ ${BASH_SOURCE[0]} == "/"* ]]; then - # Some consumers of `CcToolchainConfigInfo` (e.g. `cmake` from rules_foreign_cc) - # change CWD and call $CC (this script) with its absolute path. - # For cases like this, we'll try to find `clang` through an absolute path. - # This script is at _execroot_/external/_repo_name_/bin/cc_wrapper.sh - execroot_path="${BASH_SOURCE[0]%/*/*/*/*}/" -else - echo >&2 "ERROR: could not find clang; PWD=\"${PWD}\"; PATH=\"${PATH}\"." +# this script is located at either +# - /external//bin/cc_wrapper.sh +# - //bin/cc_wrapper.sh +# The clang is located at +# - /external//bin/clang +# - //bin/clang +# +# In both cases, getting to clang can be done via +# Finding the current dir of this script, +# - /external//bin/ +# - //bin/ +# going back 2 directories +# - /external +# - +# +# Going into %{toolchain_path_prefix} without the `external/` prefix + `bin/clang` +# + +dirname_shim() { + local path="$1" + + # Remove trailing slashes + path="${path%/}" + + # If there's no slash, return "." + if [[ "${path}" != */* ]]; then + echo "." + return + fi + + # Remove the last component after the final slash + path="${path%/*}" + + # If it becomes empty, it means root "/" + echo "${path:-/}" +} + +script_dir=$(dirname_shim "${BASH_SOURCE[0]}") +toolchain_path_prefix="%{toolchain_path_prefix}" + +# Sometimes this path may be an absolute path in which case we dont do anything because +# This is using the host toolchain to build. +if [[ ${toolchain_path_prefix} != /* ]]; then + toolchain_path_prefix="${script_dir}/../../${toolchain_path_prefix#external/}" +fi + +if [[ ! -f ${toolchain_path_prefix}bin/clang ]]; then + echo >&2 "ERROR: could not find clang; PWD=\"${PWD}\"; PATH=\"${PATH}\"; toolchain_path_prefix=${toolchain_path_prefix}." exit 5 fi function sanitize_option() { local -r opt=$1 if [[ ${opt} == */cc_wrapper.sh ]]; then - printf "%s" "${execroot_path}%{toolchain_path_prefix}bin/clang" - elif [[ ${opt} =~ ^-fsanitize-(ignore|black)list=[^/] ]]; then + printf "%s" "${toolchain_path_prefix}bin/clang" + elif [[ ${opt} =~ ^-fsanitize-(ignore|black)list=[^/] ]] && [[ ${script_dir} == /* ]]; then # shellcheck disable=SC2206 parts=(${opt/=/ }) # Split flag name and value into array. - printf "%s" "${parts[0]}=${execroot_path}${parts[1]}" + printf "%s" "${parts[0]}=${script_dir}/../../../${parts[1]}" else printf "%s" "${opt}" fi diff --git a/toolchain/osx_cc_wrapper.sh.tpl b/toolchain/osx_cc_wrapper.sh.tpl index a005caa3..6363eb43 100755 --- a/toolchain/osx_cc_wrapper.sh.tpl +++ b/toolchain/osx_cc_wrapper.sh.tpl @@ -63,31 +63,72 @@ function parse_option() { fi } -if [[ -f %{toolchain_path_prefix}bin/clang ]]; then - execroot_path="" - execroot_abs_path="${PWD}/" -elif [[ ${BASH_SOURCE[0]} == "/"* ]]; then - # Some consumers of `CcToolchainConfigInfo` (e.g. `cmake` from rules_foreign_cc) - # change CWD and call $CC (this script) with its absolute path. - # For cases like this, we'll try to find `clang` through an absolute path. - # This script is at _execroot_/external/_repo_name_/bin/cc_wrapper.sh - execroot_path="${BASH_SOURCE[0]%/*/*/*/*}/" - execroot_abs_path="$(cd "${execroot_path}" && pwd -P)/" +# See note in toolchain/internal/configure.bzl where we define +# `wrapper_bin_prefix` for why this wrapper is needed. + +# this script is located at either +# - /external//bin/cc_wrapper.sh +# - //bin/cc_wrapper.sh +# The clang is located at +# - /external//bin/clang +# - //bin/clang +# +# In both cases, getting to clang can be done via +# Finding the current dir of this script, +# - /external//bin/ +# - //bin/ +# going back 2 directories +# - /external +# - +# +# Going into %{toolchain_path_prefix} without the `external/` prefix + `bin/clang` +# + +dirname_shim() { + local path="$1" + + # Remove trailing slashes + path="${path%/}" + + # If there's no slash, return "." + if [[ "${path}" != */* ]]; then + echo "." + return + fi + + # Remove the last component after the final slash + path="${path%/*}" + + # If it becomes empty, it means root "/" + echo "${path:-/}" +} + +script_dir=$(dirname_shim "${BASH_SOURCE[0]}") +toolchain_path_prefix="%{toolchain_path_prefix}" +# Sometimes this path may be an absolute path in which case we dont do anything because +# This is using the host toolchain to build. +if [[ ${toolchain_path_prefix} != /* ]]; then + toolchain_path_prefix="${script_dir}/../../${toolchain_path_prefix#external/}" + toolchain_path_prefix_abs="$(cd "${toolchain_path_prefix}" && pwd -P)/" else - echo >&2 "ERROR: could not find clang; PWD=\"${PWD}\"; PATH=\"${PATH}\"." + toolchain_path_prefix_abs="${toolchain_path_prefix}" +fi + +if [[ ! -f ${toolchain_path_prefix}bin/clang ]]; then + echo >&2 "ERROR: could not find clang; PWD=\"${PWD}\"; PATH=\"${PATH}\"; toolchain_path_prefix=${toolchain_path_prefix}." exit 5 fi function sanitize_option() { local -r opt=$1 if [[ ${opt} == */cc_wrapper.sh ]]; then - printf "%s" "${execroot_path}%{toolchain_path_prefix}bin/clang" + printf "%s" "${toolchain_path_prefix}bin/clang" elif [[ ${opt} == "-fuse-ld=ld64.lld" ]]; then - echo "--ld-path=${execroot_abs_path}%{toolchain_path_prefix}bin/ld64.lld" - elif [[ ${opt} =~ ^-fsanitize-(ignore|black)list=[^/] ]]; then + echo "--ld-path=${toolchain_path_prefix_abs}bin/ld64.lld" + elif [[ ${opt} =~ ^-fsanitize-(ignore|black)list=[^/] ]] && [[ ${script_dir} == /* ]]; then # shellcheck disable=SC2206 parts=(${opt/=/ }) # Split flag name and value into array. - printf "%s" "${parts[0]}=${execroot_path}${parts[1]}" + printf "%s" "${parts[0]}=${script_dir}/../../../${parts[1]}" else printf "%s" "${opt}" fi