diff options
author | 2015-03-25 19:46:39 +0000 | |
---|---|---|
committer | 2015-03-25 20:07:14 +0000 | |
commit | 28ac615402bfbba56fbcbc6b4f3f51fca8bc9612 (patch) | |
tree | fab35ad69246a14209c4ff5450ff88764f4ff1b1 | |
parent | bf9b63b46142836a0c329b3c4b389c72462071b2 (diff) |
Use a wrapper around gcc on OSX to simulate rpath
OS X does not have rpath so binary fails when not executing
from the good path. This wrapper rewrite the path after the
compilation to fix that behavior.
Fixes #46
--
MOS_MIGRATED_REVID=89527942
-rwxr-xr-x | src/test/shell/bazel/bazel_example_test.sh | 6 | ||||
-rw-r--r-- | tools/cpp/CROSSTOOL | 2 | ||||
-rwxr-xr-x | tools/cpp/osx_gcc_wrapper.sh | 94 |
3 files changed, 96 insertions, 6 deletions
diff --git a/src/test/shell/bazel/bazel_example_test.sh b/src/test/shell/bazel/bazel_example_test.sh index 998f765535..a9d267209c 100755 --- a/src/test/shell/bazel/bazel_example_test.sh +++ b/src/test/shell/bazel/bazel_example_test.sh @@ -31,11 +31,7 @@ function set_up() { function test_cpp() { assert_build "//examples/cpp:hello-world" assert_bazel_run "//examples/cpp:hello-world foo" "Hello foo" - if [ "${PLATFORM}" = "darwin" ]; then - echo "Under OSX, skipping //examples/cpp:hello-success_test" - else - assert_test_ok "//examples/cpp:hello-success_test" - fi + assert_test_ok "//examples/cpp:hello-success_test" assert_test_fails "//examples/cpp:hello-fail_test" } diff --git a/tools/cpp/CROSSTOOL b/tools/cpp/CROSSTOOL index 073714d6bc..8bf19dea43 100644 --- a/tools/cpp/CROSSTOOL +++ b/tools/cpp/CROSSTOOL @@ -69,7 +69,7 @@ toolchain { tool_path { name: "compat-ld" path: "/usr/bin/ld" } tool_path { name: "cpp" path: "/usr/bin/cpp" } tool_path { name: "dwp" path: "/usr/bin/dwp" } - tool_path { name: "gcc" path: "/usr/bin/gcc" } + tool_path { name: "gcc" path: "osx_gcc_wrapper.sh" } cxx_flag: "-std=c++0x" ar_flag: "-static" ar_flag: "-s" diff --git a/tools/cpp/osx_gcc_wrapper.sh b/tools/cpp/osx_gcc_wrapper.sh new file mode 100755 index 0000000000..a8eb46ab8f --- /dev/null +++ b/tools/cpp/osx_gcc_wrapper.sh @@ -0,0 +1,94 @@ +#!/bin/bash +# +# Copyright 2015 Google Inc. 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 rpath is not really working. This is a wrapper script around gcc +# to simulate rpath 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 behaves 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 + +GCC="/usr/bin/gcc" +INSTALL_NAME_TOOL="/usr/bin/install_name_tool" + +LIBS= +LIB_DIRS= +RPATH= +OUTPUT= +# let parse the option list +for i in "$@"; do + if [[ "${OUTPUT}" = "1" ]]; then + OUTPUT=$i + elif [[ "$i" =~ ^-l(.*)$ ]]; then + # lib + LIBS="${BASH_REMATCH[1]} $LIBS" + elif [[ "$i" =~ ^-L(.*)$ ]]; then + # lib + LIB_DIRS="${BASH_REMATCH[1]} $LIB_DIRS" + elif [[ "$i" =~ ^-Wl,-rpath,\$ORIGIN/(.*)$ ]]; then + # rpath + RPATH=${BASH_REMATCH[1]} + elif [[ "$i" = "-o" ]]; then + # output is coming + OUTPUT=1 + fi +done + +# Call gcc +${GCC} "$@" + +function get_library_path() { + for libdir in ${LIB_DIRS}; do + if [ -f ${libdir}/lib$1.so ]; then + echo "${libdir}/lib$1.so" + 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/|' +} + +# Do replacements in the output +if [ -n "${RPATH}" ]; then + for lib in ${LIBS}; do + libpath=$(get_library_path ${lib}) + if [ -n "${libpath}" ]; then + ${INSTALL_NAME_TOOL} -change $(get_otool_path "${libpath}") "@loader_path/${RPATH}/lib${lib}.so" "${OUTPUT}" + fi + done +fi + |