mirror of
https://github.com/subsurface/subsurface.git
synced 2024-12-05 00:21:29 +00:00
b5efaf661c
Move around the scripts required for the setup of the build environment for android to satisfy docker's requirement of locality. This allows the removal of an extra copy step, and avoids the creation of extra artefacts, while still providing the same functionality. Signed-off-by: Michael Keller <github@ike.ch>
430 lines
13 KiB
Bash
Executable file
430 lines
13 KiB
Bash
Executable file
#!/bin/bash
|
|
#
|
|
# build a multi architecture package for Android
|
|
#
|
|
# this requires Qt5.14 or newer with matching NDK
|
|
#
|
|
# the scripts/docker/android-build-container/android-build-setup.sh sets up an environment that works for this
|
|
|
|
set -eu
|
|
|
|
exec 1> >(tee ./android-build.log) 2>&1
|
|
|
|
# get the absolute path
|
|
pushd "$(dirname "$0")/../../"
|
|
export SUBSURFACE_SOURCE=$PWD
|
|
cd ..
|
|
export BUILDROOT=$PWD
|
|
popd
|
|
|
|
# Set build defaults
|
|
# is this a release or debug build
|
|
BUILD_TYPE=Debug
|
|
|
|
# Read build variables
|
|
source $SUBSURFACE_SOURCE/scripts/docker/android-build-container/variables.sh
|
|
|
|
# this assumes that the Subsurface source directory is in the same
|
|
# directory hierarchy as the SDK and NDK
|
|
export ANDROID_NDK_ROOT="$SUBSURFACE_SOURCE/../$ANDROID_NDK"
|
|
export ANDROID_SDK_ROOT="$SUBSURFACE_SOURCE/.."
|
|
export JAVA_OPTS="-Dsun.jnu.encoding=UTF-8 -Dfile.encoding=UTF-8"
|
|
|
|
QUICK=""
|
|
ARCHITECTURES=""
|
|
BUILD_ABIS=""
|
|
versionOnly=""
|
|
|
|
while [ "$#" -gt 0 ] ; do
|
|
case "$1" in
|
|
Release|release)
|
|
shift
|
|
BUILD_TYPE=Release
|
|
;;
|
|
Debug|debug)
|
|
# this is the default - still need to eat the argument if given
|
|
BUILD_TYPE=Debug
|
|
shift
|
|
;;
|
|
-buildnr)
|
|
shift
|
|
BUILDNR=$1
|
|
shift
|
|
;;
|
|
-version)
|
|
# only update the version info without rebuilding
|
|
# this is useful when working with Xcode
|
|
versionOnly="1"
|
|
;;
|
|
arm|arm64|x86|x86_64)
|
|
ARCHITECTURES=$1
|
|
shift
|
|
;;
|
|
-quick)
|
|
QUICK="1"
|
|
shift
|
|
;;
|
|
*)
|
|
echo "Unknown argument $1"
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [ -z "${BUILDNR+X}" ] ; then
|
|
# we need a monotonic build number...
|
|
if [ ! -f ./buildnr.dat ] ; then
|
|
BUILDNR=0
|
|
else
|
|
BUILDNR=$(cat ./buildnr.dat)
|
|
fi
|
|
BUILDNR=$((BUILDNR+1))
|
|
fi
|
|
echo "${BUILDNR}" > ./buildnr.dat
|
|
|
|
mkdir -p "$BUILDROOT"/subsurface-mobile-build
|
|
pushd "$BUILDROOT"/subsurface-mobile-build
|
|
|
|
# set up the Subsurface versions by hand
|
|
CANONICALVERSION=$("$SUBSURFACE_SOURCE"/scripts/get-version)
|
|
echo "#define CANONICAL_VERSION_STRING \"$CANONICALVERSION\"" > ssrf-version.h
|
|
CANONICALVERSION_4=$("$SUBSURFACE_SOURCE"/scripts/get-version 4)
|
|
echo "#define CANONICAL_VERSION_STRING_4 \"$CANONICALVERSION_4\"" >> ssrf-version.h
|
|
popd
|
|
|
|
if [ "$versionOnly" = "1" ] ; then
|
|
exit 0
|
|
fi
|
|
|
|
# pick the Qt setup and show the configuration info
|
|
if [ -n "${QT5_ANDROID+X}" ] ; then
|
|
echo "Using Qt5 in $QT5_ANDROID"
|
|
elif [ -d "$SUBSURFACE_SOURCE/../${LATEST_QT}" ] ; then
|
|
export QT5_ANDROID=$SUBSURFACE_SOURCE/../${LATEST_QT}
|
|
else
|
|
echo "Cannot find Qt 5.12 or newer under $SUBSURFACE_SOURCE/.."
|
|
exit 1
|
|
fi
|
|
|
|
QMAKE=$QT5_ANDROID/android/bin/qmake
|
|
echo $QMAKE
|
|
$QMAKE -query
|
|
|
|
export TOOLCHAIN="$ANDROID_NDK_ROOT"/toolchains/llvm/prebuilt/linux-x86_64
|
|
PATH=$TOOLCHAIN/bin:$PATH
|
|
export ANDROID_NDK_HOME=$ANDROID_NDK_ROOT # redundant, but that's what openssl wants
|
|
|
|
# make sure we have the font that we need for OnePlus phones due to https://bugreports.qt.io/browse/QTBUG-69494
|
|
if [ ! -f "$SUBSURFACE_SOURCE"/android-mobile/Roboto-Regular.ttf ] ; then
|
|
cp "$ANDROID_SDK_ROOT"/platforms/"$ANDROID_PLATFORMS"/data/fonts/Roboto-Regular.ttf "$SUBSURFACE_SOURCE"/android-mobile || exit 1
|
|
fi
|
|
|
|
# next, make sure that the libdivecomputer sources are downloaded and
|
|
# ready for autoconfig
|
|
pushd "$SUBSURFACE_SOURCE"
|
|
if [ ! -d libdivecomputer/src ] ; then
|
|
git submodule init
|
|
git submodule update
|
|
fi
|
|
if [ ! -f libdivecomputer/configure ] ; then
|
|
cd libdivecomputer
|
|
autoreconf -i
|
|
fi
|
|
popd
|
|
|
|
# build default architectures, or the given one?
|
|
if [ "$ARCHITECTURES" = "" ] ; then
|
|
ARCHITECTURES="armv7a aarch64"
|
|
fi
|
|
|
|
# it would of course be too easy to use these terms consistently, so let's not
|
|
# no where do we support x86 style Android builds - there aren't any relevant devices
|
|
for ARCH in $ARCHITECTURES ; do
|
|
if [ "$ARCH" = "armv7a" ] ; then
|
|
ANDROID_ABI="armeabi-v7a"
|
|
else
|
|
ANDROID_ABI="arm64-v8a"
|
|
fi
|
|
BUILD_ABIS="$BUILD_ABIS $ANDROID_ABI"
|
|
done
|
|
|
|
# if this isn't just a quick rebuild, pull kirigami, icons, etc, and finally build the Googlemaps plugin
|
|
if [ "$QUICK" = "" ] ; then
|
|
pushd "$SUBSURFACE_SOURCE"
|
|
bash -x ./scripts/mobilecomponents.sh
|
|
popd
|
|
|
|
# build google maps plugin
|
|
# this is the easy one as it uses qmake which ensures things get built for all platforms, etc
|
|
"${SUBSURFACE_SOURCE}"/scripts/get-dep-lib.sh singleAndroid . googlemaps
|
|
# but unfortunately, on Android (and apparently only on Android) the naming pattern for geoservice
|
|
# plugins has changed
|
|
pushd googlemaps
|
|
sed -i 's/TARGET = qtgeoservices_googlemaps/TARGET = plugins_geoservices_qtgeoservices_googlemaps/' googlemaps.pro
|
|
popd
|
|
QT_PLUGINS_PATH=$($QMAKE -query QT_INSTALL_PLUGINS)
|
|
GOOGLEMAPS_BIN=libplugins_geoservices_qtgeoservices_googlemaps_arm64-v8a.so
|
|
if [ ! -e "$QT_PLUGINS_PATH"/geoservices/$GOOGLEMAPS_BIN ] || [ googlemaps/.git/HEAD -nt "$QT_PLUGINS_PATH"/geoservices/$GOOGLEMAPS_BIN ] ; then
|
|
mkdir -p googlemaps-build
|
|
pushd googlemaps-build
|
|
$QMAKE ANDROID_ABIS="$BUILD_ABIS" ../googlemaps/googlemaps.pro
|
|
make -j4
|
|
make install
|
|
popd
|
|
fi
|
|
fi
|
|
|
|
# autoconf based libraries are harder
|
|
for ARCH in $ARCHITECTURES ; do
|
|
echo "START building libraries for $ARCH"
|
|
echo "====================================="
|
|
|
|
# it would of course be too easy to use these terms consistently, so let's not
|
|
if [ "$ARCH" = "armv7a" ] ; then
|
|
EABI="eabi"
|
|
BINUTIL_ARCH="arm"
|
|
OPENSSL_ARCH="arm"
|
|
ANDROID_ABI="armeabi-v7a"
|
|
else
|
|
EABI=""
|
|
BINUTIL_ARCH="aarch64"
|
|
OPENSSL_ARCH="arm64"
|
|
ANDROID_ABI="arm64-v8a"
|
|
fi
|
|
|
|
export TARGET=$ARCH-linux-android
|
|
export AR=$TOOLCHAIN/bin/$BINUTIL_ARCH-linux-android$EABI-ar
|
|
export AS=$TOOLCHAIN/bin/$BINUTIL_ARCH-linux-android$EABI-as
|
|
export CC=$TOOLCHAIN/bin/$TARGET$EABI$ANDROID_PLATFORM_LEVEL-clang
|
|
export CXX=$TOOLCHAIN/bin/$TARGET$EABI$ANDROID_PLATFORM_LEVEL-clang++
|
|
export LD=$TOOLCHAIN/bin/$BINUTIL_ARCH-linux-android$EABI-ld
|
|
export RANLIB=$TOOLCHAIN/bin/$BINUTIL_ARCH-linux-android$EABI-ranlib
|
|
export STRIP=$TOOLCHAIN/bin/$BINUTIL_ARCH-linux-android$EABI-strip
|
|
|
|
# set up an install root and create part of the directory structure so the openssl
|
|
# manual install below doesn't fail
|
|
export PREFIX="$BUILDROOT"/install-root-"$ANDROID_ABI"
|
|
mkdir -p "$PREFIX"/include
|
|
mkdir -p "$PREFIX"/lib/pkgconfig
|
|
export PKG_CONFIG_PATH=$PREFIX/lib/pkgconfig
|
|
|
|
if [ "$QUICK" = "" ] ; then
|
|
"${SUBSURFACE_SOURCE}"/scripts/get-dep-lib.sh singleAndroid . openssl
|
|
if [ ! -e "$PKG_CONFIG_PATH/libssl.pc" ] ; then
|
|
# openssl build fails with these set
|
|
export SYSROOT=""
|
|
export CFLAGS=""
|
|
export CPPFLAGS=""
|
|
export CXXFLAGS=""
|
|
|
|
mkdir -p openssl-build-"$ARCH"
|
|
cp -r openssl/* openssl-build-"$ARCH"
|
|
pushd openssl-build-"$ARCH"
|
|
perl -pi -e 's/-mandroid//g' Configure
|
|
./Configure shared android-"$OPENSSL_ARCH" no-ssl2 no-ssl3 no-comp no-hw no-engine no-asm \
|
|
--prefix="$PREFIX" -DOPENSSL_NO_UI_CONSOLE -DOPENSSL_NO_STDIO \
|
|
-D__ANDROID_API__=$ANDROID_PLATFORM_LEVEL
|
|
make depend
|
|
# follow the suggestions here: https://doc.qt.io/qt-5/android-openssl-support.html
|
|
make SHLIB_VERSION_NUMBER= SHLIB_EXT=_1_1.so build_libs
|
|
|
|
cp -RL include/openssl $PREFIX/include/openssl
|
|
cp libcrypto.a $PREFIX/lib
|
|
cp libcrypto_1_1.so* $PREFIX/lib
|
|
cp libssl.a $PREFIX/lib
|
|
cp libssl_1_1.so* $PREFIX/lib
|
|
cp *.pc $PKG_CONFIG_PATH
|
|
|
|
popd
|
|
fi
|
|
|
|
fi
|
|
|
|
# autoconf seems to get lost without this -- but openssl fails if these are set
|
|
SYSROOT="$ANDROID_NDK_ROOT"/toolchains/llvm/prebuilt/linux-x86_64/sysroot
|
|
CFLAGS="--sysroot=${SYSROOT} -fPIC"
|
|
CPPFLAGS="--sysroot=${SYSROOT} -fPIC"
|
|
CXXFLAGS="--sysroot=${SYSROOT} -fPIC"
|
|
|
|
if [ "$QUICK" = "" ] ; then
|
|
"${SUBSURFACE_SOURCE}"/scripts/get-dep-lib.sh singleAndroid . sqlite
|
|
if [ ! -e "$PKG_CONFIG_PATH/sqlite3.pc" ] ; then
|
|
mkdir -p sqlite-build-"$ARCH"
|
|
pushd sqlite-build-"$ARCH"
|
|
../sqlite/configure --host="$TARGET" --prefix="$PREFIX" --enable-static --disable-shared
|
|
make
|
|
make install
|
|
popd
|
|
fi
|
|
|
|
"${SUBSURFACE_SOURCE}"/scripts/get-dep-lib.sh singleAndroid . libxml2
|
|
if [ ! -e libxml2/configure ] ; then
|
|
pushd libxml2
|
|
autoreconf --install
|
|
popd
|
|
fi
|
|
if [ ! -e "$PKG_CONFIG_PATH/libxml-2.0.pc" ] ; then
|
|
mkdir -p libxml2-build-"$ARCH"
|
|
pushd libxml2-build-"$ARCH"
|
|
../libxml2/configure --host="$TARGET" --prefix="$PREFIX" --without-python --without-iconv --enable-static --disable-shared
|
|
perl -pi -e 's/runtest\$\(EXEEXT\)//' Makefile
|
|
perl -pi -e 's/testrecurse\$\(EXEEXT\)//' Makefile
|
|
make
|
|
make install
|
|
popd
|
|
fi
|
|
|
|
"${SUBSURFACE_SOURCE}"/scripts/get-dep-lib.sh singleAndroid . libxslt
|
|
if [ ! -e libxslt/configure ] ; then
|
|
pushd libxslt
|
|
autoreconf --install
|
|
popd
|
|
fi
|
|
if [ ! -e "$PKG_CONFIG_PATH/libxslt.pc" ] ; then
|
|
mkdir -p libxslt-build-"$ARCH"
|
|
pushd libxslt-build-"$ARCH"
|
|
../libxslt/configure --host="$TARGET" --prefix="$PREFIX" --with-libxml-prefix="$PREFIX" --without-python --without-crypto --enable-static --disable-shared
|
|
make
|
|
make install
|
|
popd
|
|
fi
|
|
|
|
"${SUBSURFACE_SOURCE}"/scripts/get-dep-lib.sh singleAndroid . libzip
|
|
if [ ! -e "$PKG_CONFIG_PATH/libzip.pc" ] ; then
|
|
# libzip expects a predefined macro that isn't there for our compiler
|
|
pushd libzip
|
|
git reset --hard
|
|
sed -i 's/SIZEOF_SIZE_T/__SIZEOF_SIZE_T__/g' lib/compat.h
|
|
# also, don't deal with manuals and bzip2
|
|
sed -i 's/ADD_SUBDIRECTORY(man)//' CMakeLists.txt
|
|
sed -i 's/^FIND_PACKAGE(ZLIB/#&/' CMakeLists.txt
|
|
popd
|
|
mkdir -p libzip-build-"$ARCH"
|
|
pushd libzip-build-"$ARCH"
|
|
cmake \
|
|
-DCMAKE_C_COMPILER="$CC" \
|
|
-DCMAKE_LINKER="$CC" \
|
|
-DCMAKE_INSTALL_PREFIX="$PREFIX" \
|
|
-DCMAKE_INSTALL_LIBDIR="lib" \
|
|
-DBUILD_SHARED_LIBS=OFF \
|
|
-DCMAKE_DISABLE_FIND_PACKAGE_BZip2=TRUE \
|
|
-DZLIB_VERSION_STRING=1.2.7 \
|
|
-DZLIB_LIBRARY=z \
|
|
../libzip/
|
|
make
|
|
make install
|
|
popd
|
|
fi
|
|
|
|
"${SUBSURFACE_SOURCE}"/scripts/get-dep-lib.sh singleAndroid . libgit2
|
|
if [ ! -e "$PKG_CONFIG_PATH/libgit2.pc" ] ; then
|
|
# We don't want to find the HTTP_Parser package of the build host by mistake
|
|
mkdir -p libgit2-build-"$ARCH"
|
|
pushd libgit2-build-"$ARCH"
|
|
cmake \
|
|
-DCMAKE_C_COMPILER="$CC" \
|
|
-DCMAKE_LINKER="$CC" \
|
|
-DBUILD_CLAR=OFF -DBUILD_SHARED_LIBS=OFF \
|
|
-DCMAKE_INSTALL_PREFIX="$PREFIX" \
|
|
-DCURL=OFF \
|
|
-DUSE_SSH=OFF \
|
|
-DOPENSSL_SSL_LIBRARY="$PREFIX"/lib/libssl_1_1.so \
|
|
-DOPENSSL_CRYPTO_LIBRARY="$PREFIX"/lib/libcrypto_1_1.so \
|
|
-DOPENSSL_INCLUDE_DIR="$PREFIX"/include \
|
|
-D_OPENSSL_VERSION="${OPENSSL_VERSION}" \
|
|
-DCMAKE_DISABLE_FIND_PACKAGE_HTTP_Parser=TRUE \
|
|
../libgit2/
|
|
make
|
|
make install
|
|
# Patch away pkg-config dependency to zlib, its there, i promise
|
|
perl -pi -e 's/^(Requires.private:.*)zlib(.*)$/$1 $2/' "$PKG_CONFIG_PATH"/libgit2.pc
|
|
popd
|
|
fi
|
|
|
|
fi # QUICK
|
|
|
|
# on Android I can't make an integrated build work, so let's build Kirigami separately?
|
|
mkdir -p "$BUILDROOT"/kirigami-build-"$ARCH"
|
|
pushd "$BUILDROOT"/kirigami-build-"$ARCH"
|
|
cmake \
|
|
-DANDROID="1" \
|
|
-DANDROID_ABI="$ANDROID_ABI" \
|
|
-DBUILD_SHARED_LIBS="OFF" \
|
|
-DBUILD_EXAMPLES="OFF" \
|
|
-DCMAKE_PREFIX_PATH=/android/5.15.1/android/lib/cmake \
|
|
-DCMAKE_C_COMPILER="$CC" \
|
|
-DCMAKE_LINKER="$CC" \
|
|
-DCMAKE_INSTALL_PREFIX="$PREFIX" \
|
|
-DECM_DIR="$SUBSURFACE_SOURCE"/mobile-widgets/3rdparty/ECM \
|
|
"$SUBSURFACE_SOURCE"/mobile-widgets/3rdparty/kirigami
|
|
make
|
|
make install
|
|
popd
|
|
|
|
CURRENT_SHA=$(cd "$SUBSURFACE_SOURCE"/libdivecomputer ; git describe)
|
|
PREVIOUS_SHA=$(cat "libdivecomputer-${ARCH}.SHA" 2>/dev/null || echo)
|
|
if [ ! "$CURRENT_SHA" = "$PREVIOUS_SHA" ] || [ ! -e "$PKG_CONFIG_PATH/libdivecomputer.pc" ] ; then
|
|
mkdir -p libdivecomputer-build-"$ARCH"
|
|
pushd libdivecomputer-build-"$ARCH"
|
|
"$SUBSURFACE_SOURCE"/libdivecomputer/configure --host="$TARGET" --prefix="$PREFIX" --enable-static --disable-shared --enable-examples=no
|
|
make
|
|
make install
|
|
popd
|
|
echo "$CURRENT_SHA" > "libdivecomputer-${ARCH}.SHA"
|
|
fi
|
|
echo "DONE building libraries for $ARCH"
|
|
echo "====================================="
|
|
done # ARCH
|
|
|
|
# set up the final build
|
|
pushd "$BUILDROOT"/subsurface-mobile-build
|
|
rm -rf android-build
|
|
mkdir android-build
|
|
pushd "$SUBSURFACE_SOURCE"/android-mobile
|
|
tar c . | (cd "$BUILDROOT"/subsurface-mobile-build/android-build ; tar x)
|
|
popd
|
|
|
|
# call qmake to set up the build
|
|
echo "Run qmake to setup the Subsurface-mobile build for all architectures"
|
|
$QMAKE BUILD_NR="$BUILDNR" BUILD_VERSION_NAME="$CANONICALVERSION" ANDROID_ABIS="$BUILD_ABIS" "$SUBSURFACE_SOURCE"/Subsurface-mobile.pro
|
|
|
|
# if this isn't just a quick rebuild compile the translations
|
|
if [ "$QUICK" = "" ] ; then
|
|
pushd "$SUBSURFACE_SOURCE"/translations
|
|
SRCS=$(ls ./*.ts | grep -v source)
|
|
popd
|
|
pushd "$SUBSURFACE_SOURCE"/packaging/android
|
|
mkdir -p translation-assets
|
|
for src in $SRCS; do
|
|
"$QT5_ANDROID"/android/bin/lrelease "$SUBSURFACE_SOURCE"/translations/"$src" -qm translation-assets/"${src/.ts/.qm}"
|
|
done
|
|
popd
|
|
fi
|
|
|
|
# now build the Subsurface aab
|
|
make apk
|
|
|
|
popd
|
|
|
|
APK=$(find . -name Subsurface-mobile.apk)
|
|
APK_DIR=$(dirname ${APK})
|
|
APK_FILE=$(basename ${APK})
|
|
|
|
pushd ${APK_DIR}
|
|
if [ -n "${KEYSTORE_FILE+X}" -a -f "${KEYSTORE_FILE}" -a -n "${KEYSTORE_PASSWORD+X}" ]; then
|
|
APKSIGNER_PARAMS=""
|
|
if [ -n "${KEYSTORE_ALIAS+X}" ]; then
|
|
APKSIGNER_PARAMS="${APKSIGNER_PARAMS} --ks-key-alias ${KEYSTORE_ALIAS}"
|
|
fi
|
|
|
|
zip -d ${APK_FILE} 'META-INF/*.SF' 'META-INF/*.RSA'
|
|
${BUILDROOT}/build-tools/29.0.3/zipalign -p 4 ${APK_FILE} $(basename ${APK_FILE} .apk)-aligned.apk
|
|
${BUILDROOT}/build-tools/29.0.3/apksigner sign -ks ${KEYSTORE_FILE} -ks-pass ${KEYSTORE_PASSWORD} ${APKSIGNER_PARAMS} -in $(basename ${APK_FILE} .apk)-aligned.apk -out Subsurface-mobile-"${CANONICALVERSION}".apk
|
|
else
|
|
mv ${APK_FILE} Subsurface-mobile-"${CANONICALVERSION}".apk
|
|
fi
|
|
|
|
if [ -n "${OUTPUT_DIR+X}" ] ; then
|
|
mv Subsurface-mobile-"${CANONICALVERSION}".apk "${OUTPUT_DIR}"/
|
|
fi
|
|
popd
|