1#!/bin/sh 2## 3## Copyright (c) 2014 The WebM project authors. All Rights Reserved. 4## 5## Use of this source code is governed by a BSD-style license 6## that can be found in the LICENSE file in the root of the source 7## tree. An additional intellectual property rights grant can be found 8## in the file PATENTS. All contributing project authors may 9## be found in the AUTHORS file in the root of the source tree. 10## 11## 12## This script generates 'VPX.framework'. An iOS app can encode and decode VPx 13## video by including 'VPX.framework'. 14## 15## Run iosbuild.sh to create 'VPX.framework' in the current directory. 16## 17set -e 18devnull='> /dev/null 2>&1' 19 20BUILD_ROOT="_iosbuild" 21CONFIGURE_ARGS="--disable-docs 22 --disable-examples 23 --disable-libyuv 24 --disable-unit-tests" 25DIST_DIR="_dist" 26FRAMEWORK_DIR="VPX.framework" 27FRAMEWORK_LIB="VPX.framework/VPX" 28HEADER_DIR="${FRAMEWORK_DIR}/Headers/vpx" 29SCRIPT_DIR=$(dirname "$0") 30LIBVPX_SOURCE_DIR=$(cd ${SCRIPT_DIR}/../..; pwd) 31LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo) 32ORIG_PWD="$(pwd)" 33ARM_TARGETS="arm64-darwin-gcc 34 armv7-darwin-gcc 35 armv7s-darwin-gcc" 36SIM_TARGETS="x86-iphonesimulator-gcc 37 x86_64-iphonesimulator-gcc" 38OSX_TARGETS="x86-darwin18-gcc 39 x86_64-darwin18-gcc" 40TARGETS="${ARM_TARGETS} ${SIM_TARGETS}" 41 42# Configures for the target specified by $1, and invokes make with the dist 43# target using $DIST_DIR as the distribution output directory. 44build_target() { 45 local target="$1" 46 local old_pwd="$(pwd)" 47 local target_specific_flags="" 48 49 vlog "***Building target: ${target}***" 50 51 case "${target}" in 52 x86-*) 53 target_specific_flags="--enable-pic" 54 vlog "Enabled PIC for ${target}" 55 ;; 56 esac 57 58 mkdir "${target}" 59 cd "${target}" 60 eval "${LIBVPX_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 vpx_config.h shim that, based on preprocessor settings for the 97# current target CPU, includes the real vpx_config.h for the current target. 98# $1 is the list of targets. 99create_vpx_framework_config_shim() { 100 local targets="$1" 101 local config_file="${HEADER_DIR}/vpx_config.h" 102 local preproc_symbol="" 103 local target="" 104 local include_guard="VPX_FRAMEWORK_HEADERS_VPX_VPX_CONFIG_H_" 105 106 local file_header="/* 107 * Copyright (c) $(date +%Y) The WebM project authors. All Rights Reserved. 108 * 109 * Use of this source code is governed by a BSD-style license 110 * that can be found in the LICENSE file in the root of the source 111 * tree. An additional intellectual property rights grant can be found 112 * in the file PATENTS. All contributing project authors may 113 * be found in the AUTHORS file in the root of the source tree. 114 */ 115 116/* GENERATED FILE: DO NOT EDIT! */ 117 118#ifndef ${include_guard} 119#define ${include_guard} 120 121#if defined" 122 123 printf "%s" "${file_header}" > "${config_file}" 124 for target in ${targets}; do 125 preproc_symbol=$(target_to_preproc_symbol "${target}") 126 printf " ${preproc_symbol}\n" >> "${config_file}" 127 printf "#define VPX_FRAMEWORK_TARGET \"${target}\"\n" >> "${config_file}" 128 printf "#include \"VPX/vpx/${target}/vpx_config.h\"\n" >> "${config_file}" 129 printf "#elif defined" >> "${config_file}" 130 mkdir "${HEADER_DIR}/${target}" 131 cp -p "${BUILD_ROOT}/${target}/vpx_config.h" "${HEADER_DIR}/${target}" 132 done 133 134 # Consume the last line of output from the loop: We don't want it. 135 sed -i.bak -e '$d' "${config_file}" 136 rm "${config_file}.bak" 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 libvpx 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# VPX.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/libvpx.${suffix}" 206 done 207 208 cd "${ORIG_PWD}" 209 210 # The basic libvpx API includes are all the same; just grab the most recent 211 # set. 212 cp -p "${target_dist_dir}"/include/vpx/* "${HEADER_DIR}" 213 214 # Build the fat library. 215 ${LIPO} -create ${lib_list} -output ${FRAMEWORK_DIR}/VPX 216 217 # Create the vpx_config.h shim that allows usage of vpx_config.h from 218 # within VPX.framework. 219 create_vpx_framework_config_shim "${targets}" 220 221 # Copy in vpx_version.h. 222 cp -p "${BUILD_ROOT}/${target}/vpx_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/VPX.framework/VPX' ${FRAMEWORK_DIR}/VPX 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 VPX.framework/VPX 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 libvpx. 275 --macosx: Uses darwin18 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 "${LIBVPX_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="7.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 LIBVPX_SOURCE_DIR=${LIBVPX_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