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

Build Hermes from Source #33396

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions .circleci/Dockerfiles/Dockerfile.android
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# and build a Android application that can be used to run the
# tests specified in the scripts/ directory.
#
FROM reactnativecommunity/react-native-android:5.2
FROM reactnativecommunity/react-native-android:5.4

LABEL Description="React Native Android Test Image"
LABEL maintainer="Héctor Ramos <hector@fb.com>"
Expand Down Expand Up @@ -53,6 +53,4 @@ ADD . /app

RUN yarn

RUN ./gradlew :ReactAndroid:downloadBoost :ReactAndroid:downloadDoubleConversion :ReactAndroid:downloadFolly :ReactAndroid:downloadGlog

RUN ./gradlew :ReactAndroid:packageReactNdkLibsForBuck -Pjobs=1
RUN ./gradlew :ReactAndroid:assembleDebug
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ executors:
reactnativeandroid:
<<: *defaults
docker:
- image: reactnativecommunity/react-native-android:5.2
- image: reactnativecommunity/react-native-android:5.4
resource_class: "large"
environment:
- TERM: "dumb"
Expand Down
47 changes: 20 additions & 27 deletions ReactAndroid/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ def boostPath = dependenciesPath ?: System.getenv("REACT_NATIVE_BOOST_PATH")
// Setup build type for NDK, supported values: {debug, release}
def nativeBuildType = System.getenv("NATIVE_BUILD_TYPE") ?: "release"

// We put the publishing version from gradle.properties inside ext. so other
// subprojects can access it as well.
ext.publishing_version = VERSION_NAME

task createNativeDepsDirectories {
downloadsDir.mkdirs()
thirdPartyNdkDir.mkdirs()
Expand Down Expand Up @@ -127,24 +131,6 @@ final def prepareLibevent = tasks.register("prepareLibevent", PrepareLibeventTas
it.outputDir.set(new File(thirdPartyNdkDir, "libevent"))
}

task prepareHermes(dependsOn: createNativeDepsDirectories, type: Copy) {
def hermesPackagePath = findNodeModulePath(projectDir, "hermes-engine")
if (!hermesPackagePath) {
throw new GradleScriptException("Could not find the hermes-engine npm package", null)
}

def hermesAAR = file("$hermesPackagePath/android/hermes-debug.aar")
if (!hermesAAR.exists()) {
throw new GradleScriptException("The hermes-engine npm package is missing \"android/hermes-debug.aar\"", null)
}

def soFiles = zipTree(hermesAAR).matching({ it.include "**/*.so" })

from soFiles
from "src/main/jni/first-party/hermes/Android.mk"
into "$thirdPartyNdkDir/hermes"
}

task downloadGlog(dependsOn: createNativeDepsDirectories, type: Download) {
src("https://github.com/google/glog/archive/v${GLOG_VERSION}.tar.gz")
onlyIfNewer(true)
Expand Down Expand Up @@ -259,18 +245,11 @@ final def extractNativeDependencies = tasks.register('extractNativeDependencies'
it.extractHeadersConfiguration.setFrom(configurations.extractHeaders)
it.extractJniConfiguration.setFrom(configurations.extractJNI)
it.baseOutputDir = project.file("src/main/jni/first-party/")
// Sadly this task as an output folder path that is directly dependent on
// the task input (i.e. src/main/jni/first-party/<package-name>/...
// This means that this task is using the parent folder (first-party/) as
// @OutputFolder. The `prepareHermes` task will also output inside that
// folder and if the two tasks happen to be inside the same run, we want
// `extractNativeDependencies` to run after `prepareHermes` to do not
// invalidate the input/output calculation for this task.
it.mustRunAfter(prepareHermes)
}

task installArchives {
dependsOn("publishReleasePublicationToNpmRepository")
dependsOn(":ReactAndroid:hermes-engine:installArchives")
}

// Creating sources with comments
Expand Down Expand Up @@ -314,6 +293,7 @@ android {
"REACT_COMMON_DIR=$projectDir/../ReactCommon",
"REACT_GENERATED_SRC_DIR=$buildDir/generated/source",
"REACT_SRC_DIR=$projectDir/src/main/java/com/facebook/react",
"APP_STL=c++_shared",
"-j${ndkBuildJobs()}"

if (Os.isFamily(Os.FAMILY_MAC)) {
Expand All @@ -333,7 +313,7 @@ android {
}
}

preBuild.dependsOn(prepareJSC, prepareHermes, prepareBoost, prepareDoubleConversion, prepareFmt, prepareFolly, prepareGlog, prepareLibevent, extractNativeDependencies)
preBuild.dependsOn(prepareJSC, prepareBoost, prepareDoubleConversion, prepareFmt, prepareFolly, prepareGlog, prepareLibevent, extractNativeDependencies)
preBuild.dependsOn("generateCodegenArtifactsFromSchema")

sourceSets.main {
Expand Down Expand Up @@ -366,6 +346,10 @@ android {
extractJNI
javadocDeps.extendsFrom api
}

buildFeatures {
prefab true
}
}

dependencies {
Expand All @@ -388,6 +372,15 @@ dependencies {
extractHeaders("com.facebook.fbjni:fbjni:0.2.2:headers")
extractJNI("com.facebook.fbjni:fbjni:0.2.2")

// It's up to the consumer to decide if hermes should be included or not.
// Therefore hermes-engine is a compileOnly dependency.
// Moreover, you can toggle where to get the dependency with `buildHermesFromSource`.
if (project.getProperties().getOrDefault("buildHermesFromSource", "false").toBoolean()) {
compileOnly(project(":ReactAndroid:hermes-engine"))
} else {
compileOnly("com.facebook.react:hermes-engine:${VERSION_NAME}")
}

javadocDeps("com.squareup:javapoet:1.13.0")

testImplementation("junit:junit:${JUNIT_VERSION}")
Expand Down
3 changes: 3 additions & 0 deletions ReactAndroid/hermes-engine/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Make sure we never publish the build folders to npm.
build/
.cxx/
36 changes: 33 additions & 3 deletions ReactAndroid/hermes-engine/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ if (hermesVersionFile.exists()) {
hermesVersion = hermesVersionFile.text
}
def ndkBuildJobs = Runtime.runtime.availableProcessors().toString()
def prefabHeadersDir = new File("$buildDir/prefab-headers")

// We inject the JSI directory used inside the Hermes build with the -DJSI_DIR config.
def jsiDir = rootProject.file("ReactCommon/jsi")
Expand All @@ -42,6 +43,10 @@ task downloadNdkBuildDependencies() {
dependsOn(downloadHermes)
}

task installArchives {
dependsOn("publishAllPublicationsToNpmRepository")
}

task unzipHermes(dependsOn: downloadHermes, type: Copy) {
from(tarTree(downloadHermes.dest)) {
eachFile { file ->
Expand All @@ -56,7 +61,7 @@ task unzipHermes(dependsOn: downloadHermes, type: Copy) {
}


task configureNinjaForHermes(dependsOn: unzipHermes, type: org.gradle.api.tasks.Exec) {
task configureNinjaForHermes(dependsOn: unzipHermes, type: Exec) {
workingDir(hermesDir)
commandLine(windowsAwareCommandLine(
"python3",
Expand All @@ -67,11 +72,19 @@ task configureNinjaForHermes(dependsOn: unzipHermes, type: org.gradle.api.tasks.
))
}

task buildNinjaForHermes(dependsOn: configureNinjaForHermes, type: org.gradle.api.tasks.Exec) {
task buildNinjaForHermes(dependsOn: configureNinjaForHermes, type: Exec) {
workingDir(hermesDir)
commandLine(windowsAwareCommandLine("cmake", "--build", "./ninja_build", "--target", "hermesc", "-j", ndkBuildJobs))
}

task prepareHeadersForPrefab(dependsOn: unzipHermes, type: Copy) {
from("$hermesDir/API")
from("$hermesDir/public")
include("**/*.h")
exclude("jsi/**")
into(prefabHeadersDir)
}

static def windowsAwareCommandLine(String... commands) {
def newCommands = []
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
Expand All @@ -88,6 +101,7 @@ def reactNativeArchitectures() {

android {
compileSdkVersion 31
buildToolsVersion = "31.0.0"

// Used to override the NDK path & version on internal CI
if (System.getenv("ANDROID_NDK") != null && System.getenv("LOCAL_ANDROID_NDK_VERSION") != null) {
Expand Down Expand Up @@ -180,12 +194,28 @@ android {
allVariants()
}
}

buildFeatures {
prefabPublishing true
}

prefab {
libhermes {
headers prefabHeadersDir.absolutePath
libraryName "libhermes"
}
}
}

afterEvaluate {
preBuild.dependsOn(buildNinjaForHermes)
preBuild.dependsOn(prepareHeadersForPrefab)
// Needed as some of the native sources needs to be downloaded
// before configureCMakeRelease/configureCMakeMinSizeRel could be executed.
reactNativeArchitectures().each { architecture ->
tasks.named("configureCMakeMinSizeRel[${architecture}]") { dependsOn(preBuild) }
tasks.named("configureCMakeRelease[${architecture}]") { dependsOn(preBuild) }
}
configureCMakeRelease.dependsOn(preBuild)
configureCMakeMinSizeRel.dependsOn(preBuild)

Expand All @@ -206,4 +236,4 @@ afterEvaluate {
}

group = "com.facebook.react"
version = VERSION_NAME
version = parent.publishing_version
3 changes: 1 addition & 2 deletions ReactAndroid/hermes-engine/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
VERSION_NAME=1000.0.0-main
android.disableAutomaticComponentCreation=true
android.disableAutomaticComponentCreation=true
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@
LOCAL_PATH := $(call my-dir)
REACT_NATIVE := $(LOCAL_PATH)/../../../../../../../..

include $(REACT_NATIVE)/ReactCommon/common.mk
include $(CLEAR_VARS)

LOCAL_MODULE := jsijniprofiler

LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp)

LOCAL_C_INCLUDES := $(LOCAL_PATH) $(REACT_NATIVE)/ReactCommon/jsi $(call find-node-module,$(LOCAL_PATH),hermes-engine)/android/include
LOCAL_C_INCLUDES := $(LOCAL_PATH) $(REACT_NATIVE)/ReactCommon/jsi

LOCAL_CPP_FEATURES := exceptions

Expand All @@ -29,5 +28,3 @@ LOCAL_SHARED_LIBRARIES := \

include $(BUILD_SHARED_LIBRARY)


include $(CLEAR_VARS)
Original file line number Diff line number Diff line change
Expand Up @@ -6,47 +6,47 @@
LOCAL_PATH := $(call my-dir)
REACT_NATIVE := $(LOCAL_PATH)/../../../../../../../..

include $(REACT_NATIVE)/ReactCommon/common.mk
include $(CLEAR_VARS)
ifeq ($(APP_OPTIM),debug)
include $(CLEAR_VARS)

LOCAL_MODULE := hermes-executor-release
LOCAL_MODULE := hermes-executor-debug
LOCAL_CFLAGS := -DHERMES_ENABLE_DEBUGGER=1

LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp)

LOCAL_C_INCLUDES := $(LOCAL_PATH) $(REACT_NATIVE)/ReactCommon/jsi $(call find-node-module,$(LOCAL_PATH),hermes-engine)/android/include
LOCAL_C_INCLUDES := $(LOCAL_PATH) $(REACT_NATIVE)/ReactCommon/jsi

LOCAL_CPP_FEATURES := exceptions
LOCAL_CPP_FEATURES := exceptions

LOCAL_STATIC_LIBRARIES := libjsireact libhermes-executor-common-release
LOCAL_SHARED_LIBRARIES := \
libfb \
libfbjni \
libfolly_json \
libhermes \
libjsi \
libreactnativejni
LOCAL_STATIC_LIBRARIES := libjsireact libhermes-executor-common-debug
LOCAL_SHARED_LIBRARIES := \
libfb \
libfbjni \
libfolly_json \
libhermes \
libjsi \
libreactnativejni

include $(BUILD_SHARED_LIBRARY)
include $(BUILD_SHARED_LIBRARY)
else
include $(CLEAR_VARS)

LOCAL_MODULE := hermes-executor-release

include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp)

LOCAL_MODULE := hermes-executor-debug
LOCAL_CFLAGS := -DHERMES_ENABLE_DEBUGGER=1
LOCAL_C_INCLUDES := $(LOCAL_PATH) $(REACT_NATIVE)/ReactCommon/jsi

LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp)
LOCAL_CPP_FEATURES := exceptions

LOCAL_C_INCLUDES := $(LOCAL_PATH) $(REACT_NATIVE)/ReactCommon/jsi $(call find-node-module,$(LOCAL_PATH),hermes-engine)/android/include
LOCAL_STATIC_LIBRARIES := libjsireact libhermes-executor-common-release
LOCAL_SHARED_LIBRARIES := \
libfb \
libfbjni \
libfolly_json \
libhermes \
libjsi \
libreactnativejni

LOCAL_CPP_FEATURES := exceptions

LOCAL_STATIC_LIBRARIES := libjsireact libhermes-executor-common-debug
LOCAL_SHARED_LIBRARIES := \
libfb \
libfbjni \
libfolly_json \
libhermes \
libjsi \
libreactnativejni

include $(BUILD_SHARED_LIBRARY)
include $(BUILD_SHARED_LIBRARY)
endif
10 changes: 0 additions & 10 deletions ReactAndroid/src/main/jni/first-party/hermes/Android.mk

This file was deleted.

9 changes: 8 additions & 1 deletion ReactAndroid/src/main/jni/react/jni/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,18 @@ $(call import-module,jsiexecutor)
$(call import-module,logger)
$(call import-module,callinvoker)
$(call import-module,reactperflogger)
$(call import-module,hermes)
$(call import-module,runtimeexecutor)
$(call import-module,react/renderer/runtimescheduler)
$(call import-module,react/nativemodule/core)

# This block is needed only because we build the project on NDK r17 internally.
ifneq ($(call ndk-major-at-least,21),true)
$(call import-add-path,$(NDK_GRADLE_INJECTED_IMPORT_PATH))
endif

$(call import-module,prefab/hermes-engine)


include $(REACT_SRC_DIR)/reactperflogger/jni/Android.mk
# TODO (T48588859): Restructure this target to align with dir structure: "react/nativemodule/..."
# Note: Update this only when ready to minimize breaking changes.
Expand Down
29 changes: 0 additions & 29 deletions ReactCommon/common.mk

This file was deleted.

Loading