quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

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:
MREADME.md | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Mcross/build-android.sh | 8++++----
Mcross/build-ios.sh | 16+++++++++-------
Across/package-android.sh | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcross/package-ios.sh | 208+++++++++++++++++++++++++++++++++++++++----------------------------------------
Mdocker-android/build.sh | 8++++----
Axcode/module.modulemap | 4++++
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 * +}