Ticket #58569: osx_cc_wrapper.sh

File osx_cc_wrapper.sh, 3.2 KB (added by dbl001 (dbl), 5 years ago)
Line 
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#
28set -eu
29
30GCC=/usr/bin/gcc
31INSTALL_NAME_TOOL="/usr/bin/install_name_tool"
32
33LIBS=
34LIB_DIRS=
35RPATHS=
36OUTPUT=
37# let parse the option list
38for i in "$@"; do
39    if [[ "${OUTPUT}" = "1" ]]; then
40        OUTPUT=$i
41    elif [[ "$i" =~ ^-l(.*)$ ]]; then
42        LIBS="${BASH_REMATCH[1]} $LIBS"
43    elif [[ "$i" =~ ^-L(.*)$ ]]; then
44        LIB_DIRS="${BASH_REMATCH[1]} $LIB_DIRS"
45    elif [[ "$i" =~ ^-Wl,-rpath,\@loader_path/(.*)$ ]]; then
46        RPATHS="${BASH_REMATCH[1]} ${RPATHS}"
47    elif [[ "$i" = "-o" ]]; then
48        # output is coming
49        OUTPUT=1
50    fi
51done
52
53# Call gcc
54${GCC} "$@"
55
56function get_library_path() {
57    for libdir in ${LIB_DIRS}; do
58        if [ -f ${libdir}/lib$1.so ]; then
59            echo "${libdir}/lib$1.so"
60        elif [ -f ${libdir}/lib$1.dylib ]; then
61            echo "${libdir}/lib$1.dylib"
62        fi
63    done
64}
65
66# A convenient method to return the actual path even for non symlinks
67# and multi-level symlinks.
68function get_realpath() {
69    local previous="$1"
70    local next=$(readlink "${previous}")
71    while [ -n "${next}" ]; do
72        previous="${next}"
73        next=$(readlink "${previous}")
74    done
75    echo "${previous}"
76}
77
78# Get the path of a lib inside a tool
79function get_otool_path() {
80    # the lib path is the path of the original lib relative to the workspace
81    get_realpath $1 | sed 's|^.*/bazel-out/|bazel-out/|'
82}
83
84# Do replacements in the output
85for rpath in ${RPATHS}; do
86    for lib in ${LIBS}; do
87        unset libname
88        if [ -f "$(dirname ${OUTPUT})/${rpath}/lib${lib}.so" ]; then
89            libname="lib${lib}.so"
90        elif [ -f "$(dirname ${OUTPUT})/${rpath}/lib${lib}.dylib" ]; then
91            libname="lib${lib}.dylib"
92        fi
93        # ${libname-} --> return $libname if defined, or undefined otherwise. This is to make
94        # this set -e friendly
95        if [[ -n "${libname-}" ]]; then
96            libpath=$(get_library_path ${lib})
97            if [ -n "${libpath}" ]; then
98                ${INSTALL_NAME_TOOL} -change $(get_otool_path "${libpath}") \
99                    "@loader_path/${rpath}/${libname}" "${OUTPUT}"
100            fi
101        fi
102    done
103done
104