blob: c8bcd183c1351734d2511154cffe6a20de62a5fc [file] [log] [blame]
#!/bin/bash
#
# Copyright 2016 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.
#
# libtool.sh runs the command passed to it using "xcrunwrapper libtool".
#
# It creates symbolic links for all input files with a path-hash appended
# to their original name (foo.o becomes foo_{md5sum}.o). This is to circumvent
# a bug in the original libtool that arises when two input files have the same
# base name (even if they are in different directories).
set -eu
# A trick to allow invoking this script in multiple contexts.
if [ -z ${MY_LOCATION+x} ]; then
if [ -d "$0.runfiles/" ]; then
MY_LOCATION="$0.runfiles/bazel_tools/tools/objc"
else
MY_LOCATION="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
fi
fi
function invoke_libtool() {
# Just invoke libtool via xcrunwrapper
"${MY_LOCATION}/xcrunwrapper.sh" libtool "$@" \
2> >(grep -v "the table of contents is empty (no object file members in the"`
`" library define global symbols)$" >&2)
# ^ Filtering a warning that's unlikely to indicate a real issue
# ...and not silencable via a flag.
}
if [ ! -f "${MY_LOCATION}"/libtool_check_unique ] ; then
echo "libtool_check_unique not found. Please file an issue at github.com/bazelbuild/bazel"
exit 1
elif "${MY_LOCATION}"/libtool_check_unique "$@"; then
# If there are no duplicate .o basenames,
# libtool can be invoked with the original arguments.
invoke_libtool "$@"
exit
fi
TEMPDIR="$(mktemp -d "${TMPDIR:-/tmp}/libtool.XXXXXXXX")"
trap 'rm -rf "$TEMPDIR"' EXIT
# Creates a symbolic link to the input argument file and returns the symlink
# file path.
function hash_objfile() {
ORIGINAL_NAME="$1"
ORIGINAL_HASH="$(/sbin/md5 -qs "${ORIGINAL_NAME}")"
SYMLINK_NAME="${TEMPDIR}/$(basename "${ORIGINAL_NAME%.o}_${ORIGINAL_HASH}.o")"
if [[ ! -e "$SYMLINK_NAME" ]]; then
case "${ORIGINAL_NAME}" in
/*) ln -sf "$ORIGINAL_NAME" "$SYMLINK_NAME" ;;
*) ln -sf "$(pwd)/$ORIGINAL_NAME" "$SYMLINK_NAME" ;;
esac
fi
echo "$SYMLINK_NAME"
}
python_executable=/usr/bin/python3
if [[ ! -x "$python_executable" ]]; then
python_executable=python3
fi
ARGS=()
handle_filelist=0
keep_next=0
function parse_option() {
local -r ARG="$1"
if [[ "$handle_filelist" == "1" ]]; then
handle_filelist=0
HASHED_FILELIST="${ARG%.objlist}_hashes.objlist"
rm -f "${HASHED_FILELIST}"
# Use python helper script for fast md5 calculation of many strings.
"$python_executable" "${MY_LOCATION}/make_hashed_objlist.py" \
"${ARG}" "${HASHED_FILELIST}" "${TEMPDIR}"
ARGS+=("${HASHED_FILELIST}")
elif [[ "$keep_next" == "1" ]]; then
keep_next=0
ARGS+=("$ARG")
else
case "${ARG}" in
# Filelist flag, need to symlink each input in the contents of file and
# pass a new filelist which contains the symlinks.
-filelist)
handle_filelist=1
ARGS+=("${ARG}")
;;
@*)
path="${ARG:1}"
while IFS= read -r opt
do
parse_option "$opt"
done < "$path" || exit 1
;;
# Flags with no args
-static|-s|-a|-c|-L|-T|-D|-no_warning_for_no_symbols)
ARGS+=("${ARG}")
;;
# Single-arg flags
-arch_only|-syslibroot|-o)
keep_next=1
ARGS+=("${ARG}")
;;
# Any remaining flags are unexpected and may ruin flag parsing.
# Add any flags here to libtool_check_unique.cc as well
-*)
echo "Unrecognized libtool flag ${ARG}"
exit 1
;;
# Archive inputs can remain untouched, as they come from other targets.
*.a)
ARGS+=("${ARG}")
;;
# Remaining args are input objects
*)
ARGS+=("$(hash_objfile "${ARG}")")
;;
esac
fi
}
for arg in "$@"; do
parse_option "$arg"
done
printf '%s\n' "${ARGS[@]}" > "$TEMPDIR/processed.params"
invoke_libtool "@$TEMPDIR/processed.params"