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

Upgrade ERN to support RN 0.72 #1906

Merged
merged 4 commits into from
Jul 26, 2024
Merged
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
2 changes: 1 addition & 1 deletion docs/cli/create-container.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
- Optional extra configuration specific to creating container
- Override some ios or android container generation configuration by passing `androidConfig` and/or `iosConfig` attributes
- **As a json string**
For example `--extra '{"androidConfig": {"androidGradlePlugin": "3.2.1","buildToolsVersion": "28.0.3","compileSdkVersion": "28","gradleDistributionVersion": "4.6","minSdkVersion": "19","sourceCompatibility": "VERSION_1_8","supportLibraryVersion": "28.0.0","targetCompatibility": "VERSION_1_8","targetSdkVersion": "28"}}'`
For example `--extra '{"androidConfig": {"androidGradlePlugin": "3.2.1","rnGradlePlugin": "0.0.6","buildToolsVersion": "28.0.3","compileSdkVersion": "28","gradleDistributionVersion": "4.6","minSdkVersion": "19","sourceCompatibility": "VERSION_1_8","supportLibraryVersion": "28.0.0","targetCompatibility": "VERSION_1_8","targetSdkVersion": "28"}}'`
Find more information on [android configuration]

or
Expand Down
2 changes: 1 addition & 1 deletion docs/cli/run-android.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
- Optional extra configuration specific to local container and runner
- Override the Android build config during local container generation and runner project by passing `androidConfig` attributes
- **As a json string**
For example `--extra '{"androidConfig": {"androidGradlePlugin": "3.2.1","buildToolsVersion": "28.0.3","compileSdkVersion": "28","gradleDistributionVersion": "4.6","minSdkVersion": "19","sourceCompatibility": "VERSION_1_8","supportLibraryVersion": "28.0.0","targetCompatibility": "VERSION_1_8","targetSdkVersion": "28"}}'`
For example `--extra '{"androidConfig": {"androidGradlePlugin": "3.2.1","rnGradlePlugin": "0.0.6","buildToolsVersion": "28.0.3","compileSdkVersion": "28","gradleDistributionVersion": "4.6","minSdkVersion": "19","sourceCompatibility": "VERSION_1_8","supportLibraryVersion": "28.0.0","targetCompatibility": "VERSION_1_8","targetSdkVersion": "28"}}'`
Find more information on [android configuration]
- **As a file path**
For example `--extra /home/user/my-container-config.json`
Expand Down
141 changes: 1 addition & 140 deletions ern-container-gen-android/src/AndroidGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ export default class AndroidGenerator implements ContainerGenerator {
): Promise<ContainerGenResult> {
return generateContainer(config, {
fillContainerHull: this.fillContainerHull.bind(this),
postBundle: this.postBundle.bind(this),
});
}

Expand Down Expand Up @@ -351,7 +350,7 @@ You should replace "${annotationProcessorPrefix}:${dependency}" with "annotation
mustacheView.customPermissions = _.uniq(mustacheView.customPermissions);

androidDependencies.raw.push(
`api 'com.walmartlabs.ern:react-native:${versions.reactNativeAarVersion}'`,
`api 'com.walmartlabs.ern:react-android:${versions.reactNativeAarVersion}'`,
);

if (isKotlinEnabled) {
Expand Down Expand Up @@ -450,44 +449,6 @@ You should replace "${annotationProcessorPrefix}:${dependency}" with "annotation
for (const perform of replacements) {
perform();
}

if (semver.gte(reactNativePlugin.version, '0.60.0')) {
this.getJavaScriptEngine(config) === JavaScriptEngine.JSC
? await kax
.task('Injecting JavaScript engine [JavaScriptCore]')
.run(
this.injectJavaScriptCoreEngine(
config,
reactNativePlugin.version,
),
)
: await kax
.task('Injecting JavaScript engine [Hermes]')
.run(this.injectHermesEngine(config, reactNativePlugin.version));
}
}

public async postBundle(
config: ContainerGeneratorConfig,
bundle: BundlingResult,
reactNativeVersion: string,
) {
if (this.getJavaScriptEngine(config) === JavaScriptEngine.HERMES) {
const hermesVersion =
config.androidConfig.hermesVersion ||
android.getDefaultHermesVersion(reactNativeVersion);
const hermesCli = await kax
.task(`Installing hermes-engine@${hermesVersion}`)
.run(HermesCli.fromVersion(hermesVersion));
await kax.task('Compiling JS bundle to Hermes bytecode').run(
hermesCli.compileReleaseBundle({
bundleSourceMapPath: bundle.sourceMapPath,
compositePath: config.composite.path,
jsBundlePath: bundle.bundlePath,
}),
);
bundle.isHermesBundle = true;
}
}

public getJavaScriptEngine(
Expand All @@ -502,106 +463,6 @@ You should replace "${annotationProcessorPrefix}:${dependency}" with "annotation
: JavaScriptEngine.JSC;
}

/**
* Starting with React Native 0.60.0, JavaScriptCore engine is distributed
* separately from React Native and comes in two variants :
* 'android-jsc' and 'android-jsc-intl'.
*
* More details@ https://github.com/react-native-community/jsc-android-buildscript
*
* Prior to React Native 0.60.0, the 'libjsc.so' native library files were
* shipped inside React Native AAR itself. This is not the case anymore.
* The 'libjsc.so' files are now distributed in the 'jsc-android' npm package,
* inside an aar library.
*
* This function retrieve the 'jsc-android' package and unzip the AAR
* matching the desired JSC variant ('android-jsc' or 'android-jsc-intl').
* It then copy the 'libjsc.so' files to the 'jniLibs' directory of the
* Container. This way, the JSC engine is shipped within the Container and
* applications won't crash at runtime when trying to load this library.
*/
public async injectJavaScriptCoreEngine(
config: ContainerGeneratorConfig,
reactNativeVersion: string,
) {
let jscVersion =
config?.androidConfig?.jscVersion ??
android.getDefaultJSCVersion(reactNativeVersion);
if (/^\d+$/.test(jscVersion)) {
// For backward compatibility, to avoid breaking clients
// that are already providing a version through config that
// only specifies major excluding minor/patch
jscVersion = `${jscVersion}.0.0`;
}
const jscVariant =
config?.androidConfig?.jscVariant ?? android.DEFAULT_JSC_VARIANT;
const workingDir = createTmpDir();
try {
shell.pushd(workingDir);
await yarn.init();
await yarn.add(PackagePath.fromString(`jsc-android@${jscVersion}`));
const versionMajor = semver.major(semver.coerce(jscVersion)!.version);
const jscVersionPath = path.resolve(
`./node_modules/jsc-android/dist/org/webkit/${jscVariant}/r${versionMajor}`,
);
const jscAARPath = path.join(
jscVersionPath,
`${jscVariant}-r${versionMajor}.aar`,
);

return new Promise<void>((resolve) => {
const unzipOutDir = createTmpDir();
const zip = new AdmZip(jscAARPath);
zip.extractAllTo(unzipOutDir);
const unzippedJniPath = path.join(unzipOutDir, 'jni');
const containerJniLibsPath = path.join(
config.outDir,
'lib/src/main/jniLibs',
);
shell.cp('-Rf', unzippedJniPath, containerJniLibsPath);
resolve();
});
} finally {
shell.popd();
}
}

/**
* Inject hermes engine into the Container
* Done in a similar way as injectJavaScriptCoreEngine method
*/
public async injectHermesEngine(
config: ContainerGeneratorConfig,
reactNativeVersion: string,
) {
const hermesVersion =
config?.androidConfig?.hermesVersion ??
android.getDefaultHermesVersion(reactNativeVersion);
const workingDir = createTmpDir();
try {
shell.pushd(workingDir);
await yarn.init();
await yarn.add(PackagePath.fromString(`hermes-engine@${hermesVersion}`));
const hermesAarPath = path.resolve(
`./node_modules/hermes-engine/android/hermes-release.aar`,
);
return new Promise<void>((resolve) => {
const unzipOutDir = createTmpDir();
const zip = new AdmZip(hermesAarPath);
zip.extractAllTo(unzipOutDir);
const unzippedJniPath = path.join(unzipOutDir, 'jni');
const containerJniLibsPath = path.join(
config.outDir,
'lib/src/main/jniLibs',
);
shell.cp('-Rf', unzippedJniPath, containerJniLibsPath);
resolve();
});
} finally {
shell.popd();
}
}

public buildImplementationStatements(
dependencies: AndroidDependencies,
androidVersions: AndroidResolvedVersions,
Expand Down
22 changes: 21 additions & 1 deletion ern-container-gen-android/src/hull/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m
org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m

# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
Expand All @@ -22,3 +23,22 @@ org.gradle.jvmargs=-Xmx1536m
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true

# Version of flipper SDK to use with React Native
FLIPPER_VERSION=0.182.0

# Use this property to specify which architecture you want to build.
# You can also override it from the CLI using
# ./gradlew <task> -PreactNativeArchitectures=x86_64
reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64

# Use this property to enable support to the new architecture.
# This will allow you to use TurboModules and the Fabric render in
# your application. You should enable this flag either if you want
# to write custom TurboModules/Fabric components OR use libraries that
# are providing them.
newArchEnabled=false

# Use this property to enable or disable the Hermes JS engine.
# If set to false, you will be using JSC instead.
hermesEnabled=true
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-all.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
18 changes: 14 additions & 4 deletions ern-container-gen-android/src/hull/gradlew
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
Expand All @@ -80,10 +80,10 @@ do
esac
done

APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit

APP_NAME="Gradle"
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
Expand Down Expand Up @@ -143,12 +143,16 @@ fi
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
Expand Down Expand Up @@ -205,6 +209,12 @@ set -- \
org.gradle.wrapper.GradleWrapperMain \
"$@"

# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi

# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
Expand Down
15 changes: 9 additions & 6 deletions ern-container-gen-android/src/hull/gradlew.bat
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
@rem limitations under the License.
@rem

@if "%DEBUG%" == "" @echo off
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
Expand All @@ -25,7 +25,8 @@
if "%OS%"=="Windows_NT" setlocal

set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

Expand All @@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
if %ERRORLEVEL% equ 0 goto execute

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Expand Down Expand Up @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
if %ERRORLEVEL% equ 0 goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%

:mainEnd
if "%OS%"=="Windows_NT" endlocal
Expand Down
6 changes: 4 additions & 2 deletions ern-container-gen-ios/src/IosGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -388,12 +388,14 @@ Make sure to run these commands before building the container.`,
}

public async addReactNativeCodegen(targetDir: string, version: string) {
log.debug('Adding react-native-codegen package');
log.debug('Adding @react-native/codegen package');
const tmpDir = createTmpDir();
shell.pushd(tmpDir);
try {
await yarn.init();
await yarn.add(PackagePath.fromString(`react-native-codegen@${version}`));
await yarn.add(
PackagePath.fromString(`@react-native/codegen@${version}`),
);
// mkdirp and invariant are also needed
await yarn.add(PackagePath.fromString('mkdirp'));
await yarn.add(PackagePath.fromString('invariant'));
Expand Down
38 changes: 0 additions & 38 deletions ern-core/src/MiniApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,44 +245,6 @@ You can find instructions to install CocoaPods @ https://cocoapods.org`);

const miniAppPath = path.join(process.cwd(), miniAppName);

// For RN > 0.57
// Write custom metro.config.js to make sure that packager does not crash
// on Windows while building the Runner.
// Do not write this file if creating a MiniApp from a project template
// as the template might contain a custom metro.config.js file.
// This is the responsibility of the template project owner to add
// resolver blacklisted paths.
// See https://github.com/facebook/react-native/issues/9136#issuecomment-348773574
if (semver.gt(reactNativeVersion, '0.57.0') && !template) {
await fs.writeFile(
path.join(miniAppPath, 'metro.config.js'),
`const blacklist = require('${getMetroBlacklistPath(
reactNativeVersion,
)}');
module.exports = {
resolver: {
blacklistRE: blacklist([
// Ignore IntelliJ directories
/.*\\.idea\\/.*/,
// ignore git directories
/.*\\.git\\/.*/,
// Ignore android directories
/.*\\/app\\/build\\/.*/,
]),
},
transformer: {
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: false,
},
}),
},
};
`,
);
}

// Remove react-native generated android and ios projects
// They will be replaced with our owns when user uses `ern run android`
// or `ern run ios` command
Expand Down
Loading