aboutsummaryrefslogtreecommitdiffstats
path: root/packaging/android/qmake-build.sh
blob: 402846f21954f657c36eb260db377113b4bd0150 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
#!/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

# 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

# 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 ./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
	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 ANDROID_ABIS="$BUILD_ABIS" ../googlemaps/googlemaps.pro
	    make -j4
            make install
	    popd
	fi
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.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