Android crashing RN (0.69.4) libhermes-executor-release.so

This issue has been tracked since 2022-09-14.

Description

I updated to react-native 0.69.4. Now Android is crashing but only for certain variant types. I have 4 of them (debug, canary, beta and release). debug and release work fine but canary and beta give the following error on application startup. Maybe work mentioning is that I use expo-modules-core if that makes any difference.

09-13 13:31:26.675 20708 20708 E AndroidRuntime: java.lang.UnsatisfiedLinkError: couldn't find DSO to load: libhermes-executor-release.so

Version

0.69.4

Output of npx react-native info

System:
    OS: macOS 12.3
    CPU: (10) arm64 Apple M1 Pro
    Memory: 240.58 MB / 32.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 16.17.0 - ~/.nvm/versions/node/v16.17.0/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 8.15.0 - ~/.nvm/versions/node/v16.17.0/bin/npm
    Watchman: 2022.09.05.00 - /opt/homebrew/bin/watchman
  Managers:
    CocoaPods: 1.11.3 - /usr/local/bin/pod
  SDKs:
    iOS SDK:
      Platforms: DriverKit 21.4, iOS 15.5, macOS 12.3, tvOS 15.4, watchOS 8.5
    Android SDK: Not Found
  IDEs:
    Android Studio: 2021.2 AI-212.5712.43.2112.8815526
    Xcode: 13.4.1/13F100 - /usr/bin/xcodebuild
  Languages:
    Java: javac 17 - /Users/mrados/.jabba/jdk/[email protected]/Contents/Home/bin/javac
  npmPackages:
    @react-native-community/cli: Not Found
    react: 18.0.0 => 18.0.0 
    react-native: 0.69.4 => 0.69.4 
    react-native-macos: Not Found
  npmGlobalPackages:
    *react-native*: Not Found

Steps to reproduce

hermes -> enabled
build.gradle

	dependencies { 
	      implementation 'com.facebook.soloader:soloader:0.10.4+'
	  
	  
	      if (enableHermes) {
	          implementation("com.facebook.react:hermes-engine:+") {
	              exclude group: 'com.facebook.fbjni'
	          }
	      } else {
	          implementation jscFlavor
	      }
	}

Snack, code example, screenshot, or link to a repository

.

danilobuerger wrote this answer on 2022-09-14

Thats because hermes is missing in those variants. Pleasse share your whole build.gradle

mrados7 wrote this answer on 2022-09-14

Hey @danilobuerger

apply plugin: 'com.google.gms.google-services'

import com.android.build.OutputFile

project.ext.react = [
        enableHermes: true,
        cliPath     : "../../node_modules/react-native/cli.js"
]

apply from: "../../node_modules/react-native/react.gradle"

/**
 * Set this to true to create two separate APKs instead of one:
 *   - An APK that only works on ARM devices
 *   - An APK that only works on x86 devices
 * The advantage is the size of the APK is reduced by about 4MB.
 * Upload all the APKs to the Play Store and people will download
 * the correct one based on the CPU architecture of their device.
 */
def enableSeparateBuildPerCPUArchitecture = false

/**
 * Run Proguard to shrink the Java bytecode in release builds.
 */
def enableProguardInReleaseBuilds = false

def jscFlavor = 'org.webkit:android-jsc:+'

/**
 * Whether to enable the Hermes VM.
 *
 * This should be set on project.ext.react and mirrored here.  If it is not set
 * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
 * and the benefits of using Hermes will therefore be sharply reduced.
 */
def enableHermes = project.ext.react.get("enableHermes", false);

android {
    compileSdkVersion rootProject.ext.compileSdkVersion

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    defaultConfig {
        applicationId "com.myapp"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 19
        versionName "2.9"
    }
    splits {
        abi {
            reset()
            enable enableSeparateBuildPerCPUArchitecture
            universalApk false  // If true, also generate a universal APK
            include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
        }
    }
    signingConfigs {
        debug {
            storeFile file('debug.keystore')
            storePassword 'android'
            keyAlias 'androiddebugkey'
            keyPassword 'android'
        }

        canary {
            storeFile file('reev.jks')
            storePassword System.getProperty("APPCENTER_KEYSTORE_PASSWORD")
            keyAlias System.getProperty("APPCENTER_KEY_ALIAS")
            keyPassword System.getProperty("APPCENTER_KEY_PASSWORD")
        }

        beta {
            storeFile file('reev.jks')
            storePassword System.getProperty("APPCENTER_KEYSTORE_PASSWORD")
            keyAlias System.getProperty("APPCENTER_KEY_ALIAS")
            keyPassword System.getProperty("APPCENTER_KEY_PASSWORD")
        }

        release {
            storeFile file('reev.jks')
            storePassword System.getProperty("APPCENTER_KEYSTORE_PASSWORD")
            keyAlias System.getProperty("APPCENTER_KEY_ALIAS")
            keyPassword System.getProperty("APPCENTER_KEY_PASSWORD")
        }
    }
    buildTypes {
        debug {
            applicationIdSuffix ".debug"
            signingConfig signingConfigs.debug
        }
        release {
            applicationIdSuffix ".prod"
            signingConfig signingConfigs.debug
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
        }
        canary {
            applicationIdSuffix ".canary"
            signingConfig signingConfigs.debug
            matchingFallbacks = ['release']
        }
        beta {
            applicationIdSuffix ".beta"
            signingConfig signingConfigs.debug
            matchingFallbacks = ['release']
        }
    }

    // applicationVariants are e.g. debug, release
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            // For each separate APK per architecture, set a unique version code as described here:
            // https://developer.android.com/studio/build/configure-apk-splits.html
            def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
            def abi = output.getFilter(OutputFile.ABI)
            if (abi != null) {  // null for the universal-debug, universal-release variants
                output.versionCodeOverride =
                        versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
            }

        }
    }
}

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    //noinspection GradleDynamicVersion
    implementation "com.facebook.react:react-native:+"  // From node_modules

    def isGifEnabled = (findProperty('expo.gif.enabled') ?: "") == "true";
    def isWebpEnabled = (findProperty('expo.webp.enabled') ?: "") == "true";
    def isWebpAnimatedEnabled = (findProperty('expo.webp.animated') ?: "") == "true";

    // If your app supports Android versions before Ice Cream Sandwich (API level 14)
    // All fresco packages should use the same version
    if (isGifEnabled || isWebpEnabled) {
        implementation 'com.facebook.fresco:fresco:2.0.0'
        implementation 'com.facebook.fresco:imagepipeline-okhttp3:2.0.0'
    }

    if (isGifEnabled) {
        // For animated gif support
        implementation 'com.facebook.fresco:animated-gif:2.0.0'
    }

    if (isWebpEnabled) {
        // For webp support
        implementation 'com.facebook.fresco:webpsupport:2.0.0'
        if (isWebpAnimatedEnabled) {
            // Animated webp support
            implementation 'com.facebook.fresco:animated-webp:2.0.0'
        }
    }

    implementation 'com.facebook.soloader:soloader:0.10.4+'

    implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
    debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
        exclude group: 'com.facebook.fbjni'
    }
    debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
        exclude group: 'com.facebook.flipper'
        exclude group: 'com.squareup.okhttp3', module: 'okhttp'
    }
    debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
        exclude group: 'com.facebook.flipper'
    }

    implementation platform('com.google.firebase:firebase-bom:27.1.0')
    implementation 'com.google.firebase:firebase-analytics-ktx'

//     androidTestImplementation('com.wix:detox:+')

    if (enableHermes) {
        implementation("com.facebook.react:hermes-engine:+") {
            exclude group: 'com.facebook.fbjni'
        }
    } else {
        implementation jscFlavor
    }
}

// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
    from configurations.implementation
    into 'libs'
}

apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json')"].execute().text.trim(), "../native_modules.gradle");
applyNativeModulesAppBuildGradle(project)

apply plugin: "com.bugsnag.android.gradle"
danilobuerger wrote this answer on 2022-09-14

My guess is that its related to the change here: 4d91f40
Before you had:

def hermesPath = "../../node_modules/hermes-engine/android/";
debugImplementation files(hermesPath + "hermes-debug.aar")
releaseImplementation files(hermesPath + "hermes-release.aar")

and could just add a new line for each variant, for example:

canaryImplementation files(hermesPath + "hermes-release.aar") 

Maybe @cortinico knows more how to handle other build variants with the new directive?

mrados7 wrote this answer on 2022-09-14

@danilobuerger Yeah that's what I thought as well, but then I read this:
https://reactnative.dev/architecture/bundled-hermes

On the Gradle consumer side, we also shipped a small improvement on the consumer side: we moved from releaseImplementation & debugImplementation to implementation. This is possible because the newer hermes-engine Android artifact is variant aware and will properly match a debug build of the engine with a debug build of your app. You don't need any custom configuration here (even if you use staging or other build types/flavors).

danilobuerger wrote this answer on 2022-09-14

As far as I understand that should work with https://developer.android.com/studio/build/build-variants#variant_aware matchingFallbacks which you are using.

allemanfredi wrote this answer on 2022-09-14

I have the same issue

mrados7 wrote this answer on 2022-09-14

I'm wondering now is it possible that in my case it's looking for libhermes-executor-canary.so instead of libhermes-executor-release.so. Maybe it should be built like libhermes-executor-{variant}.so. Maybe I'm talking nosense now but I don't know what are the reasons of release and debug working normally but other variants are not.

danilobuerger wrote this answer on 2022-09-14

The way that hermes gets bundled changed in rn 0.70, could you please try with that release?

mrados7 wrote this answer on 2022-09-14

Unfortunately I cannot upgrade to rn 0.70 as I'm on expo SDK 46 which would not support 0.70 if I update manually as far as I know.

Summys wrote this answer on 2022-09-14

Might be related to this issue #33177 (comment)

allemanfredi wrote this answer on 2022-09-14

I have noticed that (using the template provided by rn team) i get these weird logs:

libhermes.so not found on /data/app/~~KKW2kpIM6DTHUhFqut084A==/io.app-z_D6rsqxO6ru8D4oSFwEAA==/lib/arm64
09-14 17:36:47.773  2724  2724 V SoLoader: liblog.so not found on /data/app/~~KKW2kpIM6DTHUhFqut084A==/io.app-z_D6rsqxO6ru8D4oSFwEAA==/lib/arm64
09-14 17:36:47.773  2724  2724 V SoLoader: liblog.so not found on /data/app/~~KKW2kpIM6DTHUhFqut084A==/io.app-z_D6rsqxO6ru8D4oSFwEAA==/base.apk!/lib/arm64-v8a
09-14 17:36:47.773  2724  2724 V SoLoader: libm.so not found on /data/app/~~KKW2kpIM6DTHUhFqut084A==/io.app-z_D6rsqxO6ru8D4oSFwEAA==/lib/arm64
09-14 17:36:47.773  2724  2724 V SoLoader: libm.so not found on /data/app/~~KKW2kpIM6DTHUhFqut084A==/io.app-z_D6rsqxO6ru8D4oSFwEAA==/base.apk!/lib/arm64-v8a
09-14 17:36:47.774  2724  2724 V SoLoader: libdl.so not found on /data/app/~~KKW2kpIM6DTHUhFqut084A==/io.app-z_D6rsqxO6ru8D4oSFwEAA==/lib/arm64
09-14 17:36:47.774  2724  2724 V SoLoader: libdl.so not found on /data/app/~~KKW2kpIM6DTHUhFqut084A==/io.app-z_D6rsqxO6ru8D4oSFwEAA==/base.apk!/lib/arm64-v8a
09-14 17:36:47.774  2724  2724 V SoLoader: libc.so not found on /data/app/~~KKW2kpIM6DTHUhFqut084A==/io.app-z_D6rsqxO6ru8D4oSFwEAA==/lib/arm64
09-14 17:36:47.774  2724  2724 V SoLoader: libc.so not found on /data/app/~~KKW2kpIM6DTHUhFqut084A==/io.app-z_D6rsqxO6ru8D4oSFwEAA==/base.apk!/lib/arm64-v8a
09-14 17:36:47.778  2724  2724 D SoLoader: libhermes.so found on /data/app/~~KKW2kpIM6DTHUhFqut084A==/io.app-z_D6rsqxO6ru8D4oSFwEAA==/base.apk!/lib/arm64-v8a
09-14 17:36:47.778  2724  2724 V SoLoader: libhermes-executor-debug.so not found on /data/app/~~KKW2kpIM6DTHUhFqut084A==/io.app-z_D6rsqxO6ru8D4oSFwEAA==/lib/arm64
09-14 17:36:47.778  2724  2724 V SoLoader: libhermes-executor-debug.so not found on /data/app/~~KKW2kpIM6DTHUhFqut084A==/io.app-z_D6rsqxO6ru8D4oSFwEAA==/base.apk!/lib/arm64-v8a
09-14 17:36:47.778  2724  2724 E SoLoader: 	SoSource 0: com.facebook.soloader.DirectorySoSource[root = /data/app/~~KKW2kpIM6DTHUhFqut084A==/io.app-z_D6rsqxO6ru8D4oSFwEAA==/lib/arm64 flags = 0]
09-14 17:36:47.778  2724  2724 E SoLoader: 	SoSource 1: com.facebook.soloader.DirectApkSoSource[root = (/data/app/~~KKW2kpIM6DTHUhFqut084A==/io.app-z_D6rsqxO6ru8D4oSFwEAA==/base.apk!/lib/arm64-v8a, )]
09-14 17:36:47.778  2724  2724 E SoLoader: 	Native lib dir: /data/app/~~KKW2kpIM6DTHUhFqut084A==/io.app-z_D6rsqxO6ru8D4oSFwEAA==/lib/arm64
09-14 17:36:47.779  2724  2724 V SoLoader: libhermes-executor-release.so not found on /data/app/~~KKW2kpIM6DTHUhFqut084A==/io.app-z_D6rsqxO6ru8D4oSFwEAA==/lib/arm64
09-14 17:36:47.780  2724  2724 V SoLoader: libandroid.so not found on /data/app/~~KKW2kpIM6DTHUhFqut084A==/io.app-z_D6rsqxO6ru8D4oSFwEAA==/lib/arm64
09-14 17:36:47.780  2724  2724 V SoLoader: libandroid.so not found on /data/app/~~KKW2kpIM6DTHUhFqut084A==/io.app-z_D6rsqxO6ru8D4oSFwEAA==/base.apk!/lib/arm64-v8a
09-14 17:36:47.784  2724  2724 D SoLoader: libhermes-executor-release.so found on /data/app/~~KKW2kpIM6DTHUhFqut084A==/io.app-z_D6rsqxO6ru8D4oSFwEAA==/base.apk!/lib/arm64-v8a

The weird thing is that i'm building in release mode but i see that for example the app is trying to access libhermes-executor-debug.so

mrados7 wrote this answer on 2022-09-14

@Summys yep #33177 (comment) this helped me. Variants have to be named with Release suffix. ({variant}Release). In my case canaryRelease and it worked like that.

danilobuerger wrote this answer on 2022-09-14

That doesn't sound like a proper solution.

mrados7 wrote this answer on 2022-09-14

I agree. Specially because docs say it can be named staging. Not sure why does this work, or is there any other solution to this, just said what worked for me.

cortinico wrote this answer on 2022-09-18

I'm wondering now is it possible that in my case it's looking for libhermes-executor-canary.so instead of libhermes-executor-release.so. Maybe it should be built like libhermes-executor-{variant}.so. Maybe I'm talking nosense now but I don't know what are the reasons of release and debug working normally but other variants are not.

The problem here is in the logic in place to remove the .so files from the final APKs.

You should be able to solve this by specifying a custom deleteDebugFilesForVariant in your build.gradle such as:

project.ext.react = [
   bundleInStaging: true,
   devDisabledInStaging: true,
   enableHermes: true,  // clean and rebuild if changing
+  deleteDebugFilesForVariant: {
+    def variant -> variant.name.toLowerCase().contains("release") || variant.name.toLowerCase().contains("canary") ||
variant.name.toLowerCase().contains("beta")
+  }
]

We're looking into potentially changing this approach in the future as it's really brittle.

sidferreira wrote this answer on 2022-09-18

@danilobuerger the fix, in the end, seems to be the same...

danilobuerger wrote this answer on 2022-09-19

@mrados7 could you please check #34678 if that solves your problem without having to rename the variants?

mrados7 wrote this answer on 2022-09-19

@danilobuerger Yes it works but I had to add additional lines as well:

project.ext.react = [
        bundleInBeta              : true,
        bundleInCanary            : true,
        devDisabledInBeta         : true,
        devDisabledInCanary       : true,
        enableHermes              : true,
        cliPath                   : "../../node_modules/react-native/cli.js",
        deleteDebugFilesForVariant: {
            def variant ->
                variant.name.toLowerCase().contains("release") || variant.name.toLowerCase().contains("canary") ||
                        variant.name.toLowerCase().contains("beta")
        }
]
sidferreira wrote this answer on 2022-09-19

@mrados7 we have a staging variant, so I totally get the struggle

More Details About Repo
Owner Name facebook
Repo Name react-native
Full Name facebook/react-native
Language JavaScript
Created Date 2015-01-09
Updated Date 2022-10-03
Star Count 105144
Watcher Count 3666
Fork Count 22469
Issue Count 2232

YOU MAY BE INTERESTED

Issue Title Created Date Updated Date