From 64eb2ff0b97f360d2f5138eb43dcb7d2abb7ea43 Mon Sep 17 00:00:00 2001 From: "tkchin@webrtc.org" Date: Mon, 23 Mar 2015 19:07:37 +0000 Subject: [PATCH] iOS library build script Script for building iOS fat libraries with armv7/arm64/x86_64. BUG=4119 R=jiayl@webrtc.org Review URL: https://webrtc-codereview.appspot.com/51429004 Cr-Commit-Position: refs/heads/master@{#8834} git-svn-id: http://webrtc.googlecode.com/svn/trunk@8834 4adac7df-926f-26a2-2b94-8c16560cd09d --- talk/build/build_ios_libs.sh | 89 ++++++++++++++++++++++++ talk/build/merge_ios_libs | 126 ++++++++++++++++++++++++++++++++++ talk/build/merge_ios_libs.gyp | 44 ++++++++++++ 3 files changed, 259 insertions(+) create mode 100755 talk/build/build_ios_libs.sh create mode 100755 talk/build/merge_ios_libs create mode 100644 talk/build/merge_ios_libs.gyp diff --git a/talk/build/build_ios_libs.sh b/talk/build/build_ios_libs.sh new file mode 100755 index 0000000000..d2d7c6796d --- /dev/null +++ b/talk/build/build_ios_libs.sh @@ -0,0 +1,89 @@ +#!/bin/bash +# +# libjingle +# Copyright 2015 Google Inc. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. 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. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + +# Generates static FAT libraries for ios in out_ios_libs. + +# Check for Darwin. +if [[ ! $(uname) = "Darwin" ]]; then + echo "OS/X required." >&2 +fi + +# Check for libtool. +if [[ -z $(which libtool) ]]; then + echo "Missing libtool binary." >&2 +fi + +# Check for GYP generator. +SCRIPT_DIR=$(dirname $0) +WEBRTC_BASE_DIR=${SCRIPT_DIR}/../.. +GYP_WEBRTC_SCRIPT=${WEBRTC_BASE_DIR}/webrtc/build/gyp_webrtc +if [[ ! -x ${GYP_WEBRTC_SCRIPT} ]]; then + echo "Failed to find gyp generator." >&2 + exit 1 +fi +# Check for merge script. +MERGE_SCRIPT=${SCRIPT_DIR}/merge_ios_libs +if [[ ! -x ${MERGE_SCRIPT} ]]; then + echo "Failed to find library merging script." >&2 + exit 1 +fi + +pushd ${WEBRTC_BASE_DIR} +LIBRARY_BASE_DIR="out_ios_libs" + +function build_webrtc { + OUTPUT_DIR=$1 + FLAVOR=$2 + TARGET_ARCH=$3 + TARGET_SUBARCH=$4 + if [[ ${TARGET_ARCH} = 'armv7' || ${TARGET_ARCH} = 'arm64' ]]; then + FLAVOR="${FLAVOR}-iphoneos" + else + FLAVOR="${FLAVOR}-iphonesimulator" + fi + export GYP_DEFINES="OS=ios" + export GYP_DEFINES="${GYP_DEFINES} target_arch=${TARGET_ARCH}" + if [[ -n ${TARGET_SUBARCH} ]]; then + export GYP_DEFINES="${GYP_DEFINES} target_subarch=${TARGET_SUBARCH}" + fi + export GYP_GENERATORS="ninja" + export GYP_GENERATOR_FLAGS="output_dir=${OUTPUT_DIR}" + webrtc/build/gyp_webrtc talk/build/merge_ios_libs.gyp + ninja -C ${OUTPUT_DIR}/${FLAVOR} libjingle_peerconnection_objc_no_op + mkdir -p ${LIBRARY_BASE_DIR}/${TARGET_ARCH} + mv ${OUTPUT_DIR}/${FLAVOR}/*.a ${LIBRARY_BASE_DIR}/${TARGET_ARCH} +} + +# Build all the common architectures. +build_webrtc "out_ios_armv7" "Release" "armv7" +build_webrtc "out_ios_arm64" "Release" "arm64" "arm64" +build_webrtc "out_ios_x86_64" "Release" "x64" "arm64" + +popd + +# Merge the libraries together. +${MERGE_SCRIPT} ${WEBRTC_BASE_DIR}/${LIBRARY_BASE_DIR} diff --git a/talk/build/merge_ios_libs b/talk/build/merge_ios_libs new file mode 100755 index 0000000000..98fd306be1 --- /dev/null +++ b/talk/build/merge_ios_libs @@ -0,0 +1,126 @@ +#!/usr/bin/python +# +# libjingle +# Copyright 2015 Google Inc. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. 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. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + +"""Script for merging generated iOS libraries.""" + +import optparse +import os +import re +import subprocess +import sys + + +def MergeLibs(lib_base_dir): + """Merges generated iOS libraries for different archs. + + Uses libtool to generate FAT archive files for each generated library. + + Args: + lib_base_dir: directory whose subdirectories are named by architecture and + contain the built libraries for that architecture + + Returns: + Exit code of libtool. + """ + output_dir_name = 'fat' + archs = [arch for arch in os.listdir(lib_base_dir) + if arch[:1] != '.' and arch != output_dir_name] + # For each arch, find (library name, libary path) for arch. We will merge + # all libraries with the same name. + libs = {} + for dirpath, _, filenames in os.walk(lib_base_dir): + if dirpath.endswith(output_dir_name): + continue + for filename in filenames: + if not filename.endswith('.a'): + continue + entry = libs.get(filename, []) + entry.append(os.path.join(dirpath, filename)) + libs[filename] = entry + # Some sublibaries are only present in certain architectures. We merge + # them into their parent library so that the library list is consistent + # across architectures. + libs_copy = dict(libs) + for library, paths in libs.items(): + if len(paths) < len(archs): + # Hacky: we find parent libraries by stripping off each name component. + components = library.strip('.a').split('_')[:-1] + found = False + while components: + parent_library = '_'.join(components) + '.a' + if (parent_library in libs_copy + and len(libs_copy[parent_library]) >= len(archs)): + libs[parent_library].extend(paths) + del libs[library] + found = True + break + components = components[:-1] + assert found + + # Create output directory. + output_dir_path = os.path.join(lib_base_dir, output_dir_name) + if not os.path.exists(output_dir_path): + os.mkdir(output_dir_path) + + # Use this so libtool merged binaries are always the same. + env = os.environ.copy() + env['ZERO_AR_DATE'] = '1' + + # Ignore certain errors. + libtool_re = re.compile(r'^.*libtool:.*file: .* has no symbols$') + + # Merge libraries using libtool. + for library, paths in libs.items(): + cmd_list = ['libtool', '-static', '-v', '-o', + os.path.join(output_dir_path, library)] + paths + libtoolout = subprocess.Popen(cmd_list, stderr=subprocess.PIPE, env=env) + _, err = libtoolout.communicate() + for line in err.splitlines(): + if not libtool_re.match(line): + print >>sys.stderr, line + # Unconditionally touch the output .a file on the command line if present + # and the command succeeded. A bit hacky. + if not libtoolout.returncode: + for i in range(len(cmd_list) - 1): + if cmd_list[i] == '-o' and cmd_list[i+1].endswith('.a'): + os.utime(cmd_list[i+1], None) + break + else: + return libtoolout.returncode + return libtoolout.returncode + + +def Main(): + parser = optparse.OptionParser() + _, args = parser.parse_args() + if len(args) != 1: + parser.error('Error: Exactly 1 argument required.') + lib_base_dir = args[0] + MergeLibs(lib_base_dir) + +if __name__ == '__main__': + sys.exit(Main()) diff --git a/talk/build/merge_ios_libs.gyp b/talk/build/merge_ios_libs.gyp new file mode 100644 index 0000000000..b9639add7c --- /dev/null +++ b/talk/build/merge_ios_libs.gyp @@ -0,0 +1,44 @@ +# +# libjingle +# Copyright 2015 Google Inc. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. 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. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + +{ + 'includes': ['common.gypi',], + 'conditions': [ + ['OS=="ios" or (OS=="mac" and mac_sdk>="10.8")', { + 'targets': [ + { + 'target_name': 'libjingle_peerconnection_objc_no_op', + 'includes': [ 'objc_app.gypi' ], + 'type': 'executable', + 'dependencies': [ + '../libjingle.gyp:libjingle_peerconnection_objc', + ], + 'sources': ['<(DEPTH)/webrtc/build/no_op.cc',], + }, + ], + }] + ], +}