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"
27HEADER_DIR="${FRAMEWORK_DIR}/Headers/vpx"
28MAKE_JOBS=1
29SCRIPT_DIR=$(dirname "$0")
30LIBVPX_SOURCE_DIR=$(cd ${SCRIPT_DIR}/../..; pwd)
31LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo)
32ORIG_PWD="$(pwd)"
33TARGETS="arm64-darwin-gcc
34         armv7-darwin-gcc
35         armv7s-darwin-gcc
36         x86-iphonesimulator-gcc
37         x86_64-iphonesimulator-gcc"
38
39# Configures for the target specified by $1, and invokes make with the dist
40# target using $DIST_DIR as the distribution output directory.
41build_target() {
42  local target="$1"
43  local old_pwd="$(pwd)"
44
45  vlog "***Building target: ${target}***"
46
47  mkdir "${target}"
48  cd "${target}"
49  eval "${LIBVPX_SOURCE_DIR}/configure" --target="${target}" \
50    ${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS} ${devnull}
51  export DIST_DIR
52  eval make -j ${MAKE_JOBS} dist ${devnull}
53  cd "${old_pwd}"
54
55  vlog "***Done building target: ${target}***"
56}
57
58# Returns the preprocessor symbol for the target specified by $1.
59target_to_preproc_symbol() {
60  target="$1"
61  case "${target}" in
62    arm64-*)
63      echo "__aarch64__"
64      ;;
65    armv7-*)
66      echo "__ARM_ARCH_7A__"
67      ;;
68    armv7s-*)
69      echo "__ARM_ARCH_7S__"
70      ;;
71    x86-*)
72      echo "__i386__"
73      ;;
74    x86_64-*)
75      echo "__x86_64__"
76      ;;
77    *)
78      echo "#error ${target} unknown/unsupported"
79      return 1
80      ;;
81  esac
82}
83
84# Create a vpx_config.h shim that, based on preprocessor settings for the
85# current target CPU, includes the real vpx_config.h for the current target.
86# $1 is the list of targets.
87create_vpx_framework_config_shim() {
88  local targets="$1"
89  local config_file="${HEADER_DIR}/vpx_config.h"
90  local preproc_symbol=""
91  local target=""
92  local include_guard="VPX_FRAMEWORK_HEADERS_VPX_VPX_CONFIG_H_"
93
94  local file_header="/*
95 *  Copyright (c) $(date +%Y) The WebM project authors. All Rights Reserved.
96 *
97 *  Use of this source code is governed by a BSD-style license
98 *  that can be found in the LICENSE file in the root of the source
99 *  tree. An additional intellectual property rights grant can be found
100 *  in the file PATENTS.  All contributing project authors may
101 *  be found in the AUTHORS file in the root of the source tree.
102 */
103
104/* GENERATED FILE: DO NOT EDIT! */
105
106#ifndef ${include_guard}
107#define ${include_guard}
108
109#if defined"
110
111  printf "%s" "${file_header}" > "${config_file}"
112  for target in ${targets}; do
113    preproc_symbol=$(target_to_preproc_symbol "${target}")
114    printf " ${preproc_symbol}\n" >> "${config_file}"
115    printf "#define VPX_FRAMEWORK_TARGET \"${target}\"\n" >> "${config_file}"
116    printf "#include \"VPX/vpx/${target}/vpx_config.h\"\n" >> "${config_file}"
117    printf "#elif defined" >> "${config_file}"
118    mkdir "${HEADER_DIR}/${target}"
119    cp -p "${BUILD_ROOT}/${target}/vpx_config.h" "${HEADER_DIR}/${target}"
120  done
121
122  # Consume the last line of output from the loop: We don't want it.
123  sed -i '' -e '$d' "${config_file}"
124
125  printf "#endif\n\n" >> "${config_file}"
126  printf "#endif  // ${include_guard}" >> "${config_file}"
127}
128
129# Configures and builds each target specified by $1, and then builds
130# VPX.framework.
131build_framework() {
132  local lib_list=""
133  local targets="$1"
134  local target=""
135  local target_dist_dir=""
136
137  # Clean up from previous build(s).
138  rm -rf "${BUILD_ROOT}" "${FRAMEWORK_DIR}"
139
140  # Create output dirs.
141  mkdir -p "${BUILD_ROOT}"
142  mkdir -p "${HEADER_DIR}"
143
144  cd "${BUILD_ROOT}"
145
146  for target in ${targets}; do
147    build_target "${target}"
148    target_dist_dir="${BUILD_ROOT}/${target}/${DIST_DIR}"
149    lib_list="${lib_list} ${target_dist_dir}/lib/libvpx.a"
150  done
151
152  cd "${ORIG_PWD}"
153
154  # The basic libvpx API includes are all the same; just grab the most recent
155  # set.
156  cp -p "${target_dist_dir}"/include/vpx/* "${HEADER_DIR}"
157
158  # Build the fat library.
159  ${LIPO} -create ${lib_list} -output ${FRAMEWORK_DIR}/VPX
160
161  # Create the vpx_config.h shim that allows usage of vpx_config.h from
162  # within VPX.framework.
163  create_vpx_framework_config_shim "${targets}"
164
165  # Copy in vpx_version.h.
166  cp -p "${BUILD_ROOT}/${target}/vpx_version.h" "${HEADER_DIR}"
167
168  vlog "Created fat library ${FRAMEWORK_DIR}/VPX containing:"
169  for lib in ${lib_list}; do
170    vlog "  $(echo ${lib} | awk -F / '{print $2, $NF}')"
171  done
172
173  # TODO(tomfinegan): Verify that expected targets are included within
174  # VPX.framework/VPX via lipo -info.
175}
176
177# Trap function. Cleans up the subtree used to build all targets contained in
178# $TARGETS.
179cleanup() {
180  local readonly res=$?
181  cd "${ORIG_PWD}"
182
183  if [ $res -ne 0 ]; then
184    elog "build exited with error ($res)"
185  fi
186
187  if [ "${PRESERVE_BUILD_OUTPUT}" != "yes" ]; then
188    rm -rf "${BUILD_ROOT}"
189  fi
190}
191
192iosbuild_usage() {
193cat << EOF
194  Usage: ${0##*/} [arguments]
195    --help: Display this message and exit.
196    --extra-configure-args <args>: Extra args to pass when configuring libvpx.
197    --jobs: Number of make jobs.
198    --preserve-build-output: Do not delete the build directory.
199    --show-build-output: Show output from each library build.
200    --targets <targets>: Override default target list. Defaults:
201         ${TARGETS}
202    --verbose: Output information about the environment and each stage of the
203               build.
204EOF
205}
206
207elog() {
208  echo "${0##*/} failed because: $@" 1>&2
209}
210
211vlog() {
212  if [ "${VERBOSE}" = "yes" ]; then
213    echo "$@"
214  fi
215}
216
217trap cleanup EXIT
218
219# Parse the command line.
220while [ -n "$1" ]; do
221  case "$1" in
222    --extra-configure-args)
223      EXTRA_CONFIGURE_ARGS="$2"
224      shift
225      ;;
226    --help)
227      iosbuild_usage
228      exit
229      ;;
230    --jobs)
231      MAKE_JOBS="$2"
232      shift
233      ;;
234    --preserve-build-output)
235      PRESERVE_BUILD_OUTPUT=yes
236      ;;
237    --show-build-output)
238      devnull=
239      ;;
240    --targets)
241      TARGETS="$2"
242      shift
243      ;;
244    --verbose)
245      VERBOSE=yes
246      ;;
247    *)
248      iosbuild_usage
249      exit 1
250      ;;
251  esac
252  shift
253done
254
255if [ "${VERBOSE}" = "yes" ]; then
256cat << EOF
257  BUILD_ROOT=${BUILD_ROOT}
258  DIST_DIR=${DIST_DIR}
259  CONFIGURE_ARGS=${CONFIGURE_ARGS}
260  EXTRA_CONFIGURE_ARGS=${EXTRA_CONFIGURE_ARGS}
261  FRAMEWORK_DIR=${FRAMEWORK_DIR}
262  HEADER_DIR=${HEADER_DIR}
263  MAKE_JOBS=${MAKE_JOBS}
264  PRESERVE_BUILD_OUTPUT=${PRESERVE_BUILD_OUTPUT}
265  LIBVPX_SOURCE_DIR=${LIBVPX_SOURCE_DIR}
266  LIPO=${LIPO}
267  ORIG_PWD=${ORIG_PWD}
268  TARGETS="${TARGETS}"
269EOF
270fi
271
272build_framework "${TARGETS}"
273echo "Successfully built '${FRAMEWORK_DIR}' for:"
274echo "         ${TARGETS}"
275