Skip to content

Commit a165a72

Browse files
authored
Copy osx_cc_wrapper.sh.tpl from bazel (#357)
1 parent 6e0fdb1 commit a165a72

File tree

8 files changed

+199
-1
lines changed

8 files changed

+199
-1
lines changed

crosstool/osx_cc_configure.bzl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ def configure_osx_toolchain(repository_ctx):
163163
# https://github.com/bazelbuild/bazel/blob/ab71a1002c9c53a8061336e40f91204a2a32c38e/tools/cpp/lib_cc_configure.bzl#L17-L38
164164
# for more info
165165
xcode_locator = Label("@bazel_tools//tools/osx:xcode_locator.m")
166-
osx_cc_wrapper = Label("@bazel_tools//tools/cpp:osx_cc_wrapper.sh.tpl")
166+
osx_cc_wrapper = Label("@build_bazel_apple_support//crosstool:osx_cc_wrapper.sh.tpl")
167167
xcrunwrapper = Label("@build_bazel_apple_support//crosstool:xcrunwrapper.sh")
168168
libtool = Label("@build_bazel_apple_support//crosstool:libtool.sh")
169169
make_hashed_objlist = Label("@build_bazel_apple_support//crosstool:make_hashed_objlist.py")

crosstool/osx_cc_wrapper.sh.tpl

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
#!/bin/bash
2+
#
3+
# Copyright 2015 The Bazel Authors. All rights reserved.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
# OS X relpath is not really working. This is a wrapper script around gcc
18+
# to simulate relpath behavior.
19+
#
20+
# This wrapper uses install_name_tool to replace all paths in the binary
21+
# (bazel-out/.../path/to/original/library.so) by the paths relative to
22+
# the binary. It parses the command line to behave as rpath is supposed
23+
# to work.
24+
#
25+
# See https://blogs.oracle.com/dipol/entry/dynamic_libraries_rpath_and_mac
26+
# on how to set those paths for Mach-O binaries.
27+
#
28+
set -eu
29+
30+
LIBS=
31+
LIB_PATHS=
32+
LIB_DIRS=
33+
RPATHS=
34+
OUTPUT=
35+
36+
function parse_option() {
37+
local -r opt="$1"
38+
if [[ "${OUTPUT}" = "1" ]]; then
39+
OUTPUT=$opt
40+
elif [[ "$opt" =~ ^-l(.*)$ ]]; then
41+
LIBS="${BASH_REMATCH[1]} $LIBS"
42+
elif [[ "$opt" =~ ^(.*)\.so$ ]]; then
43+
LIB_PATHS="${opt} $LIB_PATHS"
44+
elif [[ "$opt" =~ ^(.*)\.dylib$ ]]; then
45+
LIB_PATHS="${opt} $LIB_PATHS"
46+
elif [[ "$opt" =~ ^-L(.*)$ ]]; then
47+
LIB_DIRS="${BASH_REMATCH[1]} $LIB_DIRS"
48+
elif [[ "$opt" =~ ^\@loader_path/(.*)$ ]]; then
49+
RPATHS="${BASH_REMATCH[1]} ${RPATHS}"
50+
elif [[ "$opt" = "-o" ]]; then
51+
# output is coming
52+
OUTPUT=1
53+
fi
54+
}
55+
56+
# let parse the option list
57+
for i in "$@"; do
58+
if [[ "$i" = @* && -r "${i:1}" ]]; then
59+
while IFS= read -r opt
60+
do
61+
parse_option "$opt"
62+
done < "${i:1}" || exit 1
63+
else
64+
parse_option "$i"
65+
fi
66+
done
67+
68+
# Set-up the environment
69+
%{env}
70+
71+
# Call the C++ compiler
72+
%{cc} "$@"
73+
74+
# Generate an empty file if header processing succeeded.
75+
if [[ "${OUTPUT}" == *.h.processed ]]; then
76+
echo -n > "${OUTPUT}"
77+
fi
78+
79+
function get_library_path() {
80+
for libdir in ${LIB_DIRS}; do
81+
if [ -f ${libdir}/lib$1.so ]; then
82+
echo "${libdir}/lib$1.so"
83+
elif [ -f ${libdir}/lib$1.dylib ]; then
84+
echo "${libdir}/lib$1.dylib"
85+
fi
86+
done
87+
}
88+
89+
# A convenient method to return the actual path even for non symlinks
90+
# and multi-level symlinks.
91+
function get_realpath() {
92+
local previous="$1"
93+
local next=$(readlink "${previous}")
94+
while [ -n "${next}" ]; do
95+
previous="${next}"
96+
next=$(readlink "${previous}")
97+
done
98+
echo "${previous}"
99+
}
100+
101+
# Get the path of a lib inside a tool
102+
function get_otool_path() {
103+
# the lib path is the path of the original lib relative to the workspace
104+
get_realpath $1 | sed 's|^.*/bazel-out/|bazel-out/|'
105+
}
106+
107+
function call_install_name() {
108+
/usr/bin/xcrun install_name_tool -change $(get_otool_path "$1") \
109+
"@loader_path/$2/$3" "${OUTPUT}"
110+
}
111+
112+
# TODO: Remove when --incompatible_macos_set_install_name is not disable-able
113+
# Do replacements in the output
114+
for rpath in ${RPATHS}; do
115+
for lib in ${LIBS}; do
116+
unset libname
117+
if [ -f "$(dirname ${OUTPUT})/${rpath}/lib${lib}.so" ]; then
118+
libname="lib${lib}.so"
119+
elif [ -f "$(dirname ${OUTPUT})/${rpath}/lib${lib}.dylib" ]; then
120+
libname="lib${lib}.dylib"
121+
fi
122+
# ${libname-} --> return $libname if defined, or undefined otherwise. This is to make
123+
# this set -e friendly
124+
if [[ -n "${libname-}" ]]; then
125+
libpath=$(get_library_path ${lib})
126+
if [ -n "${libpath}" ]; then
127+
call_install_name "${libpath}" "${rpath}" "${libname}"
128+
fi
129+
fi
130+
done
131+
for libpath in ${LIB_PATHS}; do
132+
if [ -f "$libpath" ]; then
133+
libname=$(basename "$libpath")
134+
if [ -f "$(dirname ${OUTPUT})/${rpath}/${libname}" ]; then
135+
call_install_name "${libpath}" "${rpath}" "${libname}"
136+
fi
137+
fi
138+
done
139+
done

test/rpaths/BUILD

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
load("@rules_shell//shell:sh_test.bzl", "sh_test")
2+
3+
cc_library(
4+
name = "foo",
5+
srcs = ["foo.cc"],
6+
)
7+
8+
cc_binary(
9+
name = "libbar.so",
10+
srcs = ["bar.cc"],
11+
linkshared = True,
12+
)
13+
14+
cc_binary(
15+
name = "libbaz.dylib",
16+
srcs = ["baz.cc"],
17+
linkshared = True,
18+
)
19+
20+
cc_test(
21+
name = "test",
22+
srcs = [
23+
"test.cc",
24+
":libbar.so",
25+
":libbaz.dylib",
26+
],
27+
deps = [":foo"],
28+
)
29+
30+
sh_test(
31+
name = "test-portable",
32+
srcs = ["test-portable.sh"],
33+
data = [":test"],
34+
)

test/rpaths/bar.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
int bar() { return 12; }

test/rpaths/baz.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
int baz() { return 42; }

test/rpaths/foo.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
int foo() { return 2; }

test/rpaths/test-portable.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/bin/bash
2+
3+
set -euo pipefail
4+
5+
# Without valid rpaths the binary will only work from a specific PWD
6+
7+
./test/rpaths/test
8+
cd ./test
9+
./rpaths/test
10+
cd ./rpaths
11+
./test

test/rpaths/test.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
int foo();
2+
int bar();
3+
int baz();
4+
int main() {
5+
int result = foo() + bar() + baz();
6+
if (result == 56) {
7+
return 0;
8+
} else {
9+
return result;
10+
}
11+
}

0 commit comments

Comments
 (0)