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