1#!/bin/sh 2## Copyright (c) 2016, Alliance for Open Media. All rights reserved 3## 4## This source code is subject to the terms of the BSD 2 Clause License and 5## the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License 6## was not distributed with this source code in the LICENSE file, you can 7## obtain it at www.aomedia.org/license/software. If the Alliance for Open 8## Media Patent License 1.0 was not distributed with this source code in the 9## PATENTS file, you can obtain it at www.aomedia.org/license/patent. 10## 11## This script generates 'AOM.framework'. An iOS app can encode and decode AVx 12## video by including 'AOM.framework'. 13## 14## Run iosbuild.sh to create 'AOM.framework' in the current directory. 15## 16set -e 17devnull='> /dev/null 2>&1' 18 19BUILD_ROOT="_iosbuild" 20CONFIGURE_ARGS="--disable-docs 21 --disable-examples 22 --disable-libyuv 23 --disable-unit-tests" 24DIST_DIR="_dist" 25FRAMEWORK_DIR="AOM.framework" 26FRAMEWORK_LIB="AOM.framework/AOM" 27HEADER_DIR="${FRAMEWORK_DIR}/Headers/aom" 28SCRIPT_DIR=$(dirname "$0") 29LIBAOM_SOURCE_DIR=$(cd ${SCRIPT_DIR}/../..; pwd) 30LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo) 31ORIG_PWD="$(pwd)" 32ARM_TARGETS="arm64-darwin-gcc 33 armv7-darwin-gcc 34 armv7s-darwin-gcc" 35SIM_TARGETS="x86-iphonesimulator-gcc 36 x86_64-iphonesimulator-gcc" 37OSX_TARGETS="x86-darwin16-gcc 38 x86_64-darwin16-gcc" 39TARGETS="${ARM_TARGETS} ${SIM_TARGETS}" 40 41# Configures for the target specified by $1, and invokes make with the dist 42# target using $ as the distribution output directory. 43build_target() { 44 local target="$1" 45 local old_pwd="$(pwd)" 46 local target_specific_flags="" 47 48 vlog "***Building target: ${target}***" 49 50 case "${target}" in 51 x86-*) 52 target_specific_flags="--enable-pic" 53 vlog "Enabled PIC for ${target}" 54 ;; 55 esac 56 57 mkdir "${target}" 58 cd "${target}" 59 # TODO(tomfinegan@google.com): switch to cmake. 60 eval "${LIBAOM_SOURCE_DIR}/configure" --target="${target}" \ 61 ${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS} ${target_specific_flags} \ 62 ${devnull} 63 export DIST_DIR 64 eval make dist ${devnull} 65 cd "${old_pwd}" 66 67 vlog "***Done building target: ${target}***" 68} 69 70# Returns the preprocessor symbol for the target specified by $1. 71target_to_preproc_symbol() { 72 target="$1" 73 case "${target}" in 74 arm64-*) 75 echo "__aarch64__" 76 ;; 77 armv7-*) 78 echo "__ARM_ARCH_7A__" 79 ;; 80 armv7s-*) 81 echo "__ARM_ARCH_7S__" 82 ;; 83 x86-*) 84 echo "__i386__" 85 ;; 86 x86_64-*) 87 echo "__x86_64__" 88 ;; 89 *) 90 echo "#error ${target} unknown/unsupported" 91 return 1 92 ;; 93 esac 94} 95 96# Create a aom_config.h shim that, based on preprocessor settings for the 97# current target CPU, includes the real aom_config.h for the current target. 98# $1 is the list of targets. 99create_aom_framework_config_shim() { 100 local targets="$1" 101 local config_file="${HEADER_DIR}/aom_config.h" 102 local preproc_symbol="" 103 local target="" 104 local include_guard="AOM_FRAMEWORK_HEADERS_AOM_AOM_CONFIG_H_" 105 106 local file_header="/* 107 * Copyright (c) $(date +%Y), Alliance for Open Media. All rights reserved. 108 * 109 * This source code is subject to the terms of the BSD 2 Clause License and 110 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License 111 * was not distributed with this source code in the LICENSE file, you can 112 * obtain it at www.aomedia.org/license/software. If the Alliance for Open 113 * Media Patent License 1.0 was not distributed with this source code in the 114 * PATENTS file, you can obtain it at www.aomedia.org/license/patent. 115 */ 116 117/* GENERATED FILE: DO NOT EDIT! */ 118 119#ifndef ${include_guard} 120#define ${include_guard} 121 122#if defined" 123 124 printf "%s" "${file_header}" > "${config_file}" 125 for target in ${targets}; do 126 preproc_symbol=$(target_to_preproc_symbol "${target}") 127 printf " ${preproc_symbol}\n" >> "${config_file}" 128 printf "#define AOM_FRAMEWORK_TARGET \"${target}\"\n" >> "${config_file}" 129 printf "#include \"AOM/aom/${target}/aom_config.h\"\n" >> "${config_file}" 130 printf "#elif defined" >> "${config_file}" 131 mkdir "${HEADER_DIR}/${target}" 132 cp -p "${BUILD_ROOT}/${target}/aom_config.h" "${HEADER_DIR}/${target}" 133 done 134 135 # Consume the last line of output from the loop: We don't want it. 136 sed -i '' -e '$d' "${config_file}" 137 138 printf "#endif\n\n" >> "${config_file}" 139 printf "#endif // ${include_guard}" >> "${config_file}" 140} 141 142# Verifies that $FRAMEWORK_LIB fat library contains requested builds. 143verify_framework_targets() { 144 local requested_cpus="" 145 local cpu="" 146 147 # Extract CPU from full target name. 148 for target; do 149 cpu="${target%%-*}" 150 if [ "${cpu}" = "x86" ]; then 151 # lipo -info outputs i386 for libaom x86 targets. 152 cpu="i386" 153 fi 154 requested_cpus="${requested_cpus}${cpu} " 155 done 156 157 # Get target CPUs present in framework library. 158 local targets_built=$(${LIPO} -info ${FRAMEWORK_LIB}) 159 160 # $LIPO -info outputs a string like the following: 161 # Architectures in the fat file: $FRAMEWORK_LIB <architectures> 162 # Capture only the architecture strings. 163 targets_built=${targets_built##*: } 164 165 # Sort CPU strings to make the next step a simple string compare. 166 local actual=$(echo ${targets_built} | tr " " "\n" | sort | tr "\n" " ") 167 local requested=$(echo ${requested_cpus} | tr " " "\n" | sort | tr "\n" " ") 168 169 vlog "Requested ${FRAMEWORK_LIB} CPUs: ${requested}" 170 vlog "Actual ${FRAMEWORK_LIB} CPUs: ${actual}" 171 172 if [ "${requested}" != "${actual}" ]; then 173 elog "Actual ${FRAMEWORK_LIB} targets do not match requested target list." 174 elog " Requested target CPUs: ${requested}" 175 elog " Actual target CPUs: ${actual}" 176 return 1 177 fi 178} 179 180# Configures and builds each target specified by $1, and then builds 181# AOM.framework. 182build_framework() { 183 local lib_list="" 184 local targets="$1" 185 local target="" 186 local target_dist_dir="" 187 188 # Clean up from previous build(s). 189 rm -rf "${BUILD_ROOT}" "${FRAMEWORK_DIR}" 190 191 # Create output dirs. 192 mkdir -p "${BUILD_ROOT}" 193 mkdir -p "${HEADER_DIR}" 194 195 cd "${BUILD_ROOT}" 196 197 for target in ${targets}; do 198 build_target "${target}" 199 target_dist_dir="${BUILD_ROOT}/${target}/${DIST_DIR}" 200 if [ "${ENABLE_SHARED}" = "yes" ]; then 201 local suffix="dylib" 202 else 203 local suffix="a" 204 fi 205 lib_list="${lib_list} ${target_dist_dir}/lib/libaom.${suffix}" 206 done 207 208 cd "${ORIG_PWD}" 209 210 # The basic libaom API includes are all the same; just grab the most recent 211 # set. 212 cp -p "${target_dist_dir}"/include/aom/* "${HEADER_DIR}" 213 214 # Build the fat library. 215 ${LIPO} -create ${lib_list} -output ${FRAMEWORK_DIR}/AOM 216 217 # Create the aom_config.h shim that allows usage of aom_config.h from 218 # within AOM.framework. 219 create_aom_framework_config_shim "${targets}" 220 221 # Copy in aom_version.h. 222 cp -p "${BUILD_ROOT}/${target}/aom_version.h" "${HEADER_DIR}" 223 224 if [ "${ENABLE_SHARED}" = "yes" ]; then 225 # Adjust the dylib's name so dynamic linking in apps works as expected. 226 install_name_tool -id '@rpath/AOM.framework/AOM' ${FRAMEWORK_DIR}/AOM 227 228 # Copy in Info.plist. 229 cat "${SCRIPT_DIR}/ios-Info.plist" \ 230 | sed "s/\${FULLVERSION}/${FULLVERSION}/g" \ 231 | sed "s/\${VERSION}/${VERSION}/g" \ 232 | sed "s/\${IOS_VERSION_MIN}/${IOS_VERSION_MIN}/g" \ 233 > "${FRAMEWORK_DIR}/Info.plist" 234 fi 235 236 # Confirm AOM.framework/AOM contains the targets requested. 237 verify_framework_targets ${targets} 238 239 vlog "Created fat library ${FRAMEWORK_LIB} containing:" 240 for lib in ${lib_list}; do 241 vlog " $(echo ${lib} | awk -F / '{print $2, $NF}')" 242 done 243} 244 245# Trap function. Cleans up the subtree used to build all targets contained in 246# $TARGETS. 247cleanup() { 248 local res=$? 249 cd "${ORIG_PWD}" 250 251 if [ $res -ne 0 ]; then 252 elog "build exited with error ($res)" 253 fi 254 255 if [ "${PRESERVE_BUILD_OUTPUT}" != "yes" ]; then 256 rm -rf "${BUILD_ROOT}" 257 fi 258} 259 260print_list() { 261 local indent="$1" 262 shift 263 local list="$@" 264 for entry in ${list}; do 265 echo "${indent}${entry}" 266 done 267} 268 269iosbuild_usage() { 270cat << EOF 271 Usage: ${0##*/} [arguments] 272 --help: Display this message and exit. 273 --enable-shared: Build a dynamic framework for use on iOS 8 or later. 274 --extra-configure-args <args>: Extra args to pass when configuring libaom. 275 --macosx: Uses darwin16 targets instead of iphonesimulator targets for x86 276 and x86_64. Allows linking to framework when builds target MacOSX 277 instead of iOS. 278 --preserve-build-output: Do not delete the build directory. 279 --show-build-output: Show output from each library build. 280 --targets <targets>: Override default target list. Defaults: 281$(print_list " " ${TARGETS}) 282 --test-link: Confirms all targets can be linked. Functionally identical to 283 passing --enable-examples via --extra-configure-args. 284 --verbose: Output information about the environment and each stage of the 285 build. 286EOF 287} 288 289elog() { 290 echo "${0##*/} failed because: $@" 1>&2 291} 292 293vlog() { 294 if [ "${VERBOSE}" = "yes" ]; then 295 echo "$@" 296 fi 297} 298 299trap cleanup EXIT 300 301# Parse the command line. 302while [ -n "$1" ]; do 303 case "$1" in 304 --extra-configure-args) 305 EXTRA_CONFIGURE_ARGS="$2" 306 shift 307 ;; 308 --help) 309 iosbuild_usage 310 exit 311 ;; 312 --enable-shared) 313 ENABLE_SHARED=yes 314 ;; 315 --preserve-build-output) 316 PRESERVE_BUILD_OUTPUT=yes 317 ;; 318 --show-build-output) 319 devnull= 320 ;; 321 --test-link) 322 EXTRA_CONFIGURE_ARGS="${EXTRA_CONFIGURE_ARGS} --enable-examples" 323 ;; 324 --targets) 325 TARGETS="$2" 326 shift 327 ;; 328 --macosx) 329 TARGETS="${ARM_TARGETS} ${OSX_TARGETS}" 330 ;; 331 --verbose) 332 VERBOSE=yes 333 ;; 334 *) 335 iosbuild_usage 336 exit 1 337 ;; 338 esac 339 shift 340done 341 342if [ "${ENABLE_SHARED}" = "yes" ]; then 343 CONFIGURE_ARGS="--enable-shared ${CONFIGURE_ARGS}" 344fi 345 346FULLVERSION=$("${SCRIPT_DIR}"/version.sh --bare "${LIBAOM_SOURCE_DIR}") 347VERSION=$(echo "${FULLVERSION}" | sed -E 's/^v([0-9]+\.[0-9]+\.[0-9]+).*$/\1/') 348 349if [ "$ENABLE_SHARED" = "yes" ]; then 350 IOS_VERSION_OPTIONS="--enable-shared" 351 IOS_VERSION_MIN="8.0" 352else 353 IOS_VERSION_OPTIONS="" 354 IOS_VERSION_MIN="6.0" 355fi 356 357if [ "${VERBOSE}" = "yes" ]; then 358cat << EOF 359 BUILD_ROOT=${BUILD_ROOT} 360 DIST_DIR=${DIST_DIR} 361 CONFIGURE_ARGS=${CONFIGURE_ARGS} 362 EXTRA_CONFIGURE_ARGS=${EXTRA_CONFIGURE_ARGS} 363 FRAMEWORK_DIR=${FRAMEWORK_DIR} 364 FRAMEWORK_LIB=${FRAMEWORK_LIB} 365 HEADER_DIR=${HEADER_DIR} 366 LIBAOM_SOURCE_DIR=${LIBAOM_SOURCE_DIR} 367 LIPO=${LIPO} 368 MAKEFLAGS=${MAKEFLAGS} 369 ORIG_PWD=${ORIG_PWD} 370 PRESERVE_BUILD_OUTPUT=${PRESERVE_BUILD_OUTPUT} 371 TARGETS="$(print_list "" ${TARGETS})" 372 ENABLE_SHARED=${ENABLE_SHARED} 373 OSX_TARGETS="${OSX_TARGETS}" 374 SIM_TARGETS="${SIM_TARGETS}" 375 SCRIPT_DIR="${SCRIPT_DIR}" 376 FULLVERSION="${FULLVERSION}" 377 VERSION="${VERSION}" 378 IOS_VERSION_MIN="${IOS_VERSION_MIN}" 379EOF 380fi 381 382build_framework "${TARGETS}" 383echo "Successfully built '${FRAMEWORK_DIR}' for:" 384print_list "" ${TARGETS} 385