blob: 8c9c111a750587b023d188cca9ac195d46ef54bb [file] [log] [blame]
Damien Martin-Guillerez28ac6152015-03-25 19:46:39 +00001#!/bin/bash
2#
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00003# Copyright 2015 The Bazel Authors. All rights reserved.
Damien Martin-Guillerez28ac6152015-03-25 19:46:39 +00004#
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#
Damien Martin-Guillerez8fa5ae62016-03-02 16:24:13 +000017# OS X relpath is not really working. This is a wrapper script around gcc
18# to simulate relpath behavior.
Damien Martin-Guillerez28ac6152015-03-25 19:46:39 +000019#
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
Damien Martin-Guillerez8fa5ae62016-03-02 16:24:13 +000022# the binary. It parses the command line to behave as rpath is supposed
Damien Martin-Guillerez28ac6152015-03-25 19:46:39 +000023# 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
Damien Martin-Guillerez8fa5ae62016-03-02 16:24:13 +000030GCC=/usr/bin/gcc
Damien Martin-Guillerez28ac6152015-03-25 19:46:39 +000031INSTALL_NAME_TOOL="/usr/bin/install_name_tool"
32
33LIBS=
34LIB_DIRS=
Marcel Hlopkof4265442017-08-17 22:13:39 +020035RPATHS=
Damien Martin-Guillerez28ac6152015-03-25 19:46:39 +000036OUTPUT=
Keith Smileyf08819b2020-11-12 03:13:54 -080037
38function parse_option() {
39 local -r opt="$1"
ilist7ca5d7d2020-11-04 06:48:17 -080040 if [[ "${OUTPUT}" = "1" ]]; then
Keith Smileyf08819b2020-11-12 03:13:54 -080041 OUTPUT=$opt
42 elif [[ "$opt" =~ ^-l(.*)$ ]]; then
ilist7ca5d7d2020-11-04 06:48:17 -080043 LIBS="${BASH_REMATCH[1]} $LIBS"
Keith Smileyf08819b2020-11-12 03:13:54 -080044 elif [[ "$opt" =~ ^-L(.*)$ ]]; then
ilist7ca5d7d2020-11-04 06:48:17 -080045 LIB_DIRS="${BASH_REMATCH[1]} $LIB_DIRS"
Keith Smileyf08819b2020-11-12 03:13:54 -080046 elif [[ "$opt" =~ ^-Wl,-rpath,\@loader_path/(.*)$ ]]; then
ilist7ca5d7d2020-11-04 06:48:17 -080047 RPATHS="${BASH_REMATCH[1]} ${RPATHS}"
Keith Smileyf08819b2020-11-12 03:13:54 -080048 elif [[ "$opt" = "-o" ]]; then
ilist7ca5d7d2020-11-04 06:48:17 -080049 # output is coming
50 OUTPUT=1
Keith Smileyd3fc2532020-11-03 04:06:30 -080051 fi
Keith Smileyf08819b2020-11-12 03:13:54 -080052}
53
54# let parse the option list
55for i in "$@"; do
56 if [[ "$i" = @* ]]; then
57 while IFS= read -r opt
58 do
59 parse_option "$opt"
60 done < "${i:1}" || exit 1
61 else
62 parse_option "$i"
63 fi
Damien Martin-Guillerez28ac6152015-03-25 19:46:39 +000064done
65
66# Call gcc
67${GCC} "$@"
68
69function get_library_path() {
70 for libdir in ${LIB_DIRS}; do
Ulf Adams8284bd72015-08-19 11:27:02 +000071 if [ -f ${libdir}/lib$1.so ]; then
72 echo "${libdir}/lib$1.so"
hlopko600ab492017-10-12 18:30:29 +020073 elif [ -f ${libdir}/lib$1.dylib ]; then
74 echo "${libdir}/lib$1.dylib"
Damien Martin-Guillerez28ac6152015-03-25 19:46:39 +000075 fi
76 done
77}
78
79# A convenient method to return the actual path even for non symlinks
80# and multi-level symlinks.
81function get_realpath() {
82 local previous="$1"
83 local next=$(readlink "${previous}")
84 while [ -n "${next}" ]; do
85 previous="${next}"
86 next=$(readlink "${previous}")
87 done
88 echo "${previous}"
89}
90
91# Get the path of a lib inside a tool
92function get_otool_path() {
93 # the lib path is the path of the original lib relative to the workspace
94 get_realpath $1 | sed 's|^.*/bazel-out/|bazel-out/|'
95}
96
97# Do replacements in the output
Marcel Hlopkof4265442017-08-17 22:13:39 +020098for rpath in ${RPATHS}; do
Damien Martin-Guillerez28ac6152015-03-25 19:46:39 +000099 for lib in ${LIBS}; do
hlopko4f5a92b2017-12-12 04:34:58 -0800100 unset libname
hlopko600ab492017-10-12 18:30:29 +0200101 if [ -f "$(dirname ${OUTPUT})/${rpath}/lib${lib}.so" ]; then
102 libname="lib${lib}.so"
103 elif [ -f "$(dirname ${OUTPUT})/${rpath}/lib${lib}.dylib" ]; then
104 libname="lib${lib}.dylib"
105 fi
106 # ${libname-} --> return $libname if defined, or undefined otherwise. This is to make
107 # this set -e friendly
108 if [[ -n "${libname-}" ]]; then
Marcel Hlopkof4265442017-08-17 22:13:39 +0200109 libpath=$(get_library_path ${lib})
110 if [ -n "${libpath}" ]; then
111 ${INSTALL_NAME_TOOL} -change $(get_otool_path "${libpath}") \
hlopko600ab492017-10-12 18:30:29 +0200112 "@loader_path/${rpath}/${libname}" "${OUTPUT}"
Marcel Hlopkof4265442017-08-17 22:13:39 +0200113 fi
Damien Martin-Guillerez28ac6152015-03-25 19:46:39 +0000114 fi
115 done
Marcel Hlopkof4265442017-08-17 22:13:39 +0200116done