| #!/bin/sh |
| ## Copyright (c) 2021, Alliance for Open Media. All rights reserved |
| ## |
| ## This source code is subject to the terms of the BSD 3-Clause Clear License and the |
| ## Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear License was |
| ## not distributed with this source code in the LICENSE file, you can obtain it |
| ## at aomedia.org/license/software-license/bsd-3-c-c/. If the Alliance for Open Media Patent |
| ## License 1.0 was not distributed with this source code in the PATENTS file, you |
| ## can obtain it at aomedia.org/license/patent-license/. |
| ## |
| ## This script generates 'AOM.framework'. An iOS app can encode and decode AVx |
| ## video by including 'AOM.framework'. |
| ## |
| ## Run iosbuild.sh to create 'AOM.framework' in the current directory. |
| ## |
| set -e |
| devnull='> /dev/null 2>&1' |
| |
| BUILD_ROOT="_iosbuild" |
| CONFIGURE_ARGS="--disable-docs |
| --disable-examples |
| --disable-libyuv |
| --disable-unit-tests" |
| DIST_DIR="_dist" |
| FRAMEWORK_DIR="AOM.framework" |
| FRAMEWORK_LIB="AOM.framework/AOM" |
| HEADER_DIR="${FRAMEWORK_DIR}/Headers/aom" |
| SCRIPT_DIR=$(dirname "$0") |
| LIBAOM_SOURCE_DIR=$(cd ${SCRIPT_DIR}/../..; pwd) |
| LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo) |
| ORIG_PWD="$(pwd)" |
| ARM_TARGETS="arm64-darwin-gcc |
| armv7-darwin-gcc |
| armv7s-darwin-gcc" |
| SIM_TARGETS="x86-iphonesimulator-gcc |
| x86_64-iphonesimulator-gcc" |
| OSX_TARGETS="x86-darwin16-gcc |
| x86_64-darwin16-gcc" |
| TARGETS="${ARM_TARGETS} ${SIM_TARGETS}" |
| |
| # Configures for the target specified by $1, and invokes make with the dist |
| # target using $ as the distribution output directory. |
| build_target() { |
| local target="$1" |
| local old_pwd="$(pwd)" |
| local target_specific_flags="" |
| |
| vlog "***Building target: ${target}***" |
| |
| case "${target}" in |
| x86-*) |
| target_specific_flags="--enable-pic" |
| vlog "Enabled PIC for ${target}" |
| ;; |
| esac |
| |
| mkdir "${target}" |
| cd "${target}" |
| # TODO(tomfinegan@google.com): switch to cmake. |
| eval "${LIBAOM_SOURCE_DIR}/configure" --target="${target}" \ |
| ${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS} ${target_specific_flags} \ |
| ${devnull} |
| export DIST_DIR |
| eval make dist ${devnull} |
| cd "${old_pwd}" |
| |
| vlog "***Done building target: ${target}***" |
| } |
| |
| # Returns the preprocessor symbol for the target specified by $1. |
| target_to_preproc_symbol() { |
| target="$1" |
| case "${target}" in |
| arm64-*) |
| echo "__aarch64__" |
| ;; |
| armv7-*) |
| echo "__ARM_ARCH_7A__" |
| ;; |
| armv7s-*) |
| echo "__ARM_ARCH_7S__" |
| ;; |
| x86-*) |
| echo "__i386__" |
| ;; |
| x86_64-*) |
| echo "__x86_64__" |
| ;; |
| *) |
| echo "#error ${target} unknown/unsupported" |
| return 1 |
| ;; |
| esac |
| } |
| |
| # Create a aom_config.h shim that, based on preprocessor settings for the |
| # current target CPU, includes the real aom_config.h for the current target. |
| # $1 is the list of targets. |
| create_aom_framework_config_shim() { |
| local targets="$1" |
| local config_file="${HEADER_DIR}/aom_config.h" |
| local preproc_symbol="" |
| local target="" |
| local include_guard="AOM_FRAMEWORK_HEADERS_AOM_AOM_CONFIG_H_" |
| |
| local file_header="/* |
| * Copyright (c) $(date +%Y), Alliance for Open Media. All rights reserved. |
| * |
| * This source code is subject to the terms of the BSD 2 Clause License and |
| * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
| * was not distributed with this source code in the LICENSE file, you can |
| * obtain it at www.aomedia.org/license/software. If the Alliance for Open |
| * Media Patent License 1.0 was not distributed with this source code in the |
| * PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
| */ |
| |
| /* GENERATED FILE: DO NOT EDIT! */ |
| |
| #ifndef ${include_guard} |
| #define ${include_guard} |
| |
| #if defined" |
| |
| printf "%s" "${file_header}" > "${config_file}" |
| for target in ${targets}; do |
| preproc_symbol=$(target_to_preproc_symbol "${target}") |
| printf " ${preproc_symbol}\n" >> "${config_file}" |
| printf "#define AOM_FRAMEWORK_TARGET \"${target}\"\n" >> "${config_file}" |
| printf "#include \"AOM/aom/${target}/aom_config.h\"\n" >> "${config_file}" |
| printf "#elif defined" >> "${config_file}" |
| mkdir "${HEADER_DIR}/${target}" |
| cp -p "${BUILD_ROOT}/${target}/aom_config.h" "${HEADER_DIR}/${target}" |
| done |
| |
| # Consume the last line of output from the loop: We don't want it. |
| sed -i '' -e '$d' "${config_file}" |
| |
| printf "#endif\n\n" >> "${config_file}" |
| printf "#endif // ${include_guard}" >> "${config_file}" |
| } |
| |
| # Verifies that $FRAMEWORK_LIB fat library contains requested builds. |
| verify_framework_targets() { |
| local requested_cpus="" |
| local cpu="" |
| |
| # Extract CPU from full target name. |
| for target; do |
| cpu="${target%%-*}" |
| if [ "${cpu}" = "x86" ]; then |
| # lipo -info outputs i386 for libaom x86 targets. |
| cpu="i386" |
| fi |
| requested_cpus="${requested_cpus}${cpu} " |
| done |
| |
| # Get target CPUs present in framework library. |
| local targets_built=$(${LIPO} -info ${FRAMEWORK_LIB}) |
| |
| # $LIPO -info outputs a string like the following: |
| # Architectures in the fat file: $FRAMEWORK_LIB <architectures> |
| # Capture only the architecture strings. |
| targets_built=${targets_built##*: } |
| |
| # Sort CPU strings to make the next step a simple string compare. |
| local actual=$(echo ${targets_built} | tr " " "\n" | sort | tr "\n" " ") |
| local requested=$(echo ${requested_cpus} | tr " " "\n" | sort | tr "\n" " ") |
| |
| vlog "Requested ${FRAMEWORK_LIB} CPUs: ${requested}" |
| vlog "Actual ${FRAMEWORK_LIB} CPUs: ${actual}" |
| |
| if [ "${requested}" != "${actual}" ]; then |
| elog "Actual ${FRAMEWORK_LIB} targets do not match requested target list." |
| elog " Requested target CPUs: ${requested}" |
| elog " Actual target CPUs: ${actual}" |
| return 1 |
| fi |
| } |
| |
| # Configures and builds each target specified by $1, and then builds |
| # AOM.framework. |
| build_framework() { |
| local lib_list="" |
| local targets="$1" |
| local target="" |
| local target_dist_dir="" |
| |
| # Clean up from previous build(s). |
| rm -rf "${BUILD_ROOT}" "${FRAMEWORK_DIR}" |
| |
| # Create output dirs. |
| mkdir -p "${BUILD_ROOT}" |
| mkdir -p "${HEADER_DIR}" |
| |
| cd "${BUILD_ROOT}" |
| |
| for target in ${targets}; do |
| build_target "${target}" |
| target_dist_dir="${BUILD_ROOT}/${target}/${DIST_DIR}" |
| if [ "${ENABLE_SHARED}" = "yes" ]; then |
| local suffix="dylib" |
| else |
| local suffix="a" |
| fi |
| lib_list="${lib_list} ${target_dist_dir}/lib/libaom.${suffix}" |
| done |
| |
| cd "${ORIG_PWD}" |
| |
| # The basic libaom API includes are all the same; just grab the most recent |
| # set. |
| cp -p "${target_dist_dir}"/include/aom/* "${HEADER_DIR}" |
| |
| # Build the fat library. |
| ${LIPO} -create ${lib_list} -output ${FRAMEWORK_DIR}/AOM |
| |
| # Create the aom_config.h shim that allows usage of aom_config.h from |
| # within AOM.framework. |
| create_aom_framework_config_shim "${targets}" |
| |
| # Copy in aom_version.h. |
| cp -p "${BUILD_ROOT}/${target}/aom_version.h" "${HEADER_DIR}" |
| |
| if [ "${ENABLE_SHARED}" = "yes" ]; then |
| # Adjust the dylib's name so dynamic linking in apps works as expected. |
| install_name_tool -id '@rpath/AOM.framework/AOM' ${FRAMEWORK_DIR}/AOM |
| |
| # Copy in Info.plist. |
| cat "${SCRIPT_DIR}/ios-Info.plist" \ |
| | sed "s/\${FULLVERSION}/${FULLVERSION}/g" \ |
| | sed "s/\${VERSION}/${VERSION}/g" \ |
| | sed "s/\${IOS_VERSION_MIN}/${IOS_VERSION_MIN}/g" \ |
| > "${FRAMEWORK_DIR}/Info.plist" |
| fi |
| |
| # Confirm AOM.framework/AOM contains the targets requested. |
| verify_framework_targets ${targets} |
| |
| vlog "Created fat library ${FRAMEWORK_LIB} containing:" |
| for lib in ${lib_list}; do |
| vlog " $(echo ${lib} | awk -F / '{print $2, $NF}')" |
| done |
| } |
| |
| # Trap function. Cleans up the subtree used to build all targets contained in |
| # $TARGETS. |
| cleanup() { |
| local res=$? |
| cd "${ORIG_PWD}" |
| |
| if [ $res -ne 0 ]; then |
| elog "build exited with error ($res)" |
| fi |
| |
| if [ "${PRESERVE_BUILD_OUTPUT}" != "yes" ]; then |
| rm -rf "${BUILD_ROOT}" |
| fi |
| } |
| |
| print_list() { |
| local indent="$1" |
| shift |
| local list="$@" |
| for entry in ${list}; do |
| echo "${indent}${entry}" |
| done |
| } |
| |
| iosbuild_usage() { |
| cat << EOF |
| Usage: ${0##*/} [arguments] |
| --help: Display this message and exit. |
| --enable-shared: Build a dynamic framework for use on iOS 8 or later. |
| --extra-configure-args <args>: Extra args to pass when configuring libaom. |
| --macosx: Uses darwin16 targets instead of iphonesimulator targets for x86 |
| and x86_64. Allows linking to framework when builds target MacOSX |
| instead of iOS. |
| --preserve-build-output: Do not delete the build directory. |
| --show-build-output: Show output from each library build. |
| --targets <targets>: Override default target list. Defaults: |
| $(print_list " " ${TARGETS}) |
| --test-link: Confirms all targets can be linked. Functionally identical to |
| passing --enable-examples via --extra-configure-args. |
| --verbose: Output information about the environment and each stage of the |
| build. |
| EOF |
| } |
| |
| elog() { |
| echo "${0##*/} failed because: $@" 1>&2 |
| } |
| |
| vlog() { |
| if [ "${VERBOSE}" = "yes" ]; then |
| echo "$@" |
| fi |
| } |
| |
| trap cleanup EXIT |
| |
| # Parse the command line. |
| while [ -n "$1" ]; do |
| case "$1" in |
| --extra-configure-args) |
| EXTRA_CONFIGURE_ARGS="$2" |
| shift |
| ;; |
| --help) |
| iosbuild_usage |
| exit |
| ;; |
| --enable-shared) |
| ENABLE_SHARED=yes |
| ;; |
| --preserve-build-output) |
| PRESERVE_BUILD_OUTPUT=yes |
| ;; |
| --show-build-output) |
| devnull= |
| ;; |
| --test-link) |
| EXTRA_CONFIGURE_ARGS="${EXTRA_CONFIGURE_ARGS} --enable-examples" |
| ;; |
| --targets) |
| TARGETS="$2" |
| shift |
| ;; |
| --macosx) |
| TARGETS="${ARM_TARGETS} ${OSX_TARGETS}" |
| ;; |
| --verbose) |
| VERBOSE=yes |
| ;; |
| *) |
| iosbuild_usage |
| exit 1 |
| ;; |
| esac |
| shift |
| done |
| |
| if [ "${ENABLE_SHARED}" = "yes" ]; then |
| CONFIGURE_ARGS="--enable-shared ${CONFIGURE_ARGS}" |
| fi |
| |
| FULLVERSION=$("${SCRIPT_DIR}"/version.sh --bare "${LIBAOM_SOURCE_DIR}") |
| VERSION=$(echo "${FULLVERSION}" | sed -E 's/^v([0-9]+\.[0-9]+\.[0-9]+).*$/\1/') |
| |
| if [ "$ENABLE_SHARED" = "yes" ]; then |
| IOS_VERSION_OPTIONS="--enable-shared" |
| IOS_VERSION_MIN="8.0" |
| else |
| IOS_VERSION_OPTIONS="" |
| IOS_VERSION_MIN="6.0" |
| fi |
| |
| if [ "${VERBOSE}" = "yes" ]; then |
| cat << EOF |
| BUILD_ROOT=${BUILD_ROOT} |
| DIST_DIR=${DIST_DIR} |
| CONFIGURE_ARGS=${CONFIGURE_ARGS} |
| EXTRA_CONFIGURE_ARGS=${EXTRA_CONFIGURE_ARGS} |
| FRAMEWORK_DIR=${FRAMEWORK_DIR} |
| FRAMEWORK_LIB=${FRAMEWORK_LIB} |
| HEADER_DIR=${HEADER_DIR} |
| LIBAOM_SOURCE_DIR=${LIBAOM_SOURCE_DIR} |
| LIPO=${LIPO} |
| MAKEFLAGS=${MAKEFLAGS} |
| ORIG_PWD=${ORIG_PWD} |
| PRESERVE_BUILD_OUTPUT=${PRESERVE_BUILD_OUTPUT} |
| TARGETS="$(print_list "" ${TARGETS})" |
| ENABLE_SHARED=${ENABLE_SHARED} |
| OSX_TARGETS="${OSX_TARGETS}" |
| SIM_TARGETS="${SIM_TARGETS}" |
| SCRIPT_DIR="${SCRIPT_DIR}" |
| FULLVERSION="${FULLVERSION}" |
| VERSION="${VERSION}" |
| IOS_VERSION_MIN="${IOS_VERSION_MIN}" |
| EOF |
| fi |
| |
| build_framework "${TARGETS}" |
| echo "Successfully built '${FRAMEWORK_DIR}' for:" |
| print_list "" ${TARGETS} |