Wed, 31 Dec 2014 13:27:57 +0100
Ignore runtime configuration files generated during quality assurance.
michael@0 | 1 | #!/bin/bash |
michael@0 | 2 | |
michael@0 | 3 | # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
michael@0 | 4 | # Use of this source code is governed by a BSD-style license that can be |
michael@0 | 5 | # found in the LICENSE file. |
michael@0 | 6 | |
michael@0 | 7 | # Copies a framework to its new home, "unversioning" it. |
michael@0 | 8 | # |
michael@0 | 9 | # Normally, frameworks are versioned bundles. The contents of a framework are |
michael@0 | 10 | # stored in a versioned directory within the bundle, and symbolic links |
michael@0 | 11 | # provide access to the actual code and resources. See |
michael@0 | 12 | # http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html |
michael@0 | 13 | # |
michael@0 | 14 | # The symbolic links usually found in frameworks create problems. Symbolic |
michael@0 | 15 | # links are excluded from code signatures. That means that it's possible to |
michael@0 | 16 | # remove or retarget a symbolic link within a framework without affecting the |
michael@0 | 17 | # seal. In Chrome's case, the outer .app bundle contains a framework where |
michael@0 | 18 | # all application code and resources live. In order for the signature on the |
michael@0 | 19 | # .app to be meaningful, it encompasses the framework. Because framework |
michael@0 | 20 | # resources are accessed through the framework's symbolic links, this |
michael@0 | 21 | # arrangement results in a case where the resources can be altered without |
michael@0 | 22 | # affecting the .app signature's validity. |
michael@0 | 23 | # |
michael@0 | 24 | # Indirection through symbolic links also carries a runtime performance |
michael@0 | 25 | # penalty on open() operations, although open() typically completes so quickly |
michael@0 | 26 | # that this is not considered a major performance problem. |
michael@0 | 27 | # |
michael@0 | 28 | # To resolve these problems, the frameworks that ship within Chrome's .app |
michael@0 | 29 | # bundle are unversioned. Unversioning is simple: instead of using the |
michael@0 | 30 | # original outer .framework directory as the framework that ships within the |
michael@0 | 31 | # .app, the inner versioned directory is used. Instead of accessing bundled |
michael@0 | 32 | # resources through symbolic links, they are accessed directly. In normal |
michael@0 | 33 | # situations, the only hard-coded use of the versioned directory is by dyld, |
michael@0 | 34 | # when loading the framework's code, but this is handled through a normal |
michael@0 | 35 | # Mach-O load command, and it is easy to adjust the load command to point to |
michael@0 | 36 | # the unversioned framework code rather than the versioned counterpart. |
michael@0 | 37 | # |
michael@0 | 38 | # The resulting framework bundles aren't strictly conforming, but they work |
michael@0 | 39 | # as well as normal versioned framework bundles. |
michael@0 | 40 | # |
michael@0 | 41 | # An option to skip running install_name_tool is available. By passing -I as |
michael@0 | 42 | # the first argument to this script, install_name_tool will be skipped. This |
michael@0 | 43 | # is only suitable for copied frameworks that will not be linked against, or |
michael@0 | 44 | # when install_name_tool will be run on any linker output when something is |
michael@0 | 45 | # linked against the copied framework. This option exists to allow signed |
michael@0 | 46 | # frameworks to pass through without subjecting them to any modifications that |
michael@0 | 47 | # would break their signatures. |
michael@0 | 48 | |
michael@0 | 49 | set -e |
michael@0 | 50 | |
michael@0 | 51 | RUN_INSTALL_NAME_TOOL=1 |
michael@0 | 52 | if [ $# -eq 3 ] && [ "${1}" = "-I" ] ; then |
michael@0 | 53 | shift |
michael@0 | 54 | RUN_INSTALL_NAME_TOOL= |
michael@0 | 55 | fi |
michael@0 | 56 | |
michael@0 | 57 | if [ $# -ne 2 ] ; then |
michael@0 | 58 | echo "usage: ${0} [-I] FRAMEWORK DESTINATION_DIR" >& 2 |
michael@0 | 59 | exit 1 |
michael@0 | 60 | fi |
michael@0 | 61 | |
michael@0 | 62 | # FRAMEWORK should be a path to a versioned framework bundle, ending in |
michael@0 | 63 | # .framework. DESTINATION_DIR is the directory that the unversioned framework |
michael@0 | 64 | # bundle will be copied to. |
michael@0 | 65 | |
michael@0 | 66 | FRAMEWORK="${1}" |
michael@0 | 67 | DESTINATION_DIR="${2}" |
michael@0 | 68 | |
michael@0 | 69 | FRAMEWORK_NAME="$(basename "${FRAMEWORK}")" |
michael@0 | 70 | if [ "${FRAMEWORK_NAME: -10}" != ".framework" ] ; then |
michael@0 | 71 | echo "${0}: ${FRAMEWORK_NAME} does not end in .framework" >& 2 |
michael@0 | 72 | exit 1 |
michael@0 | 73 | fi |
michael@0 | 74 | FRAMEWORK_NAME_NOEXT="${FRAMEWORK_NAME:0:$((${#FRAMEWORK_NAME} - 10))}" |
michael@0 | 75 | |
michael@0 | 76 | # Find the current version. |
michael@0 | 77 | VERSIONS="${FRAMEWORK}/Versions" |
michael@0 | 78 | CURRENT_VERSION_LINK="${VERSIONS}/Current" |
michael@0 | 79 | CURRENT_VERSION_ID="$(readlink "${VERSIONS}/Current")" |
michael@0 | 80 | CURRENT_VERSION="${VERSIONS}/${CURRENT_VERSION_ID}" |
michael@0 | 81 | |
michael@0 | 82 | # Make sure that the framework's structure makes sense as a versioned bundle. |
michael@0 | 83 | if [ ! -e "${CURRENT_VERSION}/${FRAMEWORK_NAME_NOEXT}" ] ; then |
michael@0 | 84 | echo "${0}: ${FRAMEWORK_NAME} does not contain a dylib" >& 2 |
michael@0 | 85 | exit 1 |
michael@0 | 86 | fi |
michael@0 | 87 | |
michael@0 | 88 | DESTINATION="${DESTINATION_DIR}/${FRAMEWORK_NAME}" |
michael@0 | 89 | |
michael@0 | 90 | # Copy the versioned directory within the versioned framework to its |
michael@0 | 91 | # destination location. |
michael@0 | 92 | mkdir -p "${DESTINATION_DIR}" |
michael@0 | 93 | rsync -acC --delete --exclude Headers --exclude PrivateHeaders \ |
michael@0 | 94 | --include '*.so' "${CURRENT_VERSION}/" "${DESTINATION}" |
michael@0 | 95 | |
michael@0 | 96 | if [[ -n "${RUN_INSTALL_NAME_TOOL}" ]]; then |
michael@0 | 97 | # Adjust the Mach-O LC_ID_DYLIB load command in the framework. This does not |
michael@0 | 98 | # change the LC_LOAD_DYLIB load commands in anything that may have already |
michael@0 | 99 | # linked against the framework. Not all frameworks will actually need this |
michael@0 | 100 | # to be changed. Some frameworks may already be built with the proper |
michael@0 | 101 | # LC_ID_DYLIB for use as an unversioned framework. Xcode users can do this |
michael@0 | 102 | # by setting LD_DYLIB_INSTALL_NAME to |
michael@0 | 103 | # $(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(WRAPPER_NAME)/$(PRODUCT_NAME) |
michael@0 | 104 | # If invoking ld via gcc or g++, pass the desired path to -Wl,-install_name |
michael@0 | 105 | # at link time. |
michael@0 | 106 | FRAMEWORK_DYLIB="${DESTINATION}/${FRAMEWORK_NAME_NOEXT}" |
michael@0 | 107 | LC_ID_DYLIB_OLD="$(otool -l "${FRAMEWORK_DYLIB}" | |
michael@0 | 108 | grep -A10 "^ *cmd LC_ID_DYLIB$" | |
michael@0 | 109 | grep -m1 "^ *name" | |
michael@0 | 110 | sed -Ee 's/^ *name (.*) \(offset [0-9]+\)$/\1/')" |
michael@0 | 111 | VERSION_PATH="/Versions/${CURRENT_VERSION_ID}/${FRAMEWORK_NAME_NOEXT}" |
michael@0 | 112 | LC_ID_DYLIB_NEW="$(echo "${LC_ID_DYLIB_OLD}" | |
michael@0 | 113 | sed -Ee "s%${VERSION_PATH}$%/${FRAMEWORK_NAME_NOEXT}%")" |
michael@0 | 114 | |
michael@0 | 115 | if [ "${LC_ID_DYLIB_NEW}" != "${LC_ID_DYLIB_OLD}" ] ; then |
michael@0 | 116 | install_name_tool -id "${LC_ID_DYLIB_NEW}" "${FRAMEWORK_DYLIB}" |
michael@0 | 117 | fi |
michael@0 | 118 | fi |