Files
status-app/mobile/scripts/buildApp.sh
T

181 lines
7.5 KiB
Bash
Executable File

#!/usr/bin/env bash
set -eo pipefail
CWD=$(realpath "$(dirname "$0")")
REPO_ROOT=$(realpath "$CWD/../..")
ARCH=${ARCH:-amd64}
SDK=${SDK:-iphonesimulator}
BUILD_DIR=${BUILD_DIR:-"$CWD/../build"}
GRADLE_TARGETS=${GRADLE_TARGETS:-"assembleRelease"}
BUILD_VARIANT=${BUILD_VARIANT:-"release"}
FLAG_KEYCARD_ENABLED=${FLAG_KEYCARD_ENABLED:-1}
QMAKE_BIN="${QMAKE:-qmake}"
QMAKE_CONFIG=("CONFIG+=device" "CONFIG+=release" ${QMAKE_EXTRA_CONFIG:+CONFIG+=$QMAKE_EXTRA_CONFIG})
# Derive names from variant: pr -> StatusPR, release -> Status
OUTPUT_NAME="Status"
[[ "$BUILD_VARIANT" == "pr" ]] && OUTPUT_NAME="StatusPR"
echo "Building $OUTPUT_NAME for ${OS}, variant: ${BUILD_VARIANT}"
mkdir -p "${BUILD_DIR}"
cd "${BUILD_DIR}"
STATUS_DESKTOP=${STATUS_DESKTOP:-"../vendors/status-desktop"}
VERSION=$(cd "$STATUS_DESKTOP" && git describe --tags --always | cut -d- -f1 | cut -d. -f1-3 | sed 's/^v//')
BUILD_VERSION="${CHANGE_ID:+${CHANGE_ID}.}$(($(date +%s) / 60))"
echo "Version: $VERSION, build: $BUILD_VERSION"
# Configure qmake with keycard flag
QMAKE_DEFINES=()
if [[ "${FLAG_KEYCARD_ENABLED}" == "1" ]]; then
QMAKE_DEFINES=("DEFINES+=FLAG_KEYCARD_ENABLED")
fi
if [[ "${OS}" == "android" ]]; then
[[ -z "${JAVA_HOME}" ]] && { echo "JAVA_HOME is not set"; exit 1; }
STATUSQ_DIR=${STATUSQ:-"${STATUS_DESKTOP}/ui/StatusQ"}
MOBILEWEBVIEW_JAVA_DIR_FILE="${STATUSQ_DIR}/build/${OS}/StatusQ/mobilewebview_java_dir.txt"
if [[ -z "${MOBILEWEBVIEW_ANDROID_JAVA_SRC}" && -f "${MOBILEWEBVIEW_JAVA_DIR_FILE}" ]]; then
MOBILEWEBVIEW_ANDROID_JAVA_SRC="$(<"${MOBILEWEBVIEW_JAVA_DIR_FILE}")"
fi
# Export BUILD_VARIANT and BUNDLE_IDENTIFIER for build.gradle to pick up
export BUILD_VARIANT
export BUNDLE_IDENTIFIER
if [[ "$GRADLE_TARGETS" == *"Fdroid"* ]]; then
# shellcheck source=../../fdroid/generate-keystore.sh
source "$REPO_ROOT/fdroid/generate-keystore.sh" "$REPO_ROOT/status-fdroid.keystore"
fi
"$QMAKE_BIN" "$CWD/../wrapperApp/Status.pro" "${QMAKE_CONFIG[@]}" -spec android-clang \
ANDROID_ABIS="${ANDROID_ABI:-arm64-v8a}" VERSION="$VERSION" "${QMAKE_DEFINES[@]}" -after
make -j"$(nproc)" apk_install_target
androiddeployqt \
--input "$BUILD_DIR/android-${OUTPUT_NAME}-deployment-settings.json" \
--output "$BUILD_DIR/android-build" \
--android-platform android-35 \
--verbose --aux-mode
# Package service-only libs into the APK without adding them to Qt's
# bundled_libs auto-load list. Qt has no qmake variable for "package only",
# so we drop the libs into android-build/libs/<abi>/ directly after
# androiddeployqt (gradle's jniLibs.srcDirs=['libs'] picks them up).
# These are loaded by the :statusgo service via System.loadLibrary("status_service")
# and must NOT be dlopen'd in the UI process (see mobile/wrapperApp/Status.pro).
# cp -f overwrites any stale copy androiddeployqt may have left from a prior
# build when these libs were still in ANDROID_EXTRA_LIBS.
for lib in libstatus.so libstatus_service.so libsds.so; do
cp -f "$CWD/../lib/android/qt${QT_MAJOR}/$lib" "$BUILD_DIR/android-build/libs/arm64-v8a/$lib"
done
# Copy custom Android files, preserve Qt-generated libs.xml
cp "$CWD/../android/qt${QT_MAJOR}"/{AndroidManifest.xml,build.gradle,settings.gradle,gradle.properties} "$BUILD_DIR/android-build/"
rsync -a --exclude='libs.xml' "$CWD/../android/qt${QT_MAJOR}/res/" "$BUILD_DIR/android-build/res/" 2>/dev/null || true
rsync -a "$CWD/../android/qt${QT_MAJOR}/src/" "$BUILD_DIR/android-build/src/" 2>/dev/null || true
rsync -a "$CWD/../android/qt${QT_MAJOR}/aidl/" "$BUILD_DIR/android-build/aidl/" 2>/dev/null || true
if [[ -n "${MOBILEWEBVIEW_ANDROID_JAVA_SRC}" && \
-f "${MOBILEWEBVIEW_ANDROID_JAVA_SRC}/org/mobilewebview/MobileWebView.java" ]]; then
echo "Including MobileWebView Java sources from: ${MOBILEWEBVIEW_ANDROID_JAVA_SRC}"
rsync -a "${MOBILEWEBVIEW_ANDROID_JAVA_SRC}/org/" "$BUILD_DIR/android-build/src/org/"
fi
cd "$BUILD_DIR/android-build"
BIN_DIR=${BIN_DIR:-"$CWD/../bin/android/qt6"}
mkdir -p "$BIN_DIR"
# Determine build type from GRADLE_TARGETS
if [[ "$GRADLE_TARGETS" == *"Profile"* ]]; then
BUILD_TYPE="profile"
elif [[ "$GRADLE_TARGETS" == *"Debug"* ]]; then
BUILD_TYPE="debug"
elif [[ "$GRADLE_TARGETS" == *"Fdroid"* ]]; then
BUILD_TYPE="fdroid"
else
BUILD_TYPE="release"
fi
# Gradle output paths (may be signed or unsigned depending on environment)
APK_DIR="build/outputs/apk/${BUILD_TYPE}"
export APK_OUT="${APK_DIR}/android-build-${BUILD_TYPE}.apk"
export APK_OUT_UNSIGNED="${APK_DIR}/android-build-${BUILD_TYPE}-unsigned.apk"
AAB_OUT="build/outputs/bundle/${BUILD_TYPE}/android-build-${BUILD_TYPE}.aab"
# Build with specified gradle targets
# shellcheck disable=SC2086 # intentional word splitting for multiple gradle tasks
$("$QMAKE_BIN" -query QT_INSTALL_PREFIX)/src/3rdparty/gradle/gradlew ${GRADLE_TARGETS} --no-daemon --console=plain
echo "APK outputs:"
find build/outputs/apk -name '*.apk' 2>/dev/null || echo "No APKs found"
# If Gradle produced an unsigned APK (e.g. fdroid build where signing configs
# are stripped by fdroid's remove_signing_keys), sign it via the dedicated script.
if [[ ! -f "$APK_OUT" && -f "$APK_OUT_UNSIGNED" && -n "${FDROID_STORE_FILE:-}" ]]; then
echo "Signing unsigned APK..."
"$REPO_ROOT/fdroid/sign-apk.sh"
fi
# Copy whichever artifacts were built
BUILT=""
if [[ -f "$APK_OUT" ]]; then
cp "$APK_OUT" "$BIN_DIR/${OUTPUT_NAME}.apk"
BUILT="$BIN_DIR/${OUTPUT_NAME}.apk"
fi
if [[ -f "$AAB_OUT" ]]; then
cp "$AAB_OUT" "$BIN_DIR/${OUTPUT_NAME}.aab"
BUILT="$BUILT $BIN_DIR/${OUTPUT_NAME}.aab"
fi
[[ -z "$BUILT" ]] && { echo "Error: No artifacts produced"; exit 1; }
echo "Build succeeded:$BUILT"
else
# Generate Info.plist based on FLAG_KEYCARD_ENABLED
echo "Generating Info.plist (FLAG_KEYCARD_ENABLED=${FLAG_KEYCARD_ENABLED})..."
if [[ "${FLAG_KEYCARD_ENABLED}" == "1" ]]; then
# Enable NFC/Keycard support - uncomment NFC sections
# Markers may be indented; match by substring (not anchors).
sed -e '/KEYCARD_NFC_START/d' \
-e '/KEYCARD_NFC_END/d' \
"$CWD/../ios/Info.plist.template" > "$BUILD_DIR/Info.plist"
else
# Disable NFC/Keycard support - remove NFC sections entirely
# Markers may be indented; match by substring (not anchors).
sed '/KEYCARD_NFC_START/,/KEYCARD_NFC_END/d' \
"$CWD/../ios/Info.plist.template" > "$BUILD_DIR/Info.plist"
fi
XCODE_FLAGS=(-configuration Release -sdk "$SDK" -arch "$ARCH" CURRENT_PROJECT_VERSION="$BUILD_VERSION")
if [[ "${QMAKE_EXTRA_CONFIG:-}" == "fastlane" ]]; then
# CI: disable signing; fastlane handles it after the build.
XCODE_FLAGS+=(CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO)
else
# Local: allow xcodebuild to auto-download provisioning profiles.
XCODE_FLAGS+=(-allowProvisioningUpdates)
fi
BIN_DIR=${BIN_DIR:-"$CWD/../bin/ios"}
mkdir -p "$BIN_DIR"
"$QMAKE_BIN" "$CWD/../wrapperApp/Status.pro" "${QMAKE_CONFIG[@]}" -spec macx-ios-clang CONFIG+="$SDK" VERSION="$VERSION" "${QMAKE_DEFINES[@]}" -after
# Remove stale symlink from previous install that prevents xcodebuild mkdir
rm -f "${BUILD_DIR}/Release-${SDK}/${OUTPUT_NAME}.app"
xcodebuild "${XCODE_FLAGS[@]}" -target "Qt Preprocess" | xcbeautify
xcodebuild "${XCODE_FLAGS[@]}" -target "$OUTPUT_NAME" install DSTROOT="$BIN_DIR" INSTALL_PATH="/" TARGET_BUILD_DIR="$BIN_DIR" | xcbeautify
[[ ! -e "$BIN_DIR/${OUTPUT_NAME}.app/Info.plist" ]] && { echo "Build failed"; exit 1; }
echo "Build succeeded: $BIN_DIR/${OUTPUT_NAME}.app"
fi