commit f573fbd1da9ba508b269a906c3962090ad514c8d
parent e5eb8195053da0f3a564f46357430525185c0579
Author: Iván Ávalos <avalos@disroot.org>
Date: Fri, 22 Aug 2025 11:22:07 +0200
improved Android and iOS build scripts
Diffstat:
7 files changed, 277 insertions(+), 125 deletions(-)
diff --git a/README.md b/README.md
@@ -10,19 +10,110 @@ Prerequisite dependencies:
- `meson`
- `ninja`
- `gcc` or `clang`
+- `git`
-Building also requires the `taler-wallet-core-qjs.mjs` file. You can
-either build it yourself or download if from `taler.net` via the `./download_wallet_core_js.sh`
-script.
+Building also requires the `taler-wallet-core-qjs.mjs` file to be
+present in the top-level of this repository. You can build this file
+from the `taler-typescript-core.git` repository by running `make
+embedded` once the project is configured; the resulting file may then
+be found in `packages/taler-wallet-embedded/dist/` and should be
+copied into this directory.
+
+If this repository was cloned using Git without the `--recursive`
+flag, make sure to check-out all the required submodules recursively:
+
+```sh
+git submodule update --init --force --recursive
+```
The following commands build the project and place resulting files
in the `build/` directory:
+```sh
+meson setup build
+meson compile -C build
+```
+
+## Cross-compiling
+
+### Android
+
+#### Publish to local Maven repository for testing
+
+In order to test locally, you can use the `./cross/package-android.sh`
+script and pass the desired architecture, as well as specify whether
+the Gradle package should be published locally or not.
+
+```sh
+./cross/package-android.sh all # build for all architectures
+./cross/package-android.sh x86 # build only for x86
+./cross/package-android.sh x86_64 # build only for x86_64
+./cross/package-android.sh arm64 # build only for arm64
+./cross/package-android.sh gradle # only publish to local Gradle
+```
+
+In order to test the Taler wallet against this local build, add the
+following line to the project-level `build.gradle` file:
+
+```groovy
+// taler-android.git/build.gradle
+allprojects {
+ repositories {
+ mavenLocal()
+ // ...
+ }
+}
+```
+
+_**NOTE:** a distinctive suffix should be added to the `VERSION_NAME`
+in `Quickjs-android/gradle.properties` **before** building, and
+referenced in `wallet/build.gradle` in order to prevent Gradle from
+fetching the dependency from Maven Central._
+
+```properties
+# quickjs-tart.git/QuickJS-android/gradle.properties
+VERSION_NAME=1.0.28-local
+```
+
+```groovy
+// taler-android.git/wallet/build.gradle
+def qtart_version = "1.0.28-local"
+```
+
+#### Publish to Maven central
+
+See `docker-android/README.md`
+
+### iOS
+
```
-$ meson setup build
-$ meson compile -C build
+./cross/package-ios.sh
```
+This script will generate a `.xcframework` file under the `build-ios/`
+directory for each the required dynamic libraries, which should be
+copied to the Taler iOS Xcode project under the `Frameworks/`
+directory and added to all wallet targets (e.g. `GNU Taler`, `Taler
+Wallet`, `Taler Nightly`).
+
+In order to build only for certain platforms, you can edit the
+`cross/package-ios.sh` directory and comment out the platforms that
+you don't want, for instance:
+
+```bash
+targets=(
+ iphoneos-arm64
+ iphonesimulator-arm64
+ iphonesimulator-x86_64
+ # macosx-arm64
+ # macosx-x86_64
+)
+```
+
+_**NOTE:** you cannot pick individual architectures for a given
+platform, you must comment out all architectures for the platform that
+you don't want to build for._
+
## Architecture
Infra:
diff --git a/cross/build-android.sh b/cross/build-android.sh
@@ -11,7 +11,7 @@ ABI=$1
case $ABI in
armeabi-v7a)
ARCH="arm"
- BUILD_DIR="build-android-armeabi-v7a"
+ BUILD_DIR="build-android/armeabi-v7a"
CPU_FAMILY=arm
CPU=armv7
CLANG_NAME=armv7a-linux-androideabi24
@@ -19,7 +19,7 @@ armeabi-v7a)
;;
arm64-v8a)
ARCH="arm64"
- BUILD_DIR="build-android-arm64-v8a"
+ BUILD_DIR="build-android/arm64-v8a"
CPU_FAMILY=aarch64
CPU=armv8
CLANG_NAME=aarch64-linux-android24
@@ -27,7 +27,7 @@ arm64-v8a)
;;
x86)
ARCH="x86"
- BUILD_DIR="build-android-x86"
+ BUILD_DIR="build-android/x86"
CPU_FAMILY=x86
CPU=x86
CLANG_NAME=i686-linux-android24
@@ -35,7 +35,7 @@ x86)
;;
x86_64)
ARCH="x86_64"
- BUILD_DIR="build-android-x86_64"
+ BUILD_DIR="build-android/x86_64"
CPU_FAMILY=x86_64
CPU=x86_64
CLANG_NAME=x86_64-linux-android24
diff --git a/cross/build-ios.sh b/cross/build-ios.sh
@@ -5,6 +5,7 @@ if [ -z ${2+x} ]; then
echo "usage: $0 <SDK> <ABI>"
echo "example: $0 iphoneos arm64"
echo "example: $0 iphonesimulator arm64"
+ echo "example: $0 m arm64"
exit 1
fi
@@ -43,12 +44,12 @@ iphonesimulator)
SDK_NAME="iPhoneSimulator"
SYSTEM='ios'
;;
-# macosx)
-# MIN_OS_VERSION=${MIN_SDK_VERSION:-11.0}
-# TARGET_TRIPLE=$ARCH-macosx${MIN_OS_VERSION}
-# SDK_NAME="MacOSX"
-# SYSTEM='darwin'
-# ;;
+macosx)
+ MIN_OS_VERSION=${MIN_SDK_VERSION:-11.0}
+ TARGET_TRIPLE=$ARCH-macosx${MIN_OS_VERSION}
+ SDK_NAME="MacOSX"
+ SYSTEM='darwin'
+ ;;
*)
echo unknown SDK
exit 1
@@ -98,7 +99,8 @@ system = '$SYSTEM'
CMAKE_OSX_SYSROOT='${SDK}'
EOF
-BUILD_DIR=build-${SDK}-${ARCH}
+BUILD_DIR=build-ios/${SDK}-${ARCH}
+mkdir -p "${BUILD_DIR}"
meson setup --errorlogs \
-Doptimization=3 \
diff --git a/cross/package-android.sh b/cross/package-android.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+set -e
+
+if [[ $# -ne 1 ]]; then
+ echo "Usage: $0 [x86|x86_64|arm64|armeabi]"
+ echo "Usage: $0 all"
+ echo "Usage: $0 gradle"
+ exit 1
+fi
+
+ANDROID_DIR=./QuickJS-android
+NDK_VERSION=27.1.12297006
+
+if [[ "$OSTYPE" == "linux-gnu"* ]]; then
+ export ANDROID_HOME=~/Android/Sdk
+ export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin
+ export PATH=$PATH:$ANDROID_HOME/ndk/$NDK_VERSION/toolchains/llvm/prebuilt/linux-x86_64/bin
+elif [[ "$OSTYPE" == "darwin"* ]]; then
+ export ANDROID_HOME=~/Library/Android/sdk
+ export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin
+ export PATH=$PATH:$ANDROID_HOME/ndk/$NDK_VERSION/toolchains/llvm/prebuilt/darwin-x86_64/bin/
+fi
+
+export ANDROID_SDK_ROOT=$ANDROID_HOME
+
+# Install NDK version if it doesn't exist
+if [ ! -d "$ANDROID_SDK_ROOT/ndk/$NDK_VERSION" ]; then
+ sdkmanager "ndk;$NDK_VERSION"
+fi
+
+JNILIBS_DIR=$ANDROID_DIR/qtart/src/main/jniLibs
+
+if [ "$1" = "all" ] || [ "$1" = "x86" ]; then
+ ./cross/build-android.sh x86
+ cp ./build-android/x86/libtalerwalletcore.so $JNILIBS_DIR/x86
+fi
+
+if [ "$1" = "all" ] || [ "$1" = "x86_64" ]; then
+ ./cross/build-android.sh x86_64
+ cp ./build-android/x86_64/libtalerwalletcore.so $JNILIBS_DIR/x86_64
+fi
+
+if [ "$1" = "all" ] || [ "$1" = "arm64" ]; then
+ ./cross/build-android.sh arm64-v8a
+ cp ./build-android/arm64-v8a/libtalerwalletcore.so $JNILIBS_DIR/arm64-v8a
+fi
+
+if [ "$1" = "all" ] || [ "$1" = "armeabi" ]; then
+ ./cross/build-android.sh armeabi-v7a
+ cp ./build-android/armeabi-v7a/libtalerwalletcore.so $JNILIBS_DIR/armeabi-v7a
+fi
+
+pushd $ANDROID_DIR
+./gradlew publishToMavenLocal
+popd
+
+tput bel
diff --git a/cross/package-ios.sh b/cross/package-ios.sh
@@ -1,128 +1,126 @@
#!/bin/bash
-set -e
-trap 'kill -SIGTERM 0' EXIT
+set -eE
+shopt -s nullglob
-# Inspiration: https://github.com/stasel/WebRTC/blob/latest/scripts/build.sh
+handle_error() {
+ echo "$(tput bold)(!) An error has ocurred, please check the log files for more information.$(tput sgr0)"
+ exit -1
+}
-platforms=(
- ios
- macos
-)
+trap handle_error ERR
+
+# Inspiration: https://github.com/stasel/WebRTC/blob/latest/scripts/build.sh
targets=(
iphoneos-arm64
iphonesimulator-arm64
iphonesimulator-x86_64
- macosx-arm64
- macosx-x86_64
+ # macosx-arm64
+ # macosx-x86_64
)
+
libraries=(
libtalerwalletcore.dylib
subprojects/c-ares/libc_ares.dylib
)
-PLISTBUDDY_EXEC="/usr/libexec/PlistBuddy"
-
-plist_add_library() {
- local plist=$1
- local index=$2
- local identifier=$3
- local library=$4
- local platform=$5
- local platform_variant=$6
- "$PLISTBUDDY_EXEC" -c "Add :AvailableLibraries: dict" "${plist}"
- "$PLISTBUDDY_EXEC" -c "Add :AvailableLibraries:${index}:LibraryIdentifier string ${identifier}" "${plist}"
- "$PLISTBUDDY_EXEC" -c "Add :AvailableLibraries:${index}:LibraryPath string ${library}" "${plist}"
- "$PLISTBUDDY_EXEC" -c "Add :AvailableLibraries:${index}:SupportedArchitectures array" "${plist}"
- "$PLISTBUDDY_EXEC" -c "Add :AvailableLibraries:${index}:SupportedPlatform string ${platform}" "${plist}"
- if [ ! -z "$platform_variant" ]; then
- "$PLISTBUDDY_EXEC" -c "Add :AvailableLibraries:${index}:SupportedPlatformVariant string ${platform_variant}" "${plist}"
- fi
-}
-
-plist_add_architecture() {
- local plist=$1
- local index=$2
- local arch=$3
- "$PLISTBUDDY_EXEC" -c "Add :AvailableLibraries:${index}:SupportedArchitectures: string ${arch}" "${plist}"
-}
-
-contains_element () {
+contains_element() {
local e match="$1"
shift
for e; do [[ "$e" == "$match" ]] && return 0; done
return 1
}
-# Build all targets
+base_build_folder="build-ios"
build_folders=()
-for target in "${targets[@]}"; do
- sdk="${target%-*}"
- arch="${target#*-}"
- build_folder=build-$sdk-$arch
- build_folders+=("${build_folder}")
- log_file="${build_folder}/package-ios.log"
- echo [$sdk $arch] Compilation logs written to $log_file
- # build all in parallel for improved speed!
- ./cross/build-ios.sh $sdk $arch > "$log_file" 2>&1 "$log_file" &
-done
-
-wait
-
-# Package libraries into .xcframework
-for library in "${libraries[@]}"; do
- xcodebuild_flags=()
- for folder in "${build_folders[@]}"; do
- xcodebuild_flags+=(-library "${folder}/${library}")
+# Build all targets
+build_targets() {
+ mkdir -p "${base_build_folder}"
+
+ for target in "${targets[@]}"; do
+ sdk="${target%-*}"
+ arch="${target#*-}"
+ build_folder="${base_build_folder}/${sdk}-${arch}"
+ build_folders+=("${build_folder}")
+ log_file="${base_build_folder}/package-ios-${sdk}-${arch}.log"
+ echo "$(tput bold)(!) Now building for $sdk $arch... (logs written to ${log_file})$(tput sgr0)"
+ ./cross/build-ios.sh $sdk $arch &> "${log_file}"
+ build_pids+=("$!")
done
- library_="${library##*/}"
- basename="${library_%.dylib}"
-
- xcframework_dir="${basename}.xcframework"
- info_plist="${xcframework_dir}/Info.plist"
- rm -rf "${xcframework_dir}"
- mkdir "${xcframework_dir}"
- "$PLISTBUDDY_EXEC" -c "Add :CFBundlePackageType string XFWK" "${info_plist}"
- "$PLISTBUDDY_EXEC" -c "Add :XCFrameworkFormatVersion string 1.0" "${info_plist}"
- "$PLISTBUDDY_EXEC" -c "Add :AvailableLibraries array" "${info_plist}"
-
- index=0
-
- if contains_element "build-iphoneos-arm64" "${build_folders[@]}"; then
- lib_identifier="ios-arm64"
- mkdir "${xcframework_dir}/${lib_identifier}"
- plist_add_library "${info_plist}" "${index}" "${lib_identifier}" "${library_}" "ios"
- plist_add_architecture "${info_plist}" "${index}" arm64
- cp -r "build-iphoneos-arm64/${library}" "${xcframework_dir}/${lib_identifier}/"
- index=$((index+1))
- fi
-
- if contains_element "build-iphonesimulator-arm64" "${build_folders[@]}" &&
- contains_element "build-iphonesimulator-x86_64" "${build_folders[@]}"; then
- lib_identifier="ios-x86_64_arm64-simulator"
- mkdir "${xcframework_dir}/${lib_identifier}"
- plist_add_library "${info_plist}" "${index}" "${lib_identifier}" "${library_}" "ios" "simulator"
- plist_add_architecture "${info_plist}" "${index}" arm64
- plist_add_architecture "${info_plist}" "${index}" x86_64
- lipo "build-iphonesimulator-x86_64/${library}" \
- "build-iphonesimulator-arm64/${library}" \
- -output "${xcframework_dir}/${lib_identifier}/${library_}" \
- -create
- index=$((index+1))
- fi
-
- if contains_element "build-macosx-arm64" "${build_folders[@]}" &&
- contains_element "build-macosx-x86_64" "${build_folders[@]}"; then
- lib_identifier="macos-x86_64_arm64"
- mkdir "${xcframework_dir}/${lib_identifier}"
- plist_add_library "${info_plist}" "${index}" "${lib_identifier}" "${library_}" "macos"
- plist_add_architecture "${info_plist}" "${index}" arm64
- plist_add_architecture "${info_plist}" "${index}" x86_64
- lipo "build-macosx-x86_64/${library}" \
- "build-macosx-arm64/${library}" \
- -output "${xcframework_dir}/${lib_identifier}/${library_}" \
- -create
- index=$((index+1))
- fi
-done
+}
+
+include_dir="${base_build_folder}/include"
+
+# Copy headers
+copy_headers() {
+ [ -d "${include_dir}" ] && rm -r "${include_dir}"
+ mkdir -p "${include_dir}"
+ mkdir -p "${include_dir}/quickjs"
+ cp -r "taler_wallet_core_lib.h" "${include_dir}"
+ cp -r "quickjs/quickjs.h" "${include_dir}/quickjs"
+ cp -r "quickjs/quickjs-http.h" "${include_dir}/quickjs"
+ cp -r xcode/*.h "${include_dir}"
+ cp -r "xcode/module.modulemap" "${include_dir}"
+}
+
+# Package all libraries into .xcframework
+package_frameworks() {
+ for library in "${libraries[@]}"; do
+ library_name="$(basename "${library%.*}")"
+ echo "$(tput bold)(!) Now generating ${library_name}.xcframework...$(tput sgr0)"
+
+ xcodebuild_flags=()
+ xcframework_dir="${base_build_folder}/${library_name}.xcframework"
+ rm -rf "${xcframework_dir}"
+
+ # only add headers to main libtalerwalletcore framework
+ headers_flag=()
+ if [[ "${library_name}" = "libtalerwalletcore" ]]; then
+ headers_flag+=(-headers "${include_dir}")
+ fi
+
+ # iphoneos
+ if contains_element "iphoneos-arm64" "${targets[@]}"; then
+ xcodebuild_flags+=(
+ -library "${base_build_folder}/iphoneos-arm64/${library}"
+ "${headers_flag[@]}")
+ fi
+
+ # iphonesimulator
+ if contains_element "iphonesimulator-x86_64" "${targets[@]}" &&
+ contains_element "iphonesimulator-arm64" "${targets[@]}"; then
+ universal_output="${base_build_folder}/iphonesimulator-universal"
+ mkdir -p "${universal_output}"
+ lipo "${base_build_folder}/iphonesimulator-x86_64/${library}" \
+ "${base_build_folder}/iphonesimulator-arm64/${library}" \
+ -output "${universal_output}/${library_name}.dylib" -create
+ xcodebuild_flags+=(
+ -library "${universal_output}/${library_name}.dylib"
+ "${headers_flag[@]}")
+ fi
+
+ # macosx
+ if contains_element "macosx-x86_64" "${targets[@]}" &&
+ contains_element "macosx-arm64" "${targets[@]}"; then
+ universal_output="${base_build_dir}/macosx-universal"
+ mkdir -p "${universal_output}"
+ lipo "${base_build_folder}/macosx-x86_64/${library}" \
+ "${base_build_folder}/macosx-arm64/${library}" \
+ -output "${universal_output}/${library_name}.dylib" -create
+ xcodebuild_flags+=(
+ -library "${universal_output}/${library_name}.dylib"
+ "${headers_flag[@]}")
+ fi
+
+ xcodebuild -create-xcframework \
+ "${xcodebuild_flags[@]}" \
+ -output "${xcframework_dir}"
+
+ echo "$(tput bold)(!) File ${xcframework_dir} has been generated successfully!$(tput sgr0)"
+ done
+}
+
+build_targets
+copy_headers
+package_frameworks
diff --git a/docker-android/build.sh b/docker-android/build.sh
@@ -47,10 +47,10 @@ rm -rf taler-typescript-core/
ANDROID_DIR=./QuickJS-android
JNILIBS_DIR=$ANDROID_DIR/qtart/src/main/jniLibs
-cp ./build-android-x86/libtalerwalletcore.so $JNILIBS_DIR/x86
-cp ./build-android-x86_64/libtalerwalletcore.so $JNILIBS_DIR/x86_64
-cp ./build-android-arm64-v8a/libtalerwalletcore.so $JNILIBS_DIR/arm64-v8a
-cp ./build-android-armeabi-v7a/libtalerwalletcore.so $JNILIBS_DIR/armeabi-v7a
+cp ./build-android/x86/libtalerwalletcore.so $JNILIBS_DIR/x86
+cp ./build-android/x86_64/libtalerwalletcore.so $JNILIBS_DIR/x86_64
+cp ./build-android/arm64-v8a/libtalerwalletcore.so $JNILIBS_DIR/arm64-v8a
+cp ./build-android/armeabi-v7a/libtalerwalletcore.so $JNILIBS_DIR/armeabi-v7a
cd $ANDROID_DIR
# Build or publish .aar library
diff --git a/xcode/module.modulemap b/xcode/module.modulemap
@@ -0,0 +1,4 @@
+module FTalerWalletcore {
+ header "FTalerWalletcore.h"
+ export *
+}