Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android - Build issue with hermesCommand #37713

Closed
yalakkademy opened this issue Jun 6, 2023 · 15 comments
Closed

Android - Build issue with hermesCommand #37713

yalakkademy opened this issue Jun 6, 2023 · 15 comments
Labels
Needs: Attention Issues where the author has responded to feedback. Platform: Android Android applications. Type: Upgrade Issue Issues reported from upgrade issue form

Comments

@yalakkademy
Copy link

yalakkademy commented Jun 6, 2023

New Version

71.3

Old Version

69.4

Build Target(s)

debug, release, stagging

Output of react-native info

    OS: macOS 13.3.1
    CPU: (8) arm64 Apple M1 Pro
    Memory: 65.69 MB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 19.9.0 - ~/.nvm/versions/node/v19.9.0/bin/node
    Yarn: 1.22.19 - /opt/homebrew/bin/yarn
    npm: 9.6.3 - ~/.nvm/versions/node/v19.9.0/bin/npm
    Watchman: 2023.02.13.00 - /opt/homebrew/bin/watchman
  Managers:
    CocoaPods: 1.11.3 - /Users/alakkadyoussef/.rvm/gems/ruby-3.2.2/bin/pod
  SDKs:
    iOS SDK:
      Platforms: DriverKit 22.2, iOS 16.2, macOS 13.1, tvOS 16.1, watchOS 9.1
    Android SDK:
      API Levels: 29, 31, 33, 33
      Build Tools: 29.0.2, 30.0.3, 31.0.0, 33.0.0, 33.0.1
      System Images: android-30 | Google APIs Intel x86_64 Atom, android-31 | ARM 64 v8a, android-31 | Google APIs ARM 64 v8a, android-31 | Google Play ARM 64 v8a, android-33-ext4 | Google Play ARM 64 v8a, android-33 | Google APIs ARM 64 v8a, android-33 | Google Play ARM 64 v8a
      Android NDK: Not Found
  IDEs:
    Android Studio: 2022.2 AI-222.4459.24.2221.10121639
    Xcode: 14.2/14C18 - /usr/bin/xcodebuild
  Languages:
    Java: 11.0.19 - /usr/bin/javac
  npmPackages:
    @react-native-community/cli: Not Found
    react: Not Found
    react-native: Not Found
    react-native-macos: Not Found
  npmGlobalPackages:
    *react-native*: Not Found

Issue and Reproduction Steps

Hi, this issue is a duplicate of #35927
But in my case I don't have any issue with the path to hermesc.

Does someone got a tips on how I can manage to fix this issue ?

Reproduction: Upgrade RN 69.4 to 71.3 and try to build an assembleRelease :

info Done writing sourcemap output
info Copying 17 asset files
info Done copying assets

> Task :app:createBundleDevelopmentReleaseJsAndAssets FAILED

FAILURE: Build completed with 2 failures.

1: Task failed with an exception.
-----------
* What went wrong:
Execution failed for task ':app:createBundleDevelopmentReleaseJsAndAssets'.
> Couldn't determine Hermesc location. Please set `react.hermesCommand` to the path of the hermesc binary file. node_modules/react-native/sdks/hermesc/%OS-BIN%/hermesc```

Thank you
@yalakkademy yalakkademy added Needs: Triage 🔍 Type: Upgrade Issue Issues reported from upgrade issue form labels Jun 6, 2023
@github-actions github-actions bot added Version: unspecified No version information could be extracted Platform: Android Android applications. labels Jun 6, 2023
@cortinico cortinico removed Needs: Triage 🔍 Version: unspecified No version information could be extracted labels Jun 6, 2023
@cortinico
Copy link
Contributor

Does someone got a tips on how I can manage to fix this issue ?

Can you please share your android/app/build.gradle file?

@yalakkademy
Copy link
Author

yalakkademy commented Jun 6, 2023

@cortinico of course 👍

apply plugin: "com.facebook.react"
apply plugin: 'com.google.gms.google-services'

import com.android.build.OutputFile
import org.gradle.internal.logging.text.StyledTextOutputFactory
import org.gradle.internal.logging.text.StyledTextOutput.Style

/**
 * This is the configuration block to customize your React Native Android app.
 * By default you don't need to apply any configuration, just uncomment the lines you need.
 */
react {
    /* Folders */
    //   The root of your project, i.e. where "package.json" lives. Default is '..'
    // root = file("../")
    //   The folder where the react-native NPM package is. Default is ../node_modules/react-native
    reactNativeDir = file("../../../node_modules/react-native")
    //   The folder where the react-native Codegen package is. Default is ../node_modules/react-native-codegen
    codegenDir = file("../../../node_modules/react-native-codegen")
    //   The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js
    cliFile = file("../../../node_modules/react-native/cli.js")

    /* Variants */
    //   The list of variants to that are debuggable. For those we're going to
    //   skip the bundling of the JS bundle and the assets. By default is just 'debug'.
    //   If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants.
    // debuggableVariants = ["liteDebug", "prodDebug"]

    /* Bundling */
    //   A list containing the node command and its flags. Default is just 'node'.
    // nodeExecutableAndArgs = ["node"]
    //
    //   The command to run when bundling. By default is 'bundle'
    // bundleCommand = "ram-bundle"
    //
    //   The path to the CLI configuration file. Default is empty.
    // bundleConfig = file(../rn-cli.config.js)
    //
    //   The name of the generated asset file containing your JS bundle
    // bundleAssetName = "MyApplication.android.bundle"
    //
    //   The entry file for bundle generation. Default is 'index.android.js' or 'index.js'
    // entryFile = file("../js/MyApplication.android.js")
    //
    //   A list of extra flags to pass to the 'bundle' commands.
    //   See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle
    // extraPackagerArgs = []

    /* Hermes Commands */
    //   The hermes compiler command to run. By default it is 'hermesc'
    hermesCommand = "../../../node_modules/react-native/sdks/hermesc/%OS-BIN%/hermesc"
    //
    //   The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
    // hermesFlags = ["-O", "-output-source-map"]
}

/**
 * Set this to true to create four separate APKs instead of one,
 * one for each native architecture. This is useful if you don't
 * use App Bundles (https://developer.android.com/guide/app-bundle/)
 * and want to have separate APKs to upload to the Play Store.
 */
def enableSeparateBuildPerCPUArchitecture = false

/**
 * Set this to true to Run Proguard on Release builds to minify the Java bytecode.
 */
def enableProguardInReleaseBuilds = true

/**
 * The preferred build flavor of JavaScriptCore (JSC)
 *
 * For example, to use the international variant, you can use:
 * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
 *
 * The international variant includes ICU i18n library and necessary data
 * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
 * give correct results when using with locales other than en-US. Note that
 * this variant is about 6MiB larger per architecture than default.
 */
def jscFlavor = 'org.webkit:android-jsc:+'


/**
 * Private function to get the list of Native Architectures you want to build.
 * This reads the value from reactNativeArchitectures in your gradle.properties
 * file and works together with the --active-arch-only flag of react-native run-android.
 */
def reactNativeArchitectures() {
    def value = project.getProperties().get("reactNativeArchitectures")
    return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
}

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

android {
    ndkVersion rootProject.ext.ndkVersion

    compileSdkVersion rootProject.ext.compileSdkVersion

    namespace "fr.myapp.www"
    defaultConfig {
        applicationId "fr.myapp.www"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 1
        versionName "1.0"
        testBuildType System.getProperty('testBuildType', 'debug')
        testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
    }

    splits {
        abi {
            reset()
            enable enableSeparateBuildPerCPUArchitecture
            universalApk false  // If true, also generate a universal APK
            include (*reactNativeArchitectures())
        }
    }
    signingConfigs {
        debug {
            storeFile file('debug.keystore')
            storePassword 'android'
            keyAlias 'androiddebugkey'
            keyPassword 'android'
        }
        // RN TEMPLATE MODIFICATIONS - always to be able to sign our release app
        release {
            if (System.getenv("BITRISEIO_ANDROID_KEYSTORE_ALIAS")) {
                keyAlias System.getenv("BITRISEIO_ANDROID_KEYSTORE_ALIAS")
                keyPassword System.getenv("BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD")
                storeFile file("./release.keystore")
                storePassword System.getenv("BITRISEIO_ANDROID_KEYSTORE_PASSWORD")
                enableV3Signing true
            } else if (System.getenv("DETOX") || System.getenv("MYAPP_ANDROID_DEBUG")) {
                keyAlias 'androiddebugkey'
                keyPassword 'android'
                storeFile "${System.properties['user.home']}${File.separator}.android${File.separator}debug.keystore" as File
                storePassword 'android'
            } else {
              def out = services.get(StyledTextOutputFactory).create("warning-output")
              out.style(Style.Failure).text('[WARNING] No signing config is configured for the release build type, as neither BITRISEIO_ANDROID_KEYSTORE_ALIAS nor DETOX or MYAPP_ANDROID_DEBUG are set. This will result in a missing release variant in the Gradle tasks of this project. If you know what you are doing, you can set a MYAPP_ANDROID_DEBUG variable in your environment. See build.gradle.').println()
            }
        }
    }
    buildTypes {
        debug {
            signingConfig signingConfigs.debug
        }
        release {
            // Caution! In production, you need to generate your own keystore file.
            // see https://reactnative.dev/docs/signed-apk-android.
            signingConfig signingConfigs.release // RN TEMPLATE MODIFICATIONS - Signing
            minifyEnabled (enableProguardInReleaseBuilds && !System.getenv("DETOX")) // RN TEMPLATE MODIFICATIONS - Detox
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
            proguardFile "${rootProject.projectDir}/../../node_modules/detox/android/detox/proguard-rules-app.pro"
        }
    }

    flavorDimensions.add("env")
    productFlavors {
        // Environment dimension
        development {
            dimension "env"

            buildConfigField "boolean", "IS_PRODUCTION", "false"
            applicationIdSuffix ".dev"
            versionNameSuffix "-dev"
        }
        // Android does not allow flavors named or starting with "test"...
        e2e {
            dimension "env"

            buildConfigField "boolean", "IS_PRODUCTION", "false"
            applicationIdSuffix ".test"
            versionNameSuffix "-test"
        }
        staging {
            dimension "env"

            buildConfigField "boolean", "IS_PRODUCTION", "false"
            applicationIdSuffix ".staging"
            versionNameSuffix "-staging"
        }
        production {
            dimension "env"
        }
    }

    // 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
            // Example: versionCode 1 will generate 1001 for armeabi-v7a, 1002 for x86, etc.
            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 =
                        defaultConfig.versionCode * 1000 + versionCodes.get(abi)
            }

        }
    }
}

dependencies {
    // The version of react-native is set by the React Native Gradle Plugin
    implementation("com.facebook.react:react-android")

    implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.0.0")

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

    debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}")
    if (hermesEnabled.toBoolean()) {
        implementation("com.facebook.react:hermes-android")
    } else {
        implementation jscFlavor
    }

    implementation 'com.facebook.soloader:soloader:0.10.4+' // RN TEMPLATE MODIFICATIONS - upgrade soloader to fix Detox test
    // RN TEMPLATE MODIFICATIONS - additional deps
    androidTestImplementation('com.wix:detox:+') {
        // https://github.com/wix/Detox/issues/2848
        exclude group: 'com.google.android.material'
        transitive = true
    }
    androidTestImplementation 'junit:junit:4.12'
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation "androidx.annotation:annotation:1.1.0"
    implementation project(':@sentry_react-native')
}

apply from: file("../../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)```

@github-actions github-actions bot added Needs: Attention Issues where the author has responded to feedback. and removed Needs: Author Feedback labels Jun 6, 2023
@cortinico
Copy link
Contributor

Please comment out this line:

-     hermesCommand = "../../../node_modules/react-native/sdks/hermesc/%OS-BIN%/hermesc"
+  // hermesCommand = "../../../node_modules/react-native/sdks/hermesc/%OS-BIN%/hermesc"

You're specifying the default value and you don't need to do so (as most likely your project setup is different).

@cortinico cortinico added Needs: Author Feedback and removed Needs: Attention Issues where the author has responded to feedback. labels Jun 6, 2023
@yalakkademy
Copy link
Author

@cortinico I already tried this solution but when it comes to build I got this error :


FAILURE: Build completed with 2 failures.

1: Task failed with an exception.
-----------
* What went wrong:
Execution failed for task ':app:createBundleDevelopmentReleaseJsAndAssets'.
> Couldn't determine Hermesc location. Please set `react.hermesCommand` to the path of the hermesc binary file. node_modules/react-native/sdks/hermesc/%OS-BIN%/hermesc

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
==============================================================================

2: Task failed with an exception.
-----------
* What went wrong:
java.lang.StackOverflowError (no error message)

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
==============================================================================

@github-actions github-actions bot added Needs: Attention Issues where the author has responded to feedback. and removed Needs: Author Feedback labels Jun 6, 2023
@cortinico
Copy link
Contributor

The logic to detect where hermesc lives is here:

internal fun detectOSAwareHermesCommand(projectRoot: File, hermesCommand: String): String {
// 1. If the project specifies a Hermes command, don't second guess it.
if (hermesCommand.isNotBlank()) {
val osSpecificHermesCommand =
if ("%OS-BIN%" in hermesCommand) {
hermesCommand.replace("%OS-BIN%", getHermesOSBin())
} else {
hermesCommand
}
return osSpecificHermesCommand
// Execution on Windows fails with / as separator
.replace('/', File.separatorChar)
}
// 2. If the project is building hermes-engine from source, use hermesc from there
val builtHermesc =
getBuiltHermescFile(projectRoot, System.getenv("REACT_NATIVE_OVERRIDE_HERMES_DIR"))
if (builtHermesc.exists()) {
return builtHermesc.cliPath(projectRoot)
}
// 3. If the react-native contains a pre-built hermesc, use it.
val prebuiltHermesPath =
HERMESC_IN_REACT_NATIVE_DIR.plus(getHermesCBin())
.replace("%OS-BIN%", getHermesOSBin())
// Execution on Windows fails with / as separator
.replace('/', File.separatorChar)
val prebuiltHermes = File(projectRoot, prebuiltHermesPath)
if (prebuiltHermes.exists()) {
return prebuiltHermes.cliPath(projectRoot)
}
error(
"Couldn't determine Hermesc location. " +
"Please set `react.hermesCommand` to the path of the hermesc binary file. " +
"node_modules/react-native/sdks/hermesc/%OS-BIN%/hermesc")
}

The problem is that it seems like ./node_modules/react-native/sdks/hermesc/ is missing in your project. The content of that folder should be:

../../node_modules/react-native/sdks/hermesc/
├── linux64-bin
│   └── hermesc
├── osx-bin
│   └── hermesc
└── win64-bin
    ├── hermesc.exe
    ├── icudt64.dll
    ├── icuin64.dll
    ├── icuio64.dll
    ├── icutest64.dll
    ├── icutu64.dll
    ├── icuuc64.dll
    ├── msvcp140.dll
    ├── vcruntime140.dll
    └── vcruntime140_1.dll

Also this is really suspicious:

  npmPackages:
    @react-native-community/cli: Not Found
    react: Not Found
    react-native: Not Found
    react-native-macos: Not Found

from your react-native info, so it seems like you don't have node_modules/react-native or something similar.

@cortinico cortinico added Needs: Author Feedback and removed Needs: Attention Issues where the author has responded to feedback. labels Jun 6, 2023
@yalakkademy
Copy link
Author

yalakkademy commented Jun 6, 2023

@cortinico could it comes from nvm like iOS ? Where we need to specify nvm with brew to fix build phase issue ?

I think he don't find the react-native module because I'm in a mono-repo and the react native folder is at a parent node_modules folder from the project :

├── Project
│   └── node_module
        └── react-native
├── MYAPP
  └── android
    └── app
       └── build.gradle

@github-actions github-actions bot added Needs: Attention Issues where the author has responded to feedback. and removed Needs: Author Feedback labels Jun 6, 2023
@cortinico
Copy link
Contributor

could it comes from nvm like iOS ? Where we need to specify nvm with brew to fix build phase issue ?

nvm should not cause any issue.

I think he don't find the react-native module because I'm in a mono-repo and the react native folder is at a parent node_modules folder from the project :

Yup that's the issue. Then you need to specify the path to hermesc which is relative to your app root (which I believe is the MYAPP folder in your case) so:

hermesCommand = "../Project/node_modules/react-native/sdks/hermesc/%OS-BIN%/hermesc"

@cortinico cortinico added Needs: Author Feedback and removed Needs: Attention Issues where the author has responded to feedback. labels Jun 6, 2023
@yalakkademy
Copy link
Author

yalakkademy commented Jun 6, 2023

@cortinico we came back to the beginning of the issue then XD because it was what I make earlier

MyApp is in the Project folder that why I put the command like this
node_modules/react-native/sdks/hermesc/%OS-BIN%/hermesc

Also event in the Project folder when I test
npx react-native info

i also got this message

    @react-native-community/cli: Not Found
    react: Not Found
    react-native: Not Found
    react-native-macos: Not Found

And the react native folder in node module exist when I put this in my terminal into the android/app folder I got :

➜  app git:(caps-374) ✗ ../../../node_modules/react-native/sdks/hermesc/osx-bin/hermesc
Please choose output, e.g. -emit-binary. hermesc does not support -exec.
Example: hermesc -emit-binary -out myfile.hbc myfile.js

@github-actions github-actions bot added Needs: Attention Issues where the author has responded to feedback. and removed Needs: Author Feedback labels Jun 6, 2023
@cortinico
Copy link
Contributor

MyApp is in the Project folder that why I put the command like this

But that's not what you shared above in the previous comment:

├── Project
│   └── node_module
        └── react-native
├── MYAPP
  └── android
    └── app
       └── build.gradle

Can you clarify what's your folder structure?

@yalakkademy
Copy link
Author

@cortinico sorry yes :

├── Project
  └── package.json
  └── node_module
      └── react-native
  └──  MYAPP
    └── package.json
    └── node_module
    └── android
      └── app
        └── build.gradle

@cortinico
Copy link
Contributor

Ok so the path you should specify is relative to your root folder (which is MYAPPin your case). So it should be:

hermesCommand = "../node_modules/react-native/sdks/hermesc/%OS-BIN%/hermesc"

@cortinico cortinico added Needs: Author Feedback and removed Needs: Attention Issues where the author has responded to feedback. labels Jun 6, 2023
@yalakkademy
Copy link
Author

@cortinico thank you for your patience and your help, this was effectively a path relative to my root folder thank you

@github-actions github-actions bot added Needs: Attention Issues where the author has responded to feedback. and removed Needs: Author Feedback labels Jun 6, 2023
@cortinico
Copy link
Contributor

I'm glad I was helpful @yalakkademy

@SanjaySargam
Copy link

@cortinico I am also facing same issue.

@khushahal
Copy link

@cortinico I am facing the same issue in . 72 version

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs: Attention Issues where the author has responded to feedback. Platform: Android Android applications. Type: Upgrade Issue Issues reported from upgrade issue form
Projects
None yet
Development

No branches or pull requests

4 participants