Skip to content

Commit

Permalink
Copy osx_cc_wrapper.sh.tpl from bazel
Browse files Browse the repository at this point in the history
This is no longer used in bazel so we should just own it. This copies
over the relevant shell test too.
  • Loading branch information
keith committed Jan 14, 2025
1 parent 6e0fdb1 commit 045daf7
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 1 deletion.
2 changes: 1 addition & 1 deletion crosstool/osx_cc_configure.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ def configure_osx_toolchain(repository_ctx):
# https://github.com/bazelbuild/bazel/blob/ab71a1002c9c53a8061336e40f91204a2a32c38e/tools/cpp/lib_cc_configure.bzl#L17-L38
# for more info
xcode_locator = Label("@bazel_tools//tools/osx:xcode_locator.m")
osx_cc_wrapper = Label("@bazel_tools//tools/cpp:osx_cc_wrapper.sh.tpl")
osx_cc_wrapper = Label("@build_bazel_apple_support//crosstool:osx_cc_wrapper.sh.tpl")
xcrunwrapper = Label("@build_bazel_apple_support//crosstool:xcrunwrapper.sh")
libtool = Label("@build_bazel_apple_support//crosstool:libtool.sh")
make_hashed_objlist = Label("@build_bazel_apple_support//crosstool:make_hashed_objlist.py")
Expand Down
138 changes: 138 additions & 0 deletions crosstool/osx_cc_wrapper.sh.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#!/bin/bash
#
# Copyright 2015 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# 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.
#
set -eu

LIBS=
LIB_PATHS=
LIB_DIRS=
RPATHS=
OUTPUT=

function parse_option() {
local -r opt="$1"
if [[ "${OUTPUT}" = "1" ]]; then
OUTPUT=$opt
elif [[ "$opt" =~ ^-l(.*)$ ]]; then
LIBS="${BASH_REMATCH[1]} $LIBS"
elif [[ "$opt" =~ ^(.*)\.so$ ]]; then
LIB_PATHS="${opt} $LIB_PATHS"
elif [[ "$opt" =~ ^(.*)\.dylib$ ]]; then
LIB_PATHS="${opt} $LIB_PATHS"
elif [[ "$opt" =~ ^-L(.*)$ ]]; then
LIB_DIRS="${BASH_REMATCH[1]} $LIB_DIRS"
elif [[ "$opt" =~ ^\@loader_path/(.*)$ ]]; then
RPATHS="${BASH_REMATCH[1]} ${RPATHS}"
elif [[ "$opt" = "-o" ]]; then
# output is coming
OUTPUT=1
fi
}

# let parse the option list
for i in "$@"; do
if [[ "$i" = @* && -r "${i:1}" ]]; then
while IFS= read -r opt
do
parse_option "$opt"
done < "${i:1}" || exit 1
else
parse_option "$i"
fi
done

# Set-up the environment
%{env}

# Call the C++ compiler
%{cc} "$@"

# Generate an empty file if header processing succeeded.
if [[ "${OUTPUT}" == *.h.processed ]]; then
echo -n > "${OUTPUT}"
fi

function get_library_path() {
for libdir in ${LIB_DIRS}; do
if [ -f ${libdir}/lib$1.so ]; then
echo "${libdir}/lib$1.so"
elif [ -f ${libdir}/lib$1.dylib ]; then
echo "${libdir}/lib$1.dylib"
fi
done
}

# A convenient method to return the actual path even for non symlinks
# and multi-level symlinks.
function get_realpath() {
local previous="$1"
local next=$(readlink "${previous}")
while [ -n "${next}" ]; do
previous="${next}"
next=$(readlink "${previous}")
done
echo "${previous}"
}

# Get the path of a lib inside a tool
function get_otool_path() {
# the lib path is the path of the original lib relative to the workspace
get_realpath $1 | sed 's|^.*/bazel-out/|bazel-out/|'
}

function call_install_name() {
/usr/bin/xcrun install_name_tool -change $(get_otool_path "$1") \
"@loader_path/$2/$3" "${OUTPUT}"
}

# Do replacements in the output
for rpath in ${RPATHS}; do
for lib in ${LIBS}; do
unset libname
if [ -f "$(dirname ${OUTPUT})/${rpath}/lib${lib}.so" ]; then
libname="lib${lib}.so"
elif [ -f "$(dirname ${OUTPUT})/${rpath}/lib${lib}.dylib" ]; then
libname="lib${lib}.dylib"
fi
# ${libname-} --> return $libname if defined, or undefined otherwise. This is to make
# this set -e friendly
if [[ -n "${libname-}" ]]; then
libpath=$(get_library_path ${lib})
if [ -n "${libpath}" ]; then
call_install_name "${libpath}" "${rpath}" "${libname}"
fi
fi
done
for libpath in ${LIB_PATHS}; do
if [ -f "$libpath" ]; then
libname=$(basename "$libpath")
if [ -f "$(dirname ${OUTPUT})/${rpath}/${libname}" ]; then
call_install_name "${libpath}" "${rpath}" "${libname}"
fi
fi
done
done
34 changes: 34 additions & 0 deletions test/rpaths/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
load("@rules_shell//shell:sh_test.bzl", "sh_test")

cc_library(
name = "foo",
srcs = ["foo.cc"],
)

cc_binary(
name = "libbar.so",
srcs = ["bar.cc"],
linkshared = True,
)

cc_binary(
name = "libbaz.dylib",
srcs = ["baz.cc"],
linkshared = True,
)

cc_test(
name = "test",
srcs = [
"test.cc",
":libbar.so",
":libbaz.dylib",
],
deps = [":foo"],
)

sh_test(
name = "test-portable",
srcs = ["test-portable.sh"],
data = [":test"],
)
1 change: 1 addition & 0 deletions test/rpaths/bar.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
int bar() { return 12; }
1 change: 1 addition & 0 deletions test/rpaths/baz.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
int baz() { return 42; }
1 change: 1 addition & 0 deletions test/rpaths/foo.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
int foo() { return 2; }
11 changes: 11 additions & 0 deletions test/rpaths/test-portable.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash

set -euo pipefail

# Without valid rpaths the binary will only work from a specific PWD

./test/rpaths/test
cd ./test
./rpaths/test
cd ./rpaths
./test
11 changes: 11 additions & 0 deletions test/rpaths/test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
int foo();
int bar();
int baz();
int main() {
int result = foo() + bar() + baz();
if (result == 56) {
return 0;
} else {
return result;
}
}

0 comments on commit 045daf7

Please sign in to comment.