Skip to content

Commit 076e6a1

Browse files
j-piaseckimeta-codesync[bot]
authored andcommitted
Use prebuilt Hermes by default when building Android (#54707)
Summary: Pull Request resolved: #54707 Changelog: [Internal] Reviewed By: cortinico Differential Revision: D87929652 fbshipit-source-id: 439eef5eea9b9203cf2a7b5a8eae38d83e192bd5
1 parent b9ac408 commit 076e6a1

9 files changed

Lines changed: 106 additions & 23 deletions

File tree

.github/actions/build-android/action.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,19 @@ runs:
4545
if [[ "${{ inputs.release-type }}" == "dry-run" ]]; then
4646
# dry-run: we only build ARM64 to save time/resources. For release/nightlies the default is to build all archs.
4747
export ORG_GRADLE_PROJECT_reactNativeArchitectures="arm64-v8a,x86" # x86 is required for E2E testing
48+
export HERMES_PREBUILT_FLAG="ORG_GRADLE_PROJECT_react.internal.useHermesNightly=true"
4849
TASKS="publishAllToMavenTempLocal build"
4950
elif [[ "${{ inputs.release-type }}" == "nightly" ]]; then
5051
# nightly: we set isSnapshot to true so artifacts are sent to the right repository on Maven Central.
5152
export ORG_GRADLE_PROJECT_isSnapshot="true"
53+
export HERMES_PREBUILT_FLAG="ORG_GRADLE_PROJECT_react.internal.useHermesNightly=true"
5254
TASKS="publishAllToMavenTempLocal publishAndroidToSonatype build"
5355
else
5456
# release: we want to build all archs (default)
57+
export HERMES_PREBUILT_FLAG="ORG_GRADLE_PROJECT_react.internal.useHermesStable=true"
5558
TASKS="publishAllToMavenTempLocal publishAndroidToSonatype build"
5659
fi
57-
./gradlew $TASKS -PenableWarningsAsErrors=true
60+
env "$HERMES_PREBUILT_FLAG" ./gradlew $TASKS -PenableWarningsAsErrors=true
5861
- name: Save Android ccache
5962
if: ${{ github.ref == 'refs/heads/main' || contains(github.ref, '-stable') }}
6063
uses: actions/cache/save@v5

build.gradle.kts

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,16 +109,43 @@ tasks.register("publishAllToMavenTempLocal") {
109109
tasks.register("publishAndroidToSonatype") {
110110
description = "Publish the Android artifacts to Sonatype (Maven Central or Snapshot repository)"
111111
dependsOn(":packages:react-native:ReactAndroid:publishToSonatype")
112-
dependsOn(":packages:react-native:ReactAndroid:hermes-engine:publishToSonatype")
113112
}
114113

115-
if (project.findProperty("react.internal.useHermesNightly")?.toString()?.toBoolean() == true) {
114+
var hermesSubstitution: Pair<String, String>? = null
115+
116+
if (project.findProperty("react.internal.useHermesStable")?.toString()?.toBoolean() == true) {
117+
val hermesVersions = java.util.Properties()
118+
val hermesVersionPropertiesFile =
119+
File("./packages/react-native/sdks/hermes-engine/version.properties")
120+
hermesVersionPropertiesFile.inputStream().use { hermesVersions.load(it) }
121+
val selectedHermesVersion = hermesVersions["HERMES_VERSION_NAME"] as String
122+
123+
hermesSubstitution = selectedHermesVersion to "Users opted to use stable hermes release"
124+
} else if (
125+
project.findProperty("react.internal.useHermesNightly")?.toString()?.toBoolean() == true
126+
) {
127+
val reactNativePackageJson = File("./packages/react-native/package.json")
128+
val reactNativePackageJsonContent = reactNativePackageJson.readText()
129+
val packageJson = groovy.json.JsonSlurper().parseText(reactNativePackageJsonContent) as Map<*, *>
130+
131+
val hermesCompilerVersion =
132+
(packageJson["dependencies"] as Map<*, *>)["hermes-compiler"] as String
133+
134+
if (hermesCompilerVersion == "0.0.0") {
135+
throw RuntimeException(
136+
"Trying to use Hermes Nightly but hermes-compiler version is not specified"
137+
)
138+
}
139+
140+
hermesSubstitution = "$hermesCompilerVersion-SNAPSHOT" to "Users opted to use hermes nightly"
141+
} else {
116142
logger.warn(
117143
"""
118144
********************************************************************************
119-
INFO: You're using Hermes from nightly as you set
145+
INFO: You're building Hermes from source as you set
120146
121-
react.internal.useHermesNightly=true
147+
react.internal.useHermesStable=false
148+
react.internal.useHermesNightly=false
122149
123150
in the ./gradle.properties file.
124151
@@ -127,12 +154,20 @@ if (project.findProperty("react.internal.useHermesNightly")?.toString()?.toBoole
127154
"""
128155
.trimIndent()
129156
)
157+
}
158+
159+
if (hermesSubstitution != null) {
160+
val (hermesVersion, reason) = hermesSubstitution!!
161+
project(":packages:react-native:ReactAndroid:hermes-engine") {
162+
tasks.configureEach { enabled = false }
163+
}
164+
130165
allprojects {
131166
configurations.all {
132167
resolutionStrategy.dependencySubstitution {
133168
substitute(project(":packages:react-native:ReactAndroid:hermes-engine"))
134-
.using(module("com.facebook.hermes:hermes-android:0.+"))
135-
.because("Users opted to use hermes from nightly")
169+
.using(module("com.facebook.hermes:hermes-android:$hermesVersion"))
170+
.because(reason)
136171
}
137172
}
138173
}

gradle.properties

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,14 @@ android.newDsl=false
1616
# ./gradlew <task> -PreactNativeArchitectures=x86_64
1717
reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
1818

19+
# Controls whether to use Hermes from stable builds. This will force hermes version
20+
# set in the sdks/hermes-engine/version.properties file to be used. This has a higher
21+
# priority than react.internal.useHermesNightly.
22+
react.internal.useHermesStable=false
23+
1924
# Controls whether to use Hermes from nightly builds. This will speed up builds
2025
# but should NOT be turned on for CI or release builds.
21-
react.internal.useHermesNightly=false
26+
react.internal.useHermesNightly=true
2227

2328
# Controls whether to use Hermes 1.0. Clean and rebuild when changing.
2429
hermesV1Enabled=false

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"lint-kotlin": "./gradlew ktfmtFormat",
2424
"lint-markdown": "markdownlint-cli2 2>&1",
2525
"lint": "eslint --max-warnings 0 .",
26+
"preinstall": "node ./scripts/try-set-nightly-hermes-compiler.js",
2627
"prettier": "prettier --write \"./**/*.{js,md,yml,ts,tsx}\"",
2728
"print-packages": "node ./scripts/monorepo/print",
2829
"shellcheck": "./.github/workflow-scripts/analyze_scripts.sh",

packages/gradle-plugin/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PropertyUtils.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ object PropertyUtils {
6565
*/
6666
const val INTERNAL_REACT_WINDOWS_BASH = "react.internal.windowsBashPath"
6767

68+
/**
69+
* Controls whether to use Hermes from stable builds. This will force hermes version set in the
70+
* sdks/hermes-engine/version.properties file to be used. This has a higher priority than
71+
* react.internal.useHermesNightly.
72+
*/
73+
const val INTERNAL_USE_HERMES_STABLE = "react.internal.useHermesStable"
74+
6875
/**
6976
* Internal property to force the build to use Hermes from the latest nightly. This speeds up the
7077
* build at the cost of not testing the latest integration against Hermes.

packages/react-native/ReactAndroid/hermes-engine/build.gradle.kts

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import de.undercouch.gradle.tasks.download.Download
1111
import org.apache.tools.ant.taskdefs.condition.Os
1212

1313
plugins {
14-
id("maven-publish")
1514
id("signing")
1615
alias(libs.plugins.android.library)
1716
alias(libs.plugins.download)
@@ -348,10 +347,7 @@ android {
348347
java.srcDirs("$hermesDir/lib/Platform/Intl/java", "$hermesDir/lib/Platform/Unicode/java")
349348
}
350349

351-
buildFeatures {
352-
prefab = true
353-
prefabPublishing = true
354-
}
350+
buildFeatures { prefab = true }
355351

356352
dependencies {
357353
implementation(libs.fbjni)
@@ -365,13 +361,6 @@ android {
365361
jniLibs.excludes.add("**/libfbjni.so")
366362
}
367363

368-
publishing {
369-
multipleVariants {
370-
withSourcesJar()
371-
allVariants()
372-
}
373-
}
374-
375364
prefab { create("hermesvm") { headers = prefabHeadersDir.absolutePath } }
376365
}
377366

packages/rn-tester/android/app/build.gradle.kts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,14 @@ react {
6161

6262
/* Hermes Commands */
6363
// The hermes compiler command to run. By default it is 'hermesc'
64-
hermesCommand = "$reactNativeDirPath/ReactAndroid/hermes-engine/build/hermes/bin/hermesc"
64+
hermesCommand =
65+
if (
66+
project.findProperty("react.internal.useHermesStable")?.toString()?.toBoolean() == true ||
67+
project.findProperty("react.internal.useHermesNightly")?.toString()?.toBoolean() ==
68+
true
69+
)
70+
"$rootDir/node_modules/hermes-compiler/hermesc/%OS-BIN%/hermesc"
71+
else "$reactNativeDirPath/ReactAndroid/hermes-engine/build/hermes/bin/hermesc"
6572

6673
autolinkLibrariesWithApp()
6774
}
@@ -179,8 +186,10 @@ tasks.withType<KotlinCompile>().configureEach {
179186

180187
afterEvaluate {
181188
if (
182-
project.findProperty("react.internal.useHermesNightly") == null ||
183-
project.findProperty("react.internal.useHermesNightly").toString() == "false"
189+
(project.findProperty("react.internal.useHermesNightly") == null ||
190+
project.findProperty("react.internal.useHermesNightly").toString() == "false") &&
191+
(project.findProperty("react.internal.useHermesStable") == null ||
192+
project.findProperty("react.internal.useHermesStable").toString() == "false")
184193
) {
185194
// As we're consuming Hermes from source, we want to make sure
186195
// `hermesc` is built before we actually invoke the `emit*HermesResource` task

private/react-native-fantom/build.gradle.kts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,17 @@ val prepareRNCodegen by
139139
into(codegenOutDir)
140140
}
141141

142+
val enableHermesBuild by
143+
tasks.registering {
144+
project(":packages:react-native:ReactAndroid:hermes-engine") {
145+
tasks.configureEach { enabled = true }
146+
}
147+
}
148+
142149
val prepareHermesDependencies by
143150
tasks.registering {
144151
dependsOn(
152+
enableHermesBuild,
145153
":packages:react-native:ReactAndroid:hermes-engine:buildHermesLib",
146154
":packages:react-native:ReactAndroid:hermes-engine:prepareHeadersForPrefab",
147155
)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
// @flow
9+
const { execSync } = require('child_process');
10+
const fs = require('fs');
11+
const path = require('path');
12+
13+
function main() {
14+
const packageJsonPath = path.join(__dirname, '../packages/react-native/package.json');
15+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
16+
const hermesCompilerVersion = packageJson.dependencies['hermes-compiler'];
17+
18+
if (hermesCompilerVersion === '0.0.0') {
19+
console.log(`Hermes compiler version not set. Updating to the latest nightly release.`);
20+
execSync('yarn workspace react-native add hermes-compiler@nightly --exact', { stdio: 'inherit' });
21+
} else {
22+
console.log(`Hermes compiler version set to ${hermesCompilerVersion}. Not setting nightly hermes.`);
23+
}
24+
}
25+
26+
main();

0 commit comments

Comments
 (0)