diff --git a/.changeset/salty-mugs-judge.md b/.changeset/salty-mugs-judge.md new file mode 100644 index 00000000..febf9381 --- /dev/null +++ b/.changeset/salty-mugs-judge.md @@ -0,0 +1,6 @@ +--- +'@react-native-node-api/test-app': patch +'react-native-node-api': patch +--- + +Improvements to setup scripts, updated docs diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 00000000..2bd5a0a9 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +22 diff --git a/README.md b/README.md index 34af256b..550d2acd 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,10 @@ See the document on ["how it works"](./docs/HOW-IT-WORKS.md) for a detailed description of what it's like to write native modules using this package. +### Quick start + +To get started, first install the dependencies with `npm i` and then build all packages using `npm run build`. + ## Packages This mono-repository hosts the development of a few packages: diff --git a/apps/test-app/android/settings.gradle b/apps/test-app/android/settings.gradle index 04d27aae..ec4aeb3e 100644 --- a/apps/test-app/android/settings.gradle +++ b/apps/test-app/android/settings.gradle @@ -19,3 +19,7 @@ apply(from: { throw new GradleException("Could not find `react-native-test-app`"); }()) applyTestAppSettings(settings) + +// customize the path to match your node_modules location +apply(from: "../../../node_modules/react-native-node-api/android/app-settings.gradle") +applyNodeAPISettings(settings) diff --git a/docs/ANDROID.md b/docs/ANDROID.md index d946cf29..4745d1bf 100644 --- a/docs/ANDROID.md +++ b/docs/ANDROID.md @@ -2,11 +2,32 @@ ## Building Hermes from source -Because we're using a version of Hermes patched with Node-API support, we need to build React Native from source. +### Step 1: `settings.gradle` +Gradle needs specific configuration to build React Native from source: dependency substitutions for React Native & Hermes modules, and modifications to default logic in RN build scripts, which is done by setting an environment variable, as described in this section. + +In your app's `settings.gradle` please include the below: + +```groovy +// customize the path to match your node_modules location +apply(from: "../../../node_modules/react-native-node-api/android/app-settings.gradle") +applyNodeAPISettings(settings) ``` -export REACT_NATIVE_OVERRIDE_HERMES_DIR=`npx react-native-node-api vendor-hermes --silent` + +### Step 2: script for adjusting environment variables + +> [!IMPORTANT] +> Each time you run Android Studio or build the Android app from a terminal, make sure the below is in place. + +Because we're using a version of Hermes patched with Node-API support, we need to build React Native from source. A special environment variable (`REACT_NATIVE_OVERRIDE_HERMES_DIR`) must be set to the path of a Hermes engine with Node-API support. Since Gradle does not support loading `.env` files directly, this must be automated by the consumer. We provide the `react-native-node-api vendor-hermes --silent` command, which will download Hermes and output the path to Hermes directory path as its only output. + +You can configure the environment variable using the following command: + ``` +export REACT_NATIVE_OVERRIDE_HERMES_DIR="$(npx react-native-node-api vendor-hermes --silent)" +``` + +This either needs to be done each time before Gradle / Android Studio invocation, or permanently in a shell init script such as `~/.zshrc` on Zsh (MacOS) or `~/.bashrc` on Bash (Linux). ## Cleaning your React Native build folders diff --git a/docs/IOS.md b/docs/IOS.md new file mode 100644 index 00000000..23bce4a9 --- /dev/null +++ b/docs/IOS.md @@ -0,0 +1,3 @@ +# iOS support + +Because we're using a version of Hermes patched with Node-API support, we need to build React Native from source. Special environment variables (`REACT_NATIVE_OVERRIDE_HERMES_DIR`, `BUILD_FROM_SOURCE`) must be set to the path of a Hermes engine with Node-API support. The podspec of the iOS Pod already includes instrumentation to configure React Native appropriately via [`patch-hermes.rb`](../packages/host/scripts/patch-hermes.rb). diff --git a/packages/host/android/app-settings.gradle b/packages/host/android/app-settings.gradle new file mode 100644 index 00000000..071727d4 --- /dev/null +++ b/packages/host/android/app-settings.gradle @@ -0,0 +1,22 @@ +import org.gradle.initialization.DefaultSettings + + +ext.applyNodeAPISettings = { DefaultSettings settings -> + def searchDirectory = rootDir.toPath() + do { + def p = searchDirectory.resolve("node_modules/react-native") + if (p.toFile().exists()) { + println "[Node-API] !!! PATCHING HERMES WITH NODE-API SUPPORT !!! Found React Native in ${p.toRealPath().toString()}" + + includeBuild(p.toRealPath().toString()) { + dependencySubstitution { + substitute(module("com.facebook.react:react-android")).using(project(":packages:react-native:ReactAndroid")) + substitute(module("com.facebook.react:react-native")).using(project(":packages:react-native:ReactAndroid")) + substitute(module("com.facebook.react:hermes-android")).using(project(":packages:react-native:ReactAndroid:hermes-engine")) + substitute(module("com.facebook.react:hermes-engine")).using(project(":packages:react-native:ReactAndroid:hermes-engine")) + } + } + break + } + } while (searchDirectory = searchDirectory.getParent()) +} diff --git a/packages/host/src/node/cli/hermes.ts b/packages/host/src/node/cli/hermes.ts index a7c875a5..869b2972 100644 --- a/packages/host/src/node/cli/hermes.ts +++ b/packages/host/src/node/cli/hermes.ts @@ -55,7 +55,7 @@ export const command = new Command("vendor-hermes") successText: "Removed existing Hermes clone", failText: (error) => `Failed to remove existing Hermes clone: ${error.message}`, - isEnabled: !silent, + isSilent: silent, } ); } @@ -84,7 +84,7 @@ export const command = new Command("vendor-hermes") successText: "Cloned custom Hermes", failText: (err) => `Failed to clone custom Hermes: ${err.message}`, - isEnabled: !silent, + isSilent: silent, } ); } catch (error) { @@ -117,7 +117,7 @@ export const command = new Command("vendor-hermes") successText: "Copied JSI from patched Hermes to React Native", failText: (err) => `Failed to copy JSI from Hermes to React Native: ${err.message}`, - isEnabled: !silent, + isSilent: silent, } ); console.log(hermesPath);