From ab4e1cf9121c31a3cc6847e56814d36999733c5b Mon Sep 17 00:00:00 2001 From: Szymon Chmal Date: Tue, 7 Jul 2026 10:30:03 +0200 Subject: [PATCH 1/3] fix: support RN 0.81.5 and below Hermes prefab target on Android RN <= 0.81 publishes the Hermes prefab module as `libhermes` (CMake target hermes-engine::libhermes), while RN >= 0.82 renamed it to `libhermesvm` (hermes-engine::hermesvm). CMakeLists.txt hard-coded the 0.82+ target name, so any app on RN 0.81.x failed to configure with "target was not found". Branch on whichever target find_package actually resolves. Also explicitly pin libvoltra_js_renderer.so to 16KB page alignment via -Wl,-z,max-page-size=16384 so older NDKs (< r28) still produce 16KB-compatible output, and exclude libhermesvm.so from packaging so Voltra never bundles a duplicate Hermes engine on RN >= 0.82 hosts (mirrors the existing libhermes.so exclude for RN <= 0.81). Fixes #216 --- .../android-client/android/CMakeLists.txt | 23 ++++++++++++++++--- packages/android-client/android/build.gradle | 12 ++++++---- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/packages/android-client/android/CMakeLists.txt b/packages/android-client/android/CMakeLists.txt index 1cddb02b..2ba0ebd4 100644 --- a/packages/android-client/android/CMakeLists.txt +++ b/packages/android-client/android/CMakeLists.txt @@ -8,12 +8,22 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) # We consume them through find_package below. # # NOTE: find_package does NOT error on a wrong target *name* — the failure only -# surfaces at target_link_libraries. The correct Hermes prefab target on Android -# (RN 0.83, com.facebook.react:hermes-android) is `hermes-engine::hermesvm`. +# surfaces at target_link_libraries. The Hermes prefab target on Android has +# been renamed across RN versions (com.facebook.react:hermes-android): +# - RN <= 0.81: prefab module `libhermes` -> CMake target hermes-engine::libhermes +# - RN >= 0.82: prefab module `libhermesvm` -> CMake target hermes-engine::hermesvm +# We branch on which target find_package actually resolved so Voltra builds +# against both RN generations. find_package(ReactAndroid REQUIRED CONFIG) find_package(hermes-engine REQUIRED CONFIG) find_package(fbjni REQUIRED CONFIG) +if(TARGET hermes-engine::hermesvm) + set(VOLTRA_HERMES_TARGET hermes-engine::hermesvm) +else() + set(VOLTRA_HERMES_TARGET hermes-engine::libhermes) +endif() + # --------------------------------------------------------------------------- # Voltra JS Renderer (Dynamic Widgets on Android) # --------------------------------------------------------------------------- @@ -28,6 +38,13 @@ target_link_libraries(voltra_js_renderer android log ReactAndroid::jsi - hermes-engine::hermesvm + ${VOLTRA_HERMES_TARGET} fbjni::fbjni ) + +# 16KB page size support: explicitly align libvoltra_js_renderer.so to 16KB +# pages regardless of host NDK version. NDK r28+ defaults to this, but we +# pin it explicitly so older NDKs also produce 16KB-compatible output. We +# only support 16KB alignment (no 4KB-only build) — 16KB-aligned libs run +# fine on 4KB-page devices too. +target_link_options(voltra_js_renderer PRIVATE "-Wl,-z,max-page-size=16384") diff --git a/packages/android-client/android/build.gradle b/packages/android-client/android/build.gradle index a2b61838..cd12cdc0 100644 --- a/packages/android-client/android/build.gradle +++ b/packages/android-client/android/build.gradle @@ -59,7 +59,7 @@ android { buildFeatures { buildConfig true compose true - // Required to consume React Native's published prefab modules (jsi, hermesvm, fbjni). + // Required to consume React Native's published prefab modules (jsi, hermes, fbjni). prefab true } @@ -71,6 +71,7 @@ android { "**/libfbjni.so", "**/libjsi.so", "**/libhermes.so", + "**/libhermesvm.so", ] } @@ -95,10 +96,11 @@ android { dependencies { // React Native implementation "com.facebook.react:react-android" - // Provides the `hermes-engine` prefab (libhermesvm) that CMakeLists.txt's - // find_package(hermes-engine) consumes for the standalone Hermes JS runtime. Without it the - // native build fails to configure in release variants (react-android alone does not publish the - // Hermes prefab). Version is substituted by the React Native Gradle Plugin (applied above). + // Provides the `hermes-engine` prefab (libhermes on RN <= 0.81, libhermesvm on RN >= 0.82) + // that CMakeLists.txt's find_package(hermes-engine) consumes for the standalone Hermes JS + // runtime. Without it the native build fails to configure in release variants (react-android + // alone does not publish the Hermes prefab). Version is substituted by the React Native + // Gradle Plugin (applied above). implementation "com.facebook.react:hermes-android" // Jetpack Glance From 0f01bdc872dc112caf854658d920afd806864096 Mon Sep 17 00:00:00 2001 From: Szymon Chmal Date: Tue, 7 Jul 2026 10:33:39 +0200 Subject: [PATCH 2/3] fix: correct hermesvm prefab module name in comment and fail fast on unknown Hermes prefab target --- packages/android-client/android/CMakeLists.txt | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/android-client/android/CMakeLists.txt b/packages/android-client/android/CMakeLists.txt index 2ba0ebd4..1ab72058 100644 --- a/packages/android-client/android/CMakeLists.txt +++ b/packages/android-client/android/CMakeLists.txt @@ -10,18 +10,21 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) # NOTE: find_package does NOT error on a wrong target *name* — the failure only # surfaces at target_link_libraries. The Hermes prefab target on Android has # been renamed across RN versions (com.facebook.react:hermes-android): -# - RN <= 0.81: prefab module `libhermes` -> CMake target hermes-engine::libhermes -# - RN >= 0.82: prefab module `libhermesvm` -> CMake target hermes-engine::hermesvm +# - RN <= 0.81: prefab module `libhermes` -> CMake target hermes-engine::libhermes +# - RN >= 0.82: prefab module `hermesvm` -> CMake target hermes-engine::hermesvm # We branch on which target find_package actually resolved so Voltra builds -# against both RN generations. +# against both RN generations, and fail fast at configure time if neither +# exists (e.g. a future prefab rename) instead of erroring later at link time. find_package(ReactAndroid REQUIRED CONFIG) find_package(hermes-engine REQUIRED CONFIG) find_package(fbjni REQUIRED CONFIG) if(TARGET hermes-engine::hermesvm) - set(VOLTRA_HERMES_TARGET hermes-engine::hermesvm) + set(VOLTRA_HERMES_TARGET hermes-engine::hermesvm) # RN >= 0.82 +elseif(TARGET hermes-engine::libhermes) + set(VOLTRA_HERMES_TARGET hermes-engine::libhermes) # RN <= 0.81 else() - set(VOLTRA_HERMES_TARGET hermes-engine::libhermes) + message(FATAL_ERROR "Voltra: hermes-engine prefab found but neither target hermes-engine::hermesvm (RN >= 0.82) nor hermes-engine::libhermes (RN <= 0.81) exists. Unsupported React Native version?") endif() # --------------------------------------------------------------------------- From 87dd5c26722e469d1d06d01ab3cd77f053618957 Mon Sep 17 00:00:00 2001 From: Szymon Chmal Date: Tue, 7 Jul 2026 13:08:45 +0200 Subject: [PATCH 3/3] fix: add RN 0.81 Android build changeset Document the user-facing Android build fix for React Native 0.81 apps. --- .changeset/strong-cycles-spark.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/strong-cycles-spark.md diff --git a/.changeset/strong-cycles-spark.md b/.changeset/strong-cycles-spark.md new file mode 100644 index 00000000..c0394702 --- /dev/null +++ b/.changeset/strong-cycles-spark.md @@ -0,0 +1,5 @@ +--- +'@use-voltra/android-client': patch +--- + +Fix Android builds for React Native 0.81 apps by linking the correct Hermes prefab target.