mirror of
https://github.com/mappu/miqt.git
synced 2025-05-03 18:40:21 +00:00
android: major rework for all-in-one android support
This commit is contained in:
parent
687579d76f
commit
a4a4074948
@ -1,66 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# android-mktemplate generates a template json file suitable for use with the
|
||||
# androiddeployqt tool.
|
||||
|
||||
set -eu
|
||||
|
||||
# QT_PATH is already pre-set in our docker container environment. Includes trailing slash.
|
||||
QT_PATH=${QT_PATH:-/usr/local/Qt-5.15.13/}
|
||||
QT_ANDROID=${QT_ANDROID:-$QT_PATH}
|
||||
|
||||
ndk_version() {
|
||||
ls /opt/android-sdk/ndk/ | tail -n1
|
||||
}
|
||||
|
||||
target_sdk_version() {
|
||||
ls /opt/android-sdk/platforms | tail -n1 | sed -re 's/android-//'
|
||||
}
|
||||
|
||||
build_tools_version() {
|
||||
ls /opt/android-sdk/build-tools | tail -n1
|
||||
}
|
||||
|
||||
extra_libs() {
|
||||
if [[ -d /opt/android_openssl ]] ; then
|
||||
# Our miqt Qt5 container includes these extra .so libraries
|
||||
# However, the aqtinstall-based Qt 6 container does not use them
|
||||
echo "/opt/android_openssl/ssl_1.1/arm64-v8a/libssl_1_1.so,/opt/android_openssl/ssl_1.1/arm64-v8a/libcrypto_1_1.so"
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
|
||||
if [[ $# -ne 2 ]] ; then
|
||||
echo "Usage: android-mktemplate.sh appname output.json" >&2
|
||||
exit 1
|
||||
fi
|
||||
local ARG_APPNAME="$1"
|
||||
local ARG_DESTFILE="$2"
|
||||
|
||||
# Available fields are documented in the template file at
|
||||
# @ref /usr/local/Qt-5.15.13/mkspecs/features/android/android_deployment_settings.prf
|
||||
cat > "${ARG_DESTFILE}" <<EOF
|
||||
{
|
||||
"_description": "Generated by miqt/android-mktemplate",
|
||||
"application-binary": "${ARG_APPNAME}",
|
||||
"architectures": {
|
||||
"arm64-v8a" : "aarch64-linux-android"
|
||||
},
|
||||
"android-extra-libs": "$(extra_libs)",
|
||||
"android-min-sdk-version": "23",
|
||||
"android-target-sdk-version": "$(target_sdk_version)",
|
||||
"ndk": "/opt/android-sdk/ndk/$(ndk_version)",
|
||||
"ndk-host": "linux-x86_64",
|
||||
"qt": "${QT_ANDROID}",
|
||||
"sdk": "/opt/android-sdk",
|
||||
"sdkBuildToolsRevision": "$(build_tools_version)",
|
||||
"stdcpp-path": "/opt/android-sdk/ndk/$(ndk_version)/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/",
|
||||
"tool-prefix": "llvm",
|
||||
"toolchain-prefix": "llvm",
|
||||
"useLLVM": true
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
main "$@"
|
@ -1,106 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# android-stub-gen generates a .so that runs an exported function from another
|
||||
# so file. This is because Qt for Android always tries to run `main`, but Go's
|
||||
# c-shared build mode cannot export a function named `main`.
|
||||
|
||||
set -eu
|
||||
|
||||
main() {
|
||||
|
||||
if [[ $# -ne 3 && $# -ne 4 ]] ; then
|
||||
echo "Usage: android-gen-stub.sh src.so function-name dest.so [--qt6|--qt5]" >&2
|
||||
exit 1
|
||||
fi
|
||||
local ARG_SOURCE_SOFILE="$1"
|
||||
local ARG_FUNCTIONNAME="$2"
|
||||
local ARG_DEST_SOFILE="$3"
|
||||
local ARG_QTVERSION="${4:---qt5}"
|
||||
|
||||
local tmpdir=$(mktemp -d)
|
||||
trap "rm -r ${tmpdir}" EXIT
|
||||
|
||||
echo "- Using temporary directory: ${tmpdir}"
|
||||
|
||||
echo "Generating stub..."
|
||||
|
||||
cat > $tmpdir/miqtstub.cpp <<EOF
|
||||
#include <android/log.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef void goMainFunc_t();
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
__android_log_print(ANDROID_LOG_VERBOSE, "miqt_stub", "Starting up");
|
||||
|
||||
void* handle = dlopen("$(basename "$ARG_SOURCE_SOFILE")", RTLD_LAZY);
|
||||
if (handle == NULL) {
|
||||
__android_log_print(ANDROID_LOG_VERBOSE, "miqt_stub", "miqt_stub: null handle opening so: %s", dlerror());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void* goMain = dlsym(handle, "${ARG_FUNCTIONNAME}");
|
||||
if (goMain == NULL) {
|
||||
__android_log_print(ANDROID_LOG_VERBOSE, "miqt_stub", "miqt_stub: null handle looking for function: %s", dlerror());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
__android_log_print(ANDROID_LOG_VERBOSE, "miqt_stub", "miqt_stub: Found target, calling");
|
||||
|
||||
// Cast to function pointer and call
|
||||
goMainFunc_t* f = (goMainFunc_t*)goMain;
|
||||
f();
|
||||
|
||||
__android_log_print(ANDROID_LOG_VERBOSE, "miqt_stub", "miqt_stub: Target function returned");
|
||||
return 0;
|
||||
}
|
||||
|
||||
EOF
|
||||
|
||||
# Compile
|
||||
# Link with Qt libraries so that androiddeployqt detects us as being the
|
||||
# main shared library
|
||||
|
||||
if [[ $ARG_QTVERSION == '--qt5' ]] ; then
|
||||
|
||||
# QT_PATH is already pre-set in our docker container environment. Includes trailing slash.
|
||||
QT_PATH=${QT_PATH:-/usr/local/Qt-5.15.13/}
|
||||
echo "- Found Qt path: ${QT_PATH}"
|
||||
|
||||
$CXX -shared \
|
||||
-ldl \
|
||||
-llog \
|
||||
-L${QT_PATH}plugins/platforms -lplugins_platforms_qtforandroid_arm64-v8a \
|
||||
$(pkg-config --libs Qt5Widgets) \
|
||||
$(pkg-config --libs Qt5AndroidExtras) \
|
||||
$tmpdir/miqtstub.cpp \
|
||||
"-Wl,-soname,$(basename "$ARG_DEST_SOFILE")" \
|
||||
-o "$ARG_DEST_SOFILE"
|
||||
|
||||
elif [[ $ARG_QTVERSION == '--qt6' ]] ; then
|
||||
|
||||
# QT_ANDROID is already pre-set in our docker container environment. Does NOT include trailing slash
|
||||
QT_ANDROID=${QT_ANDROID:-/opt/Qt/6.6.1/android_arm64_v8a}
|
||||
echo "- Found Qt path: ${QT_ANDROID}"
|
||||
|
||||
# There is no AndroidExtras in Qt 6
|
||||
|
||||
$CXX -shared \
|
||||
-ldl \
|
||||
-llog \
|
||||
-L${QT_ANDROID}/plugins/platforms -lplugins_platforms_qtforandroid_arm64-v8a \
|
||||
$(pkg-config --libs Qt6Widgets) \
|
||||
$tmpdir/miqtstub.cpp \
|
||||
"-Wl,-soname,$(basename "$ARG_DEST_SOFILE")" \
|
||||
-o "$ARG_DEST_SOFILE"
|
||||
|
||||
else
|
||||
echo "Unknown Qt version argument "${ARG_QTVERSION}" (expected --qt5 or --qt6)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Done."
|
||||
}
|
||||
|
||||
main "$@"
|
415
cmd/miqt-docker/android-build.sh
Normal file
415
cmd/miqt-docker/android-build.sh
Normal file
@ -0,0 +1,415 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# android-build.sh allows building a MIQT Go application for Android.
|
||||
# For details, see the top-level README.md file.
|
||||
|
||||
set -Eeuo pipefail
|
||||
|
||||
# QT_PATH is pre-set in the Qt 5 docker container environment. Includes trailing slash
|
||||
# QT_ANDROID is pre-set in the Qt 6 docker container environment
|
||||
QT_PATH=${QT_PATH:-/usr/local/Qt-5.15.13/}
|
||||
QT_ANDROID=${QT_ANDROID:-$QT_PATH}
|
||||
|
||||
export LC_ALL=C.UTF-8
|
||||
|
||||
# get_app_name returns the android app's name. This affects the default name
|
||||
# in deployment-settings.json and the generated lib.so names.
|
||||
# You can still customise the package name and the package ID in the xml
|
||||
# files after generation.
|
||||
get_app_name() {
|
||||
basename "$(pwd)"
|
||||
}
|
||||
|
||||
get_stub_soname() {
|
||||
# libRealAppName_arm64-v8a.so
|
||||
echo "lib$(get_app_name)_arm64-v8a.so"
|
||||
}
|
||||
|
||||
get_go_soname() {
|
||||
echo "libMiqtGolangApp_arm64-v8a.so"
|
||||
}
|
||||
|
||||
ndk_version() {
|
||||
ls /opt/android-sdk/ndk/ | tail -n1
|
||||
}
|
||||
|
||||
target_sdk_version() {
|
||||
ls /opt/android-sdk/platforms | tail -n1 | sed -re 's/android-//'
|
||||
}
|
||||
|
||||
build_tools_version() {
|
||||
ls /opt/android-sdk/build-tools | tail -n1
|
||||
}
|
||||
|
||||
# extra_libs returns a comma-separated list of extra libraries to include in
|
||||
# the apk package
|
||||
extra_libs() {
|
||||
if [[ -d /opt/android_openssl ]] ; then
|
||||
# Our miqt Qt5 container includes these extra .so libraries
|
||||
# However, the aqtinstall-based Qt 6 container does not use them
|
||||
echo "/opt/android_openssl/ssl_1.1/arm64-v8a/libssl_1_1.so,/opt/android_openssl/ssl_1.1/arm64-v8a/libcrypto_1_1.so"
|
||||
fi
|
||||
}
|
||||
|
||||
# generate_template_contents produces a deployment settings JSON file that is
|
||||
# understood by the androiddeployqt program.
|
||||
# Available fields are documented in the template file at:
|
||||
# @ref /usr/local/Qt-5.15.13/mkspecs/features/android/android_deployment_settings.prf
|
||||
generate_template_contents() {
|
||||
|
||||
cat <<EOF
|
||||
{
|
||||
"_description": "Generated by miqt/android-mktemplate",
|
||||
"application-binary": "$(get_app_name)",
|
||||
"architectures": {
|
||||
"arm64-v8a" : "aarch64-linux-android"
|
||||
},
|
||||
"android-extra-libs": "$(extra_libs)",
|
||||
"android-min-sdk-version": "23",
|
||||
"android-target-sdk-version": "$(target_sdk_version)",
|
||||
"ndk": "/opt/android-sdk/ndk/$(ndk_version)",
|
||||
"ndk-host": "linux-x86_64",
|
||||
"qt": "${QT_ANDROID}",
|
||||
"sdk": "/opt/android-sdk",
|
||||
"sdkBuildToolsRevision": "$(build_tools_version)",
|
||||
"stdcpp-path": "/opt/android-sdk/ndk/$(ndk_version)/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/",
|
||||
"tool-prefix": "llvm",
|
||||
"toolchain-prefix": "llvm",
|
||||
"useLLVM": true
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
# pkg_config_dependencies echoes the pkg-config packages that are needed as
|
||||
# a baseline for the detected Qt version.
|
||||
# It's not smart enough to discover other Qt packages yet.
|
||||
pkg_config_dependencies() {
|
||||
local QT_VERSION=$(detect_miqt_qt_version)
|
||||
if [[ $QT_VERSION == 'qt5' ]] ; then
|
||||
echo Qt5Widgets
|
||||
echo Qt5AndroidExtras
|
||||
|
||||
elif [[ $QT_VERSION == 'qt6' ]] ; then
|
||||
# There is no AndroidExtras in Qt 6
|
||||
echo Qt6Widgets
|
||||
|
||||
fi
|
||||
}
|
||||
|
||||
# android_stub_gen generates a .so that runs an exported function from another
|
||||
# so file. This is because Qt for Android always tries to run `main`, but Go's
|
||||
# c-shared build mode cannot export a function named `main`.
|
||||
android_stub_gen() {
|
||||
|
||||
local STUBNAME="miqt-stub-$(date +%s).cpp"
|
||||
|
||||
cat > $STUBNAME <<EOF
|
||||
#include <android/log.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef void goMainFunc_t();
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
__android_log_print(ANDROID_LOG_VERBOSE, "miqt_stub", "Starting up");
|
||||
|
||||
void* handle = dlopen("$(get_go_soname)", RTLD_LAZY);
|
||||
if (handle == NULL) {
|
||||
__android_log_print(ANDROID_LOG_VERBOSE, "miqt_stub", "miqt_stub: null handle opening so: %s", dlerror());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void* goMain = dlsym(handle, "AndroidMain");
|
||||
if (goMain == NULL) {
|
||||
__android_log_print(ANDROID_LOG_VERBOSE, "miqt_stub", "miqt_stub: null handle looking for function: %s", dlerror());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
__android_log_print(ANDROID_LOG_VERBOSE, "miqt_stub", "miqt_stub: Found target, calling");
|
||||
|
||||
// Cast to function pointer and call
|
||||
goMainFunc_t* f = (goMainFunc_t*)goMain;
|
||||
f();
|
||||
|
||||
__android_log_print(ANDROID_LOG_VERBOSE, "miqt_stub", "miqt_stub: Target function returned");
|
||||
return 0;
|
||||
}
|
||||
|
||||
EOF
|
||||
|
||||
# Compile
|
||||
# Link with Qt libraries so that androiddeployqt detects us as being the
|
||||
# main shared library
|
||||
|
||||
$CXX -shared \
|
||||
-ldl \
|
||||
-llog \
|
||||
-L${QT_ANDROID}/plugins/platforms -lplugins_platforms_qtforandroid_arm64-v8a \
|
||||
$(pkg-config --libs $(pkg_config_dependencies)) \
|
||||
${STUBNAME} \
|
||||
"-Wl,-soname,$(basename "$(get_stub_soname)")" \
|
||||
-o "android-build/libs/arm64-v8a/$(get_stub_soname)"
|
||||
|
||||
rm "${STUBNAME}"
|
||||
}
|
||||
|
||||
# require_is_main_package verifies that this is the main Go package.
|
||||
require_is_main_package() {
|
||||
if ! grep -Fq 'package main' *.go ; then
|
||||
echo "This doesn't seem to be the main package" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# patch_app_main sets up the startup go files so that the go program can be
|
||||
# built either as c-shared for Android or as a normal program for desktop OSes.
|
||||
patch_app_main() {
|
||||
|
||||
# Replace func main() with app_main()
|
||||
|
||||
for srcfile in *.go ; do
|
||||
sed -i -re 's/^func main\(\) \{/func app_main() {/' "$srcfile"
|
||||
done
|
||||
|
||||
# Add shim startup files
|
||||
|
||||
cat <<EOF > startup_android.go
|
||||
//go:build android
|
||||
// +build android
|
||||
|
||||
package main
|
||||
|
||||
import "C" // Required for export support
|
||||
|
||||
//export AndroidMain
|
||||
func AndroidMain() {
|
||||
app_main()
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Must be empty
|
||||
}
|
||||
|
||||
EOF
|
||||
|
||||
cat <<EOF > startup_other.go
|
||||
//go:build !android
|
||||
// +build !android
|
||||
|
||||
package main
|
||||
|
||||
func main() {
|
||||
app_main()
|
||||
}
|
||||
|
||||
EOF
|
||||
|
||||
gofmt -w startup_android.go || true
|
||||
gofmt -w startup_other.go || true
|
||||
|
||||
# Done
|
||||
}
|
||||
|
||||
# unpatch_app_main undoes the transformation from patch_app_main.
|
||||
unpatch_app_main() {
|
||||
|
||||
# Replace func main() with app_main()
|
||||
|
||||
for srcfile in *.go ; do
|
||||
sed -i -re 's/^func app_main\(\) \{/func main() {/' "$srcfile"
|
||||
done
|
||||
|
||||
# Remove extra startup files
|
||||
|
||||
rm startup_android.go || true
|
||||
rm startup_other.go || true
|
||||
}
|
||||
|
||||
# build_app_so compiles the Go app as a c-shared .so.
|
||||
build_app_so() {
|
||||
go build \
|
||||
-buildmode c-shared \
|
||||
-ldflags "-s -w -extldflags -Wl,-soname,$(get_go_soname)" \
|
||||
-o "android-build/libs/arm64-v8a/$(get_go_soname)"
|
||||
}
|
||||
|
||||
sdkmanager() {
|
||||
echo /opt/android-sdk/cmdline-tools/*/bin/sdkmanager
|
||||
}
|
||||
|
||||
# build_apk calls androiddeployqt to package the android-build directory into
|
||||
# the final apk.
|
||||
build_apk() {
|
||||
|
||||
# Qt 6 androiddeployqt: Understands the QT_ANDROID_KEYSTORE_STORE_PASS in env
|
||||
# Qt 5 androiddeployqt: Doesn't - any use of `--sign keystore alias` here
|
||||
# requires stdin prompt but doesn't pass androiddeployqt's stdin through
|
||||
# to jarsigner subprocess
|
||||
# Either way, don't sign the app here, rely on separate jarsigner command
|
||||
|
||||
# Work around an issue with Qt 6 sporadically failing to detect that
|
||||
# we have a valid Qt platform plugin
|
||||
# TODO why does this happen? Is it related to file sort ordering?
|
||||
# It really does fix itself after multiple attempts (usually less than 5)
|
||||
# - When it fails: Error: qmlimportscanner not found at /qmlimportscanner
|
||||
# - When it works: Error: qmlimportscanner not found at libexec/qmlimportscanner
|
||||
while ! androiddeployqt \
|
||||
--input ./deployment-settings.json \
|
||||
--output ./android-build/ \
|
||||
--release \
|
||||
2> >(tee /tmp/androiddeployqt.stderr.log >&2) ; do
|
||||
|
||||
if grep -Fq 'Make sure the app links to Qt Gui library' /tmp/androiddeployqt.stderr.log ; then
|
||||
echo "Detected temporary problem with Qt plugin detection. Retrying..."
|
||||
sleep 1
|
||||
|
||||
else
|
||||
# real error
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
local OUTAPK=$(get_app_name).apk
|
||||
rm "$OUTAPK" || true
|
||||
|
||||
# Zipalign
|
||||
echo "Zipalign..."
|
||||
/opt/android-sdk/build-tools/*/zipalign \
|
||||
-p 4 \
|
||||
./android-build/build/outputs/apk/release/android-build-release-unsigned.apk \
|
||||
"$OUTAPK"
|
||||
|
||||
# Sign
|
||||
echo "Signing..."
|
||||
#jarsigner \
|
||||
# -verbose \
|
||||
# -sigalg SHA256withRSA -digestalg SHA256 \
|
||||
# -keystore ./android.keystore \
|
||||
# "$OUTAPK" \
|
||||
# "${QT_ANDROID_KEYSTORE_ALIAS}" \
|
||||
# -storepass:env QT_ANDROID_KEYSTORE_STORE_PASS \
|
||||
# -keypass:env QT_ANDROID_KEYSTORE_KEY_PASS
|
||||
|
||||
/opt/android-sdk/build-tools/*/apksigner \
|
||||
sign \
|
||||
--ks ./android.keystore \
|
||||
--ks-key-alias "${QT_ANDROID_KEYSTORE_ALIAS}" \
|
||||
--ks-pass env:QT_ANDROID_KEYSTORE_STORE_PASS \
|
||||
--key-pass env:QT_ANDROID_KEYSTORE_KEY_PASS \
|
||||
"$OUTAPK"
|
||||
}
|
||||
|
||||
# detect_env_qt_version detects the system's current Qt version.
|
||||
detect_env_qt_version() {
|
||||
if qmake --version | fgrep -q 'Qt version 5' ; then
|
||||
echo "qt5"
|
||||
return 0
|
||||
|
||||
elif qmake --version | fgrep -q 'Qt version 6' ; then
|
||||
echo "qt6"
|
||||
return 0
|
||||
|
||||
else
|
||||
echo "Missing Qt tools in PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# detect_miqt_qt_version echoes either "qt5", "qt6", or exits bash.
|
||||
detect_miqt_qt_version() {
|
||||
local IS_QT5=false
|
||||
if grep -qF '"github.com/mappu/miqt/qt"' *.go ; then
|
||||
IS_QT5=true
|
||||
fi
|
||||
|
||||
local IS_QT6=false
|
||||
if grep -qF '"github.com/mappu/miqt/qt6"' *.go ; then
|
||||
IS_QT6=true
|
||||
fi
|
||||
|
||||
if [[ $IS_QT5 == true && $IS_QT6 == true ]] ; then
|
||||
echo "Found qt5 and qt6 imports, confused about what to do next" >&2
|
||||
exit 1
|
||||
|
||||
elif [[ $IS_QT5 == true ]] ; then
|
||||
echo "qt5"
|
||||
return 0
|
||||
|
||||
elif [[ $IS_QT6 == true ]] ; then
|
||||
echo "qt6"
|
||||
return 0
|
||||
|
||||
else
|
||||
echo "Found neither qt5 nor qt6 imports. Is this a MIQT Qt app?" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
generate_default_keystore() {
|
||||
|
||||
local GENPASS=storepass_$(cat /dev/urandom | head -c64 | md5sum | cut -d' ' -f1)
|
||||
|
||||
keytool \
|
||||
-genkeypair \
|
||||
-dname "cn=Miqt, ou=Miqt, o=Miqt, c=US" \
|
||||
-keyalg RSA \
|
||||
-alias miqt \
|
||||
-keypass "${GENPASS}" \
|
||||
-keystore ./android.keystore \
|
||||
-storepass "${GENPASS}" \
|
||||
-validity 20000
|
||||
|
||||
echo "QT_ANDROID_KEYSTORE_PATH=./android.keystore" > android.keystore.env
|
||||
echo "QT_ANDROID_KEYSTORE_ALIAS=miqt" >> android.keystore.env
|
||||
echo "QT_ANDROID_KEYSTORE_STORE_PASS=${GENPASS}" >> android.keystore.env
|
||||
echo "QT_ANDROID_KEYSTORE_KEY_PASS=${GENPASS}" >> android.keystore.env
|
||||
}
|
||||
|
||||
# main is the entrypoint for android-build.sh.
|
||||
main() {
|
||||
|
||||
if [[ $(detect_env_qt_version) != $(detect_miqt_qt_version) ]] ; then
|
||||
echo "The system is $(detect_env_qt_version) but the app uses $(detect_miqt_qt_version). Is this the right container?" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
require_is_main_package
|
||||
|
||||
# Rebuild deployment-settings.json
|
||||
if [[ ! -f deployment-settings.json ]] ; then
|
||||
echo "Generating deployment-settings.json..."
|
||||
generate_template_contents > deployment-settings.json
|
||||
fi
|
||||
|
||||
mkdir -p android-build/libs/arm64-v8a
|
||||
|
||||
if [[ ! -f android-build/libs/arm64-v8a/$(get_stub_soname) ]] ; then
|
||||
echo "Generating stub so..."
|
||||
android_stub_gen
|
||||
fi
|
||||
|
||||
# Rebuild miqt_golang_app.so
|
||||
echo "Compiling Go app..."
|
||||
patch_app_main
|
||||
build_app_so
|
||||
unpatch_app_main
|
||||
|
||||
# Keypair
|
||||
if [[ ! -f android.keystore || ! -f android.keystore.env ]] ; then
|
||||
echo "Signing keystore not found, generating a default one..."
|
||||
generate_default_keystore
|
||||
fi
|
||||
|
||||
# Load keypair credentials into exported env vars
|
||||
set -o allexport
|
||||
source android.keystore.env
|
||||
set +o allexport
|
||||
|
||||
# Generate .apk
|
||||
echo "Packaging APK..."
|
||||
build_apk
|
||||
|
||||
echo "Complete"
|
||||
}
|
||||
|
||||
main "$@"
|
@ -213,7 +213,9 @@ func getDockerRunArgsForGlob(dockerfiles []fs.DirEntry, containerNameGlob string
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fullCommand = append(fullCommand, `-v`, basedir+`:/src`, `-w`, filepath.Join(`/src`, relCwd))
|
||||
mountDir := `/src/` + filepath.Base(cwd) // Don't use /src directly, otherwise -android-build will not know the package name for top-level builds
|
||||
|
||||
fullCommand = append(fullCommand, `-v`, basedir+`:`+mountDir, `-w`, filepath.Join(mountDir, relCwd))
|
||||
|
||||
fullCommand = append(fullCommand, `-e`, `HOME=/tmp`)
|
||||
|
||||
|
@ -1,11 +1,18 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
//go:embed android-build.sh
|
||||
var embedAndroidBuildSh []byte
|
||||
|
||||
var _ embed.FS // Workaround to allow import of package `embed`
|
||||
|
||||
// evaluateTask turns the supplied process arguments into real arguments to
|
||||
// execute, handling quick command recipes as well as arbitrary execution
|
||||
func evaluateTask(taskArgs []string) (retArgs []string, fixup func(*exec.Cmd), allowTty bool, err error) {
|
||||
@ -26,6 +33,14 @@ func evaluateTask(taskArgs []string) (retArgs []string, fixup func(*exec.Cmd), a
|
||||
|
||||
//
|
||||
|
||||
stdinFrom := func(stdinBytes []byte) func(*exec.Cmd) {
|
||||
return func(c *exec.Cmd) {
|
||||
c.Stdin = bytes.NewReader(stdinBytes)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
if taskArgs[0][0] != '-' {
|
||||
// Task does not start with a hyphen = plain command
|
||||
retArgs = taskArgs
|
||||
@ -49,6 +64,13 @@ func evaluateTask(taskArgs []string) (retArgs []string, fixup func(*exec.Cmd), a
|
||||
retArgs = append(retArgs, taskArgs[1:]...)
|
||||
return
|
||||
|
||||
case `-android-build`:
|
||||
retArgs = []string{"/bin/bash", "-s"}
|
||||
retArgs = append(retArgs, taskArgs[1:]...)
|
||||
fixup = stdinFrom(embedAndroidBuildSh)
|
||||
allowTty = false
|
||||
return
|
||||
|
||||
default:
|
||||
return nil, nil, false, fmt.Errorf("Unrecognized task %q", taskArgs[0])
|
||||
}
|
||||
|
@ -4,9 +4,6 @@ RUN wget 'https://go.dev/dl/go1.23.1.linux-amd64.tar.gz' && \
|
||||
tar x -C /usr/local/ -f go1.23.1.linux-amd64.tar.gz && \
|
||||
rm go1.23.1.linux-amd64.tar.gz
|
||||
|
||||
COPY cmd/android-stub-gen/android-stub-gen.sh /usr/local/bin/android-stub-gen.sh
|
||||
COPY cmd/android-mktemplate/android-mktemplate.sh /usr/local/bin/android-mktemplate.sh
|
||||
|
||||
ENV PATH=/usr/local/go/bin:/opt/cmake/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/Qt-5.15.13/bin:/opt/android-sdk/cmdline-tools/tools/bin:/opt/android-sdk/tools:/opt/android-sdk/tools/bin:/opt/android-sdk/platform-tools
|
||||
|
||||
# The pkg-config definitions were all installed with platform-specific suffixes
|
||||
@ -14,6 +11,10 @@ ENV PATH=/usr/local/go/bin:/opt/cmake/bin:/usr/local/sbin:/usr/local/bin:/usr/sb
|
||||
# This container is targeting armv8-a, so set up simple symlinks
|
||||
RUN /bin/bash -c 'cd /usr/local/Qt-5.15.13/lib/pkgconfig ; for f in *_arm64-v8a.pc ; do cp $f "$(basename -s _arm64-v8a.pc "$f").pc"; done'
|
||||
|
||||
# This is gross but (A) it's containerized and (B) allows --uid=1000 to perform builds
|
||||
# Only needed for certain problematic versions of the Android SDK; a readonly SDK works in both older+newer SDKs
|
||||
RUN /bin/bash -c 'find /opt/android-sdk/ -type d -exec chmod 777 {} \; && find /opt/android-sdk/ -perm 660 -exec chmod 666 {} \;'
|
||||
|
||||
ENV CC=/opt/android-sdk/ndk/22.1.7171670/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android30-clang
|
||||
ENV CXX=/opt/android-sdk/ndk/22.1.7171670/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android30-clang++
|
||||
ENV CGO_ENABLED=1
|
||||
|
@ -9,9 +9,6 @@ RUN wget 'https://go.dev/dl/go1.23.6.linux-amd64.tar.gz' && \
|
||||
tar x -C /usr/local/ -f go1.23.6.linux-amd64.tar.gz && \
|
||||
rm go1.23.6.linux-amd64.tar.gz
|
||||
|
||||
COPY cmd/android-stub-gen/android-stub-gen.sh /usr/local/bin/android-stub-gen.sh
|
||||
COPY cmd/android-mktemplate/android-mktemplate.sh /usr/local/bin/android-mktemplate.sh
|
||||
|
||||
# Fix up pkg-config definitions:
|
||||
# 1. There are only pkg-config definitions included for gcc_64 (Linux native), not for the android_arm64_v8a target we actually want
|
||||
# 2. It looks for `Libs: -L${libdir} -lQt6Widgets` but the file is named libQt6Widgets_arm64-v8a.so
|
||||
|
Loading…
x
Reference in New Issue
Block a user