diff options
author | Dirk Hohndel <dirk@hohndel.org> | 2020-11-18 22:02:38 +0000 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2020-11-19 17:18:33 -0800 |
commit | 64913bba475ae04cd3300e73f7de8b81b1021e38 (patch) | |
tree | 22b414d8213761bc4ea3b730c6d60ef54bdd6b7c /packaging/android | |
parent | 3a00ac0157ca4ad680c79da269a52bcd4f71f8d6 (diff) | |
download | subsurface-64913bba475ae04cd3300e73f7de8b81b1021e38.tar.gz |
android: add qmake based build for Subsurface-mobile
Several features that are needed to create Android bundles with the
current NDK and QT 5.15 aren't easily available when using cmake. Given
that we already do a qmake based build for iOS, I decided to simply
switch Android to that as well.
An added complication is that some of the magic that qmake uses to do
the right things fails if the .pro file isn't in the root directory of
your project. So this is right now somewhat inconsistent with the way we
build for iOS. Something that should get cleaned up in the near future
as it makes no sense to maintain two separate .pro files.
This commits also adds a new build shell script to drive the assembly of
all the dependencies. Once again this is a new file with the old one
left in place for now (but to be removed fairly soon).
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Diffstat (limited to 'packaging/android')
-rwxr-xr-x | packaging/android/build.sh | 6 | ||||
-rwxr-xr-x | packaging/android/qmake-build.sh | 369 | ||||
-rw-r--r-- | packaging/android/translations.qrc | 27 |
3 files changed, 402 insertions, 0 deletions
diff --git a/packaging/android/build.sh b/packaging/android/build.sh index 718721b6a..53b22c7b8 100755 --- a/packaging/android/build.sh +++ b/packaging/android/build.sh @@ -1,5 +1,11 @@ #!/bin/bash # +# THIS IS OBSOLETE AN ONLY WORKS UP TO Qt 5.13 +# for now keeping it around for reference + + + +# # Filesystem layout considerations... # for this explanation I assume that your Subsurface sources are in # ~/src/subsurface diff --git a/packaging/android/qmake-build.sh b/packaging/android/qmake-build.sh new file mode 100755 index 000000000..6b4321ad2 --- /dev/null +++ b/packaging/android/qmake-build.sh @@ -0,0 +1,369 @@ +#!/bin/bash +# +# build a multi architecture package for Android +# +# this requires Qt5.14 or newer with matching NDK +# +# the packaging/android/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 + +# and now we need a monotonic build number... +if [ ! -f ./buildnr.dat ] ; then + BUILDNR=0 +else + BUILDNR=$(cat ./buildnr.dat) +fi +BUILDNR=$((BUILDNR+1)) +echo "${BUILDNR}" > ./buildnr.dat + +# Read build variables +source $SUBSURFACE_SOURCE/packaging/android/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/.." + +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 + +mkdir -p "$BUILDROOT"/subsurface-mobile-build +pushd "$BUILDROOT"/subsurface-mobile-build + +# set up the Subsurface versions by hand +GITVERSION=$(cd "$SUBSURFACE_SOURCE" ; git describe --abbrev=12) +CANONICALVERSION=$(echo "$GITVERSION" | sed -e 's/-g.*$// ; s/^v//' | sed -e 's/-/./') +MOBILEVERSION=$(grep MOBILE "$SUBSURFACE_SOURCE"/cmake/Modules/version.cmake | cut -d\" -f 2) +echo "#define GIT_VERSION_STRING \"$GITVERSION\"" > ssrf-version.h +echo "#define CANONICAL_VERSION_STRING \"$CANONICALVERSION\"" >> ssrf-version.h +echo "#define MOBILE_VERSION_STRING \"$MOBILEVERSION\"" >> ssrf-version.h +SUBSURFACE_MOBILE_VERSION="$MOBILEVERSION ($CANONICALVERSION)" +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 + + +# if we are just doing a quick rebuild, don't bother with any of the dependencies + +if [ "$QUICK" = "" ] ; then + + # 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 + QT_PLUGINS_PATH=$($QMAKE -query QT_INSTALL_PLUGINS) + GOOGLEMAPS_BIN=libqtgeoservices_googlemaps.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 ../googlemaps/googlemaps.pro + make -j4 + # $QMAKE -install qinstall -exe $GOOGLEMAPS_BIN "$QT_PLUGINS_PATH"/geoservices/$GOOGLEMAPS_BIN + make install + popd + fi +fi + +# autoconf based libraries are harder +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 + +# build default architectures, or the given one? +if [ "$ARCHITECTURES" = "" ] ; then + ARCHITECTURES="armv7a aarch64" +fi + +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 + BUILD_ABIS="$BUILD_ABIS $ANDROID_ABI" + + 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 + + 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 + +#"${SUBSURFACE_SOURCE}"/scripts/get-dep-lib.sh singleAndroid . qt-android-cmake +# the Qt Android cmake addon runs androiddeployqt with '--verbose' which +# is, err, rather verbose. Let's not do that. +#sed -i -e 's/--verbose//' qt-android-cmake/AddQtAndroidApk.cmake + +# if this isn't just a quick rebuild, pull kirigami, icons, etc +if [ "$QUICK" = "" ] ; then + pushd "$SUBSURFACE_SOURCE" + bash ./scripts/mobilecomponents.sh + popd +fi + +# 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="$SUBSURFACE_MOBILE_VERSION" ANDROID_ABIS="$BUILD_ABIS" "$SUBSURFACE_SOURCE"/Subsurface-mobile-android.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 aab + diff --git a/packaging/android/translations.qrc b/packaging/android/translations.qrc new file mode 100644 index 000000000..2bf25d0fc --- /dev/null +++ b/packaging/android/translations.qrc @@ -0,0 +1,27 @@ +<RCC> + <qresource prefix="/"> + <file alias="subsurface_bg_BG.qm">translation-assets/subsurface_bg_BG.qm</file> + <file alias="subsurface_cd.qm">translation-assets/subsurface_cs.qm</file> + <file alias="subsurface_da_DK.qm">translation-assets/subsurface_da_DK.qm</file> + <file alias="subsurface_de_CH">translation-assets/subsurface_de_CH.qm</file> + <file alias="subsurface_de_DE">translation-assets/subsurface_de_DE.qm</file> + <file alias="subsurface_en_GB">translation-assets/subsurface_en_GB.qm</file> + <file alias="subsurface_en_US">translation-assets/subsurface_en_US.qm</file> + <file alias="subsurface_es_ES">translation-assets/subsurface_es_ES.qm</file> + <file alias="subsurface_et_EE">translation-assets/subsurface_et_EE.qm</file> + <file alias="subsurface_fi_FI">translation-assets/subsurface_fi_FI.qm</file> + <file alias="subsurface_fr_FR">translation-assets/subsurface_fr_FR.qm</file> + <file alias="subsurface_he">translation-assets/subsurface_he.qm</file> + <file alias="subsurface_it_IT">translation-assets/subsurface_it_IT.qm</file> + <file alias="subsurface_nb_NO">translation-assets/subsurface_nb_NO.qm</file> + <file alias="subsurface_nl_NL">translation-assets/subsurface_nl_NL.qm</file> + <file alias="subsurface_pl_PL">translation-assets/subsurface_pl_PL.qm</file> + <file alias="subsurface_pt_BR">translation-assets/subsurface_pt_BR.qm</file> + <file alias="subsurface_pt_PT">translation-assets/subsurface_pt_PT.qm</file> + <file alias="subsurface_ro_RO">translation-assets/subsurface_ro_RO.qm</file> + <file alias="subsurface_ru_RU">translation-assets/subsurface_ru_RU.qm</file> + <file alias="subsurface_sk_SK">translation-assets/subsurface_sk_SK.qm</file> + <file alias="subsurface_sv_SE">translation-assets/subsurface_sv_SE.qm</file> + <file alias="subsurface_zh_TW">translation-assets/subsurface_zh_TW.qm</file> + </qresource> +</RCC> |