#!/bin/sh # # Copyright (C) 2009 Google Inc. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # usage: adjust_visibility.sh INPUT OUTPUT WORK_DIR # # Transforms a static library at INPUT by marking all of its symbols # private_extern. The output is placed at OUTPUT. WORK_DIR is used as a # scratch directory, which need not exist before this script is invoked, # and which will be left behind when the script exits. set -e if [ $# -ne 3 ] ; then echo "usage: ${0} INPUT OUTPUT WORK_DIR" >& 2 exit 1 fi INPUT="${1}" OUTPUT="${2}" WORK_DIR="${3}" # Start with a clean slate. rm -f "${OUTPUT}" rm -rf "${WORK_DIR}" mkdir -p "${WORK_DIR}" # ar doesn't operate on fat files. Figure out what architectures are # involved. ARCHS=$(file "${INPUT}" | sed -Ene 's/^.*\(for architecture (.+)\):.*$/\1/p') if [ -z "${ARCHS}" ] ; then ARCHS=self fi OUTPUT_NAME="output.a" for ARCH in ${ARCHS} ; do # Get a thin version of fat input by running lipo. If the input is already # thin, just copy it into place. The extra copy isn't strictly necessary # but it simplifies the script. ARCH_DIR="${WORK_DIR}/${ARCH}" mkdir -p "${ARCH_DIR}" INPUT_NAME=input.a ARCH_INPUT="${ARCH_DIR}/${INPUT_NAME}" if [ "${ARCHS}" = "self" ] ; then cp "${INPUT}" "${ARCH_INPUT}" else lipo -thin "${ARCH}" "${INPUT}" -output "${ARCH_INPUT}" fi # Change directories to extract the archive to ensure correct pathnames. (cd "${ARCH_DIR}" && ar -x "${INPUT_NAME}") # Use ld -r to relink each object that was in the archive. Providing an # empty -exported_symbols_list will transform all symbols to private_extern; # these symbols are retained with -keep_private_externs. for OBJECT in "${ARCH_DIR}/"*.o ; do NEW_OBJECT="${OBJECT}.new" ld -o "${NEW_OBJECT}" -r "${OBJECT}" \ -exported_symbols_list /dev/null -keep_private_externs mv "${NEW_OBJECT}" "${OBJECT}" done # Build an architecture-specific archive from the modified object files. ARCH_OUTPUT="${ARCH_DIR}/${OUTPUT_NAME}" (cd "${ARCH_DIR}" && ar -rc "${OUTPUT_NAME}" *.o) ranlib "${ARCH_OUTPUT}" # Toss the object files out now that they're in the archive. rm -f "${ARCH_DIR}/"*.o done # Create a fat archive from the architecture-specific archives if needed. # If the input was thin, leave the output thin by copying the only output # archive to the destination. if [ "${ARCHS}" = "self" ] ; then cp "${WORK_DIR}/self/${OUTPUT_NAME}" "${OUTPUT}" else lipo -create -output "${OUTPUT}" "${WORK_DIR}/"*"/${OUTPUT_NAME}" fi