diff --git a/infra/common.sh b/infra/common.sh index 2b526eac..9f51a6c2 100644 --- a/infra/common.sh +++ b/infra/common.sh @@ -47,3 +47,13 @@ make_build_dir() { rm -rf "${build_dir}" mkdir -p "${build_dir}" } + +####################################### +# Setup ccache for toolchain. +####################################### +setup_ccache() { + if [[ -x "$(command -v ccache)" ]]; then + export CCACHE_CPP2=yes + export PATH="/usr/lib/ccache:${PATH}" + fi +} diff --git a/infra/compile_android.sh b/infra/compile_android.sh new file mode 100755 index 00000000..013b97cd --- /dev/null +++ b/infra/compile_android.sh @@ -0,0 +1,224 @@ +#!/bin/bash +# Copyright (c) 2021, Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# * Neither the name of Google nor the names of its contributors may +# be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +set -xe +LIBWEBP_ROOT="$(realpath "$(dirname "$0")/..")" +readonly LIBWEBP_ROOT +readonly WORKSPACE=${WORKSPACE:-"$(mktemp -d -t webp.android.XXX)"} +# shellcheck source=infra/common.sh +source "${LIBWEBP_ROOT}/infra/common.sh" + +usage() { + cat << EOF +Usage: $(basename "$0") BUILD_TYPE APP_ABI +Options: +BUILD_TYPE supported build types: + static + static-debug + shared + shared-debug +APP_ABI supported application binary interfaces: + armeabi-v7a + arm64-v8a + x86 + x86_64 +Environment variables: +WORKSPACE directory where the build is done. +ANDROID_NDK_DIR directory where the android ndk tools are. +EOF +} + +################################################################################ +echo "Building libwebp for Android in ${WORKSPACE}" + +if [[ ! -d "${WORKSPACE}" ]]; then + log_err "${WORKSPACE} directory does not exist." + exit 1 +fi + +readonly BUILD_TYPE=${1:?"BUILD_TYPE is not defined.$( + echo + usage +)"} +readonly APP_ABI=${2:?"APP_ABI not defined.$( + echo + usage +)"} +readonly ANDROID_NDK_DIR=${ANDROID_NDK_DIR:?"ANDROID_NDK_DIR is not defined.$( + echo + usage +)"} +readonly BUILD_DIR="${WORKSPACE}/build-${BUILD_TYPE}" +readonly STANDALONE_ANDROID_DIR="${WORKSPACE}/android" + +if [[ ! -x "${ANDROID_NDK_DIR}/ndk-build" ]]; then + log_err "unable to find ndk-build in ANDROID_NDK_DIR: ${ANDROID_NDK_DIR}." + exit 1 +fi + +CFLAGS= +LDFLAGS= +opts=() +case "${BUILD_TYPE}" in + *debug) + readonly APP_OPTIM="debug" + CFLAGS="-O0 -g" + opts+=("--enable-asserts") + ;; + static* | shared*) + readonly APP_OPTIM="release" + CFLAGS="-O2 -g" + ;; + *) + usage + exit 1 + ;; +esac + +case "${BUILD_TYPE}" in + shared*) readonly SHARED="1" ;; + *) + readonly SHARED="0" + CFLAGS="${CFLAGS} -fPIE" + LDFLAGS="${LDFLAGS} -Wl,-pie" + opts+=("--disable-shared") + ;; +esac + +# Create a fresh build directory +make_build_dir "${BUILD_DIR}" +cd "${BUILD_DIR}" +ln -s "${LIBWEBP_ROOT}" jni + +"${ANDROID_NDK_DIR}/ndk-build" -j2 \ + APP_ABI="${APP_ABI}" \ + APP_OPTIM="${APP_OPTIM}" \ + ENABLE_SHARED="${SHARED}" + +cd "${LIBWEBP_ROOT}" +./autogen.sh + +case "${APP_ABI}" in + armeabi*) arch="arm" ;; + arm64*) arch="arm64" ;; + *) arch="${APP_ABI}" ;; +esac +# TODO(b/185520507): remove this and use the binaries from +# toolchains/llvm/prebuilt/ directly. +rm -rf "${STANDALONE_ANDROID_DIR}" +"${ANDROID_NDK_DIR}/build/tools/make_standalone_toolchain.py" \ + --api 24 --arch "${arch}" --stl gnustl --install-dir \ + "${STANDALONE_ANDROID_DIR}" +export PATH="${STANDALONE_ANDROID_DIR}/bin:${PATH}" + +rm -rf "${BUILD_DIR}" +make_build_dir "${BUILD_DIR}" +cd "${BUILD_DIR}" + +case "${arch}" in + arm) + host="arm-linux-androideabi" + case "${APP_ABI}" in + armeabi) ;; + armeabi-v7a) + CFLAGS="${CFLAGS} -march=armv7-a -mfpu=neon -mfloat-abi=softfp" + ;; + *) ;; # No configuration needed + esac + ;; + arm64) + host="aarch64-linux-android" + ;; + x86) + host="i686-linux-android" + ;; + x86_64) + host="x86_64-linux-android" + ;; + *) ;; # Skip configuration +esac + +setup_ccache +CC="clang" + +"${LIBWEBP_ROOT}/configure" --host "${host}" --build \ + "$("${LIBWEBP_ROOT}/config.guess")" CC="${CC}" CFLAGS="${CFLAGS}" \ + LDFLAGS="${LDFLAGS}" "${opts[@]}" +make -j + +if [[ "${GERRIT_REFSPEC:-}" = "refs/heads/portable-intrinsics" ]] \ + || [[ "${GERRIT_BRANCH:-}" = "portable-intrinsics" ]]; then + cd "${WORKSPACE}" + rm -rf build && mkdir build + cd build + standalone="${WORKSPACE}/android" + cmake ../libwebp \ + -DWEBP_BUILD_DWEBP=1 \ + -DCMAKE_C_COMPILER="${standalone}/bin/clang" \ + -DCMAKE_PREFIX_PATH="${standalone}/sysroot/usr/lib" \ + -DCMAKE_C_FLAGS=-fPIE \ + -DCMAKE_EXE_LINKER_FLAGS=-Wl,-pie \ + -DCMAKE_BUILD_TYPE=Release \ + -DWEBP_ENABLE_WASM=1 + make -j2 + + cd "${WORKSPACE}" + make_build_dir "${BUILD_DIR}" + cd "${BUILD_DIR}" + case "${APP_ABI}" in + armeabi-v7a | arm64*) + cmake "${LIBWEBP_ROOT}" \ + -DWEBP_BUILD_DWEBP=1 \ + -DCMAKE_C_COMPILER="${standalone}/bin/clang" \ + -DCMAKE_PREFIX_PATH="${standalone}/sysroot/usr/lib" \ + -DCMAKE_C_FLAGS='-fPIE -DENABLE_NEON_BUILTIN_MULHI_INT16X8' \ + -DCMAKE_EXE_LINKER_FLAGS=-Wl,-pie \ + -DCMAKE_BUILD_TYPE=Release \ + -DWEBP_ENABLE_WASM=1 + make -j2 + ;; + x86*) + cmake "${LIBWEBP_ROOT}" \ + -DWEBP_BUILD_DWEBP=1 \ + -DCMAKE_C_COMPILER="${standalone}/bin/clang" \ + -DCMAKE_PREFIX_PATH="${standalone}/sysroot/usr/lib" \ + -DCMAKE_C_FLAGS='-fPIE -DENABLE_X86_BUILTIN_MULHI_INT16X8' \ + -DCMAKE_EXE_LINKER_FLAGS=-Wl,-pie \ + -DCMAKE_BUILD_TYPE=Release \ + -DWEBP_ENABLE_WASM=1 + make -j2 + ;; + *) + log_err "APP_ABI not supported." + exit 1 + ;; + esac +fi