diff --git a/.github/ISSUE_TEMPLATE/release.md b/.github/ISSUE_TEMPLATE/release.md index 3635c7b..c00ce2b 100644 --- a/.github/ISSUE_TEMPLATE/release.md +++ b/.github/ISSUE_TEMPLATE/release.md @@ -30,15 +30,26 @@ just pod-install just run-ios ``` -- [ ] Create the tag -- [ ] Build the tarball -- [ ] Sign the artifact -- [ ] Create the release on GitHub -- [ ] Let people know! +- [ ] Bump the version in `package.json` and merge it +- [ ] Create and push the signed tag on the commit with the bumped version. + Pushing the tag does not publish anything ```shell git tag v1.1.0 --sign --edit git push upstream v1.1.0 ``` +- [ ] Rehearse the release: run the Release workflow from the tag without + `publish`. It builds everything and runs `npm publish --dry-run` +- [ ] Publish: run the Release workflow from the tag with `publish` checked. It + publishes to npm and creates the GitHub release with the same tarball attached + +```shell +gh workflow run release.yml --repo bitcoindevkit/bdk-rn --ref v1.1.0 # rehearse +gh workflow run release.yml --repo bitcoindevkit/bdk-rn --ref v1.1.0 --field publish=true # publish +``` + +- [ ] Check the workflow succeeded and `npm view bdk-rn dist-tags` shows the new version +- [ ] Let people know! + - [ ] Bump the `next` version on `master` diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..910d977 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,369 @@ +name: Release + +# Builds the native libraries, packs them into the npm tarball, and publishes it. +# The package ships its prebuilt binaries: consumers need neither a Rust +# toolchain nor an install script. +# +# build-android ─┐ +# ├─ publish (npm) ── github-release +# build-ios ─────┘ +# +# The two build jobs need different hosts (the xcframework needs macOS, the +# Android libraries need the NDK). The publish job has no Rust toolchain and no +# ubrn: everything native arrives as an artifact, and it only assembles, checks +# and publishes. +# +# Releases are started by hand. Run the workflow from the release tag. +# +# Running from the tag, rather than passing the tag as an input, makes the run's +# ref and commit the tag's, which is what npm provenance and the GitHub +# attestation record. +# +# Without `publish`, the run does everything except the publish itself +# (`npm publish --dry-run`). That is how to rehearse a release, on the tag or on +# a branch. Publishing is refused unless the run is on a tag. +# +# npm publishing uses trusted publishing (OIDC). This repository and workflow +# must be registered as a trusted publisher for bdk-rn on npmjs.com, and no npm +# token is stored. Provenance is attached to every publish. + +on: + workflow_dispatch: + inputs: + publish: + description: "Publish to npm and create the GitHub release (requires running from a tag)" + type: boolean + default: false + +permissions: {} + +concurrency: + group: release-${{ github.ref }} + cancel-in-progress: false + +env: + # Same NDK as test-android.yaml and tests/android/build.gradle. + NDK_VERSION: "27.1.12297006" + +jobs: + check-version: + name: "Check version" + runs-on: ubuntu-24.04 + outputs: + version: ${{ steps.version.outputs.version }} + dist-tag: ${{ steps.version.outputs.dist-tag }} + publish: ${{ steps.version.outputs.publish }} + steps: + - name: "Checkout" + uses: actions/checkout@v5 + with: + persist-credentials: false + + - name: "Read the version and check it against the tag" + id: version + env: + PUBLISH: ${{ inputs.publish }} + run: | + version="$(node --print "require('./package.json').version")" + if [ "${GITHUB_REF_TYPE}" = "tag" ]; then + if [ "${GITHUB_REF_NAME}" != "v${version}" ]; then + echo "::error::Tag ${GITHUB_REF_NAME} does not match package.json version ${version}." + exit 1 + fi + elif [ "${PUBLISH}" = "true" ]; then + echo "::error::Publishing requires running the workflow from a release tag, not the ${GITHUB_REF_NAME} branch." + exit 1 + fi + # A prerelease must not take over `latest`, which is what a plain + # `npm install bdk-rn` resolves to. + case "${version}" in + *-*) dist_tag="next" ;; + *) dist_tag="latest" ;; + esac + echo "version=${version}" >> "${GITHUB_OUTPUT}" + echo "dist-tag=${dist_tag}" >> "${GITHUB_OUTPUT}" + echo "publish=${PUBLISH}" >> "${GITHUB_OUTPUT}" + if [ "${PUBLISH}" = "true" ]; then + echo "Publishing ${version} under the '${dist_tag}' dist-tag." + else + echo "Rehearsing ${version} under the '${dist_tag}' dist-tag (dry run)." + fi + + build-android: + name: "Build Android libraries" + needs: check-version + runs-on: ubuntu-24.04 + timeout-minutes: 90 + steps: + - name: "Checkout" + uses: actions/checkout@v5 + with: + submodules: true + persist-credentials: false + + # Two release builds of bdk-ffi leave a large target directory. + - name: "Free disk space" + run: sudo rm -rf /usr/share/dotnet /opt/ghc /usr/local/.ghcup /opt/hostedtoolcache/CodeQL + + - name: "Set up Android NDK" + run: | + yes | "${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager" --licenses > /dev/null + "${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager" --install "ndk;${NDK_VERSION}" > /dev/null + echo "ANDROID_NDK_HOME=${ANDROID_HOME}/ndk/${NDK_VERSION}" >> "${GITHUB_ENV}" + echo "ANDROID_NDK_ROOT=${ANDROID_HOME}/ndk/${NDK_VERSION}" >> "${GITHUB_ENV}" + + - name: "Set up just" + uses: extractions/setup-just@v3 + + - name: "Set up pnpm" + uses: pnpm/action-setup@v5 + + # No dependency cache in this workflow: its output is what gets published. + - name: "Set up Node" + uses: actions/setup-node@v5 + with: + node-version-file: .nvmrc + + - name: "Install dependencies" + run: pnpm install --frozen-lockfile --ignore-scripts + + - name: "Apply the bdk-ffi async-sync patches" + run: just submodule-apply-patch + + # bdk-ffi pins its toolchain in rust-toolchain.toml, and cargo runs inside + # that directory, so the targets have to be added to that toolchain. + - name: "Set up Rust" + working-directory: bdk-ffi/bdk-ffi + run: | + rustup toolchain install + rustup target add aarch64-linux-android x86_64-linux-android + rustc --version + + - name: "Install cargo-ndk" + run: cargo install cargo-ndk --locked + + - name: "Build the libraries and generate the bindings" + run: pnpm ubrn:android --config ubrn.config.yaml + + # ubrn also regenerates the committed glue (android/, ios/, the podspec, + # src/NativeBdkRn.ts). What ships must be what is in the repository. + - name: "Check the committed glue matches the generated glue" + run: | + if [ -n "$(git status --porcelain -- . ':(exclude)bdk-ffi')" ]; then + git status --short -- . ':(exclude)bdk-ffi' + git diff -- . ':(exclude)bdk-ffi' + echo "::error::ubrn regenerated committed files. Run the build locally and commit the result." + exit 1 + fi + + - name: "Upload the Android libraries" + uses: actions/upload-artifact@v7 + with: + name: android-jnilibs + path: android/src/main/jniLibs + if-no-files-found: error + + - name: "Upload the generated bindings" + uses: actions/upload-artifact@v7 + with: + name: bindings-android + path: | + cpp + src/generated + if-no-files-found: error + + build-ios: + name: "Build iOS xcframework" + needs: check-version + runs-on: macos-15 + timeout-minutes: 90 + steps: + - name: "Checkout" + uses: actions/checkout@v5 + with: + submodules: true + persist-credentials: false + + - name: "Set up just" + uses: extractions/setup-just@v3 + + - name: "Set up pnpm" + uses: pnpm/action-setup@v5 + + - name: "Set up Node" + uses: actions/setup-node@v5 + with: + node-version-file: .nvmrc + + - name: "Install dependencies" + run: pnpm install --frozen-lockfile --ignore-scripts + + - name: "Apply the bdk-ffi async-sync patches" + run: just submodule-apply-patch + + - name: "Set up Rust" + working-directory: bdk-ffi/bdk-ffi + run: | + rustup toolchain install + rustup target add aarch64-apple-ios aarch64-apple-ios-sim + rustc --version + + - name: "Build the xcframework and generate the bindings" + run: pnpm ubrn:ios --config ubrn.config.yaml + + - name: "Check the committed glue matches the generated glue" + run: | + if [ -n "$(git status --porcelain -- . ':(exclude)bdk-ffi')" ]; then + git status --short -- . ':(exclude)bdk-ffi' + git diff -- . ':(exclude)bdk-ffi' + echo "::error::ubrn regenerated committed files. Run the build locally and commit the result." + exit 1 + fi + + - name: "Upload the xcframework" + uses: actions/upload-artifact@v7 + with: + name: ios-xcframework + path: BdkRnFramework.xcframework + if-no-files-found: error + + - name: "Upload the generated bindings" + uses: actions/upload-artifact@v7 + with: + name: bindings-ios + path: | + cpp + src/generated + if-no-files-found: error + + publish: + name: "Publish to npm" + needs: [check-version, build-android, build-ios] + runs-on: ubuntu-24.04 + timeout-minutes: 20 + permissions: + contents: read + id-token: write + env: + VERSION: ${{ needs.check-version.outputs.version }} + DIST_TAG: ${{ needs.check-version.outputs.dist-tag }} + PUBLISH: ${{ needs.check-version.outputs.publish }} + steps: + - name: "Checkout" + uses: actions/checkout@v5 + with: + persist-credentials: false + + - name: "Set up pnpm" + uses: pnpm/action-setup@v5 + + - name: "Set up Node" + uses: actions/setup-node@v5 + with: + node-version-file: .nvmrc + registry-url: "https://registry.npmjs.org" + + # Trusted publishing needs npm 11.5.1 or later. + - name: "Update npm" + run: npm install --global npm@^11.5.1 + + - name: "Install dependencies" + run: pnpm install --frozen-lockfile --ignore-scripts + + - name: "Download the Android libraries" + uses: actions/download-artifact@v8 + with: + name: android-jnilibs + path: android/src/main/jniLibs + + - name: "Download the xcframework" + uses: actions/download-artifact@v8 + with: + name: ios-xcframework + path: BdkRnFramework.xcframework + + - name: "Download the generated bindings" + uses: actions/download-artifact@v8 + with: + pattern: bindings-* + path: bindings + + # Both build jobs generate the bindings. They embed checksums of the Rust + # API that uniffi checks at startup, so one set has to be right for both + # platforms. Ship the Android copy only after confirming the two match. + - name: "Check both platforms generated the same bindings" + run: | + diff --recursive bindings/bindings-android bindings/bindings-ios + cp -R bindings/bindings-android/cpp . + mkdir -p src/generated + cp -R bindings/bindings-android/src/generated/. src/generated/ + rm -rf bindings + + - name: "Build the JavaScript" + run: pnpm prepare + + - name: "Check the package contents" + run: node scripts/verify-package.js + + # Pack once and publish that exact file, so the tarball attached to the + # GitHub release is byte-for-byte the one on npm. + - name: "Pack" + run: npm pack --ignore-scripts + + - name: "Publish" + run: | + tarball="bdk-rn-${VERSION}.tgz" + if [ "${PUBLISH}" = "true" ]; then + npm publish "${tarball}" --provenance --access public --tag "${DIST_TAG}" + else + echo "Dry run: publish was not requested." + npm publish "${tarball}" --dry-run --access public --tag "${DIST_TAG}" + fi + + - name: "Upload the tarball" + uses: actions/upload-artifact@v7 + with: + name: npm-tarball + path: bdk-rn-${{ env.VERSION }}.tgz + if-no-files-found: error + + # After npm, so a release never describes a version that failed to publish. + github-release: + name: "Create GitHub release" + needs: [check-version, publish] + if: needs.check-version.outputs.publish == 'true' + runs-on: ubuntu-24.04 + timeout-minutes: 10 + permissions: + contents: write + id-token: write + attestations: write + env: + VERSION: ${{ needs.check-version.outputs.version }} + steps: + - name: "Download the tarball" + uses: actions/download-artifact@v8 + with: + name: npm-tarball + + - name: "Checksum" + run: sha256sum "bdk-rn-${VERSION}.tgz" > "bdk-rn-${VERSION}.tgz.sha256" + + - name: "Attest build provenance" + uses: actions/attest-build-provenance@v4 + with: + subject-path: bdk-rn-${{ env.VERSION }}.tgz + + - name: "Create the release" + env: + GH_TOKEN: ${{ github.token }} + GH_REPO: ${{ github.repository }} + run: | + prerelease="" + case "${VERSION}" in *-*) prerelease="--prerelease" ;; esac + gh release create "${GITHUB_REF_NAME}" \ + "bdk-rn-${VERSION}.tgz" "bdk-rn-${VERSION}.tgz.sha256" \ + --title "${GITHUB_REF_NAME}" \ + --generate-notes \ + --verify-tag \ + ${prerelease} diff --git a/.gitignore b/.gitignore index 9b79adb..470cb75 100644 --- a/.gitignore +++ b/.gitignore @@ -79,6 +79,7 @@ nitrogen/ # Rust target/ libbdkffi.a +android/src/main/jniLibs/ # Other temp/ diff --git a/README.md b/README.md index 5272480..f7d8648 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,19 @@ The code in this repository is mostly comprised of: The core Rust code that is exposed to the React Native language bindings actually resides in the [bdk-ffi](https://github.com/bitcoindevkit/bdk-ffi) repository. This repo pulls it in as a submodule. +## Supported Platforms + +The package ships prebuilt native libraries for: + +- **Android:** `arm64-v8a` (devices) and `x86_64` (emulators) +- **iOS:** `arm64` devices and `arm64` simulators (Apple Silicon Macs) + +32-bit Android ABIs (`armeabi-v7a` and `x86`) are not supported. New React Native apps build all four Android ABIs by default, which produces 32-bit builds that do not contain bdk-rn and would crash on a 32-bit-only device. Restrict your app to the supported ABIs in `android/gradle.properties`: + +```properties +reactNativeArchitectures=arm64-v8a,x86_64 +``` + ## Exploring the Example Apps To take a look at the API exposed in this library, you can run our example applications. [Read the docs on this here](https://bitcoindevkit.github.io/bdk-rn/example-apps/), and [find our example apps here](https://github.com/thunderbiscuit/bdk-rn-example-apps). @@ -36,7 +49,7 @@ git clone git@github.com:bitcoindevkit/bdk-rn.git cd bdk-rn # Install compilation targets -rustup target add aarch64-linux-android aarch64-apple-ios aarch64-apple-ios-sim +rustup target add aarch64-linux-android x86_64-linux-android aarch64-apple-ios aarch64-apple-ios-sim # Build the library and create tarball (includes both Android and iOS) just rename-library diff --git a/android/CMakeLists.txt b/android/CMakeLists.txt index 41c0e93..fdf0713 100644 --- a/android/CMakeLists.txt +++ b/android/CMakeLists.txt @@ -42,11 +42,11 @@ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,max-page-size cmake_path( SET MY_RUST_LIB - ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libbdkffi.a + ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libbdkffi.so NORMALIZE ) -add_library(my_rust_lib STATIC IMPORTED) -set_target_properties(my_rust_lib PROPERTIES IMPORTED_LOCATION ${MY_RUST_LIB}) +add_library(my_rust_lib SHARED IMPORTED) +set_target_properties(my_rust_lib PROPERTIES IMPORTED_LOCATION ${MY_RUST_LIB} IMPORTED_NO_SONAME ON) # Add ReactAndroid libraries, being careful to account for different versions. find_package(ReactAndroid REQUIRED CONFIG) diff --git a/android/build.gradle b/android/build.gradle index b51cb7c..316b154 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -79,7 +79,7 @@ android { } } ndk { - abiFilters "arm64-v8a" + abiFilters "arm64-v8a", "x86_64" } } diff --git a/docs/build.md b/docs/build.md index 863b1fd..68e190e 100644 --- a/docs/build.md +++ b/docs/build.md @@ -15,7 +15,7 @@ git clone git@github.com:bitcoindevkit/bdk-rn.git cd bdk-rn # Install compilation targets -rustup target add aarch64-linux-android aarch64-apple-ios aarch64-apple-ios-sim +rustup target add aarch64-linux-android x86_64-linux-android aarch64-apple-ios aarch64-apple-ios-sim # Apply the patch to the submodule (required for async Electrum and Esplora methods) just submodule-apply-patch diff --git a/docs/overview.md b/docs/overview.md index 71ec6f8..46ecbc0 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -2,27 +2,77 @@ React Native language bindings for the [Bitcoin Development Kit](https://bitcoindevkit.org/). -## Overview +## Installation -The code in this repository is mostly comprised of: +```shell +npm install bdk-rn +``` -- Build tools -- CI workflows -- Tests -- Docs +The package ships prebuilt native libraries for iOS and Android, so you do not need a Rust toolchain, and nothing is compiled or downloaded at install time. + +While 1.x is in prerelease, versions are published under the `next` tag. Install one with `npm install bdk-rn@next`. + +### Requirements + +- The React Native [New Architecture](https://reactnative.dev/architecture/landscape-and-new-architecture), which is on by default since React Native 0.76. bdk-rn is a TurboModule and does not work with the old architecture. +- An app with native projects you build yourself. bdk-rn contains native code, so it does not run in Expo Go. With Expo, use a [development build](https://docs.expo.dev/develop/development-builds/introduction/). + +### iOS + +Install the pods after adding the package: + +```shell +cd ios && pod install +``` + +Supported targets are `arm64` devices and `arm64` simulators (Apple Silicon Macs). + +### Android -The core Rust code that is exposed to the React Native language bindings actually resides in the [bdk-ffi](https://github.com/bitcoindevkit/bdk-ffi) repository. This repo pulls it in as a submodule and applies a specialized [patch]() to it so that sync methods on the Electrum and Esplora clients become `async` when used on the JS side. +Supported ABIs are `arm64-v8a` (devices) and `x86_64` (emulators). 32-bit ABIs (`armeabi-v7a` and `x86`) are not supported. -## Prerequisites +New React Native apps build all four ABIs by default. The 32-bit builds would not contain bdk-rn and would crash on a 32-bit-only device, so restrict your app to the supported ABIs in `android/gradle.properties`: -To build the library and start testing locally, you must have: +```properties +reactNativeArchitectures=arm64-v8a,x86_64 +``` -- The [Rust](https://rust-lang.org/) toolchain installed on your machine -- Set the default Rust toolchain to `1.91.1` (currently Rust stable) -- The [just](https://github.com/casey/just) CLI tool -- Initiated the submodule (`just submodule-init`) -- Installed your Rust compilation targets +bdk-rn's small C++ bridge is compiled as part of your app's build, using the NDK and CMake your React Native app already uses. + +## Usage + +```typescript +import { + Mnemonic, + WordCount, + DescriptorSecretKey, + Descriptor, + KeychainKind, + Network, + NetworkKind, + Persister, + Wallet, +} from 'bdk-rn'; + +const mnemonic = new Mnemonic(WordCount.Words12); +const secretKey = new DescriptorSecretKey(NetworkKind.Test, mnemonic, undefined); +const descriptor = Descriptor.newBip86(secretKey, KeychainKind.External, NetworkKind.Test); + +const wallet = Wallet.createSingle(descriptor, Network.Signet, Persister.newInMemory()); +const addressInfo = wallet.revealNextAddress(KeychainKind.External); +``` + +The [example apps](examples/about.md) show more of the API. + +## About This Repository + +The code in this repository is mostly comprised of: + +- Build tools +- CI and release workflows +- Tests +- Docs -## Additional Resources +The core Rust code that is exposed to the React Native language bindings actually resides in the [bdk-ffi](https://github.com/bitcoindevkit/bdk-ffi) repository. This repo pulls it in as a submodule and applies [patches](https://github.com/bitcoindevkit/bdk-rn/tree/master/patches) to it so that sync methods on the Electrum and Esplora clients become `async` when used on the JS side. -For more advanced information on how to build this library, see the [uniffi-bindgen-react-native documentation](https://jhugman.github.io/uniffi-bindgen-react-native/guides/rn/getting-started.html). +To build the library from source, for example to work on bdk-rn itself, see [Build](build.md). For more on how the bindings are generated, see the [uniffi-bindgen-react-native documentation](https://jhugman.github.io/uniffi-bindgen-react-native/guides/rn/getting-started.html). diff --git a/package.json b/package.json index c462381..2345404 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,8 @@ "lint": "eslint \"**/*.{js,ts,tsx}\"", "clean": "del-cli android/build lib", "prepare": "bob build", + "prepublishOnly": "node scripts/verify-package.js", + "verify-package": "node scripts/verify-package.js", "release": "release-it --only-version" }, "keywords": [ diff --git a/scripts/verify-package.js b/scripts/verify-package.js new file mode 100644 index 0000000..24288ff --- /dev/null +++ b/scripts/verify-package.js @@ -0,0 +1,88 @@ +#!/usr/bin/env node + +/** + * Refuse to publish a tarball that is missing its prebuilt native binaries. + * + * bdk-rn ships the Rust library inside the npm package and has no install + * script, so a tarball without it is not slower to install, it is broken, and + * it only shows up later as a CMake or linker error in someone else's app. + * + * The release workflow runs this before packing. It also hangs off + * `prepublishOnly` so a hand-run `npm publish` from a working tree that never + * built the binaries fails here instead of on npm. + */ + +const { execSync } = require('child_process'); +const path = require('path'); + +const ANDROID_ABIS = ['arm64-v8a', 'x86_64']; + +// npm rejects tarballs over 256 MiB. Fail well before that so growth is noticed +// while there is still room to act on it. +const MAX_PACKED_BYTES = 200 * 1024 * 1024; + +// --ignore-scripts so packing does not re-run `prepare`; only the file list and +// size are needed here. +const [pack] = JSON.parse( + execSync('npm pack --dry-run --json --ignore-scripts', { + cwd: path.join(__dirname, '..'), + encoding: 'utf8', + }) +); +const files = new Set(pack.files.map((file) => file.path)); + +const required = [ + ['BdkRnFramework.xcframework/Info.plist', 'iOS xcframework'], + ['BdkRnFramework.xcframework/ios-arm64/libbdkffi.a', 'iOS device slice'], + [ + 'BdkRnFramework.xcframework/ios-arm64-simulator/libbdkffi.a', + 'iOS simulator slice', + ], + ...ANDROID_ABIS.map((abi) => [ + `android/src/main/jniLibs/${abi}/libbdkffi.so`, + `Android ${abi} shared library`, + ]), + ['cpp/generated/bdk.cpp', 'generated C++ bindings'], + ['src/generated/bdk.ts', 'generated TypeScript bindings'], + ['lib/module/index.js', 'compiled JavaScript (run `pnpm prepare`)'], +]; + +const problems = required + .filter(([file]) => !files.has(file)) + .map(([file, label]) => `missing ${label} (${file})`); + +// A static archive still links, but multiplies the package size ~10x, so it +// would be a silent regression. See android.useSharedLibrary in ubrn.config.yaml. +for (const file of files) { + if (/^android\/src\/main\/jniLibs\/.*\.a$/.test(file)) { + problems.push(`Android static archive in the tarball (${file})`); + } + if (file.startsWith('bdk-ffi/')) { + problems.push(`Rust sources leaked into the tarball (${file})`); + } +} + +const packedMiB = (pack.size / 1024 / 1024).toFixed(1); +if (pack.size > MAX_PACKED_BYTES) { + problems.push( + `tarball is ${packedMiB} MiB, over the ${MAX_PACKED_BYTES / 1024 / 1024} MiB budget` + ); +} + +if (problems.length > 0) { + console.error(`\nRefusing to publish ${pack.id}:\n`); + for (const problem of problems) { + console.error(` - ${problem}`); + } + console.error( + '\nReleases are built and published by .github/workflows/release.yml when a' + ); + console.error( + 'v* tag is pushed. To build locally, run `just build-tarball`.\n' + ); + process.exit(1); +} + +console.log( + `${pack.id}: ${files.size} files, ${packedMiB} MiB packed, prebuilt binaries present` +); diff --git a/tests/android/gradle.properties b/tests/android/gradle.properties index 9afe615..463bc12 100644 --- a/tests/android/gradle.properties +++ b/tests/android/gradle.properties @@ -25,7 +25,7 @@ android.useAndroidX=true # Use this property to specify which architecture you want to build. # You can also override it from the CLI using # ./gradlew -PreactNativeArchitectures=x86_64 -reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 +reactNativeArchitectures=arm64-v8a,x86_64 # Use this property to enable support to the new architecture. # This will allow you to use TurboModules and the Fabric render in diff --git a/ubrn.config.yaml b/ubrn.config.yaml index 8e978ff..1ba1202 100644 --- a/ubrn.config.yaml +++ b/ubrn.config.yaml @@ -3,8 +3,18 @@ rust: manifestPath: Cargo.toml android: + # 64-bit only: arm64-v8a for devices, x86_64 for emulators. ubrn writes this + # list into ndk.abiFilters in android/build.gradle, so bdk-rn is only built + # and packaged for these two whatever the app's reactNativeArchitectures says. targets: - arm64-v8a + - x86_64 + # Link the Rust library as a .so rather than a static archive. The binaries + # ship in the npm package, and a static archive carries every object file in + # the dependency graph: ~150 MB per ABI, against ~15 MB for the linked .so. + # ubrn requires the .so to keep its symbols. The release-smaller profile only + # strips debuginfo, which leaves them intact. + useSharedLibrary: true ios: targets: