mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
RNGP - Various improvements needed for 3rd party libs (#35496)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/35496 This commit includes a series of fixes needed for better integration with libraries for 0.71: - I've added an `android/README.md` file as some libraries were failing the build if the folder was missing - RNGP now applies dep substitution on app and all the libraries project - RNGP now adds repositories on app and all the libraries project - I've removed the maven local repo to the `/android` folder as now is empty - I've fixed the path for the JSC repo for Windows users - I've added a bit of backward compat by re-adding an empty `project.react.ext` block that libraries might read from. - I've removed `codegenDir` from the `GenerateCodegenArtifactsTask` which was unused. Changelog: [Internal] [Changed] - RNGP - Various improvements needed for 3rd party libs Reviewed By: cipolleschi Differential Revision: D41549489 fbshipit-source-id: 2252da0180ac24fd3fe5a55300527da6781f0f8c
This commit is contained in:
1 parent
8b00b4f286
commit
f0972cb101
9 files changed
+220
-69
No files matched your search
+2
-1
@@ -64,7 +64,8 @@ buck-out
|
||||
.gradle
|
||||
local.properties
|
||||
*.iml
|
||||
/android/
|
||||
/android/*
|
||||
!/android/README.md
|
||||
|
||||
# Node
|
||||
node_modules
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# The `/android` folder inside `react-native`
|
||||
|
||||
Starting from React Native 0.71, we're not shipping the `/android` folder inside the React Native NPM package
|
||||
anymore due to sizing constraints on NPM. The Android artifacts are distributed via Maven Central.
|
||||
You can read more about it in this RFC:
|
||||
https://github.com/react-native-community/discussions-and-proposals/pull/508
|
||||
|
||||
If you're a library author and you're manipulating the React Native .aar files, to extract headers,
|
||||
extract `.so` files or do anything with it, you're probably doing something wrong. React Native
|
||||
0.71 ships with all the necessary logic to let you consume it transparently by just using:
|
||||
|
||||
```
|
||||
implementation("com.facebook.react:react-android")
|
||||
// or to keep backward compatibility with older versions of React Native:
|
||||
implementation("com.facebook.react:react-native:+")
|
||||
```
|
||||
|
||||
You should consider refactoring your library code not to unzip/manipulate the React Native .aar files.
|
||||
|
||||
This README.md file is kept in this folder as some libraries are checking the existence of the `/android` folder
|
||||
and failing user builds if the folder is missing.
|
||||
+2
-1
@@ -14,6 +14,7 @@ import com.facebook.react.tasks.GenerateCodegenArtifactsTask
|
||||
import com.facebook.react.tasks.GenerateCodegenSchemaTask
|
||||
import com.facebook.react.utils.AgpConfiguratorUtils.configureBuildConfigFields
|
||||
import com.facebook.react.utils.AgpConfiguratorUtils.configureDevPorts
|
||||
import com.facebook.react.utils.BackwardCompatUtils.configureBackwardCompatibilityReactMap
|
||||
import com.facebook.react.utils.DependencyUtils.configureDependencies
|
||||
import com.facebook.react.utils.DependencyUtils.configureRepositories
|
||||
import com.facebook.react.utils.DependencyUtils.readVersionString
|
||||
@@ -46,6 +47,7 @@ class ReactPlugin : Plugin<Project> {
|
||||
configureReactNativeNdk(project, extension)
|
||||
configureBuildConfigFields(project)
|
||||
configureDevPorts(project)
|
||||
configureBackwardCompatibilityReactMap(project)
|
||||
|
||||
project.extensions.getByType(AndroidComponentsExtension::class.java).apply {
|
||||
onVariants(selector().all()) { variant ->
|
||||
@@ -134,7 +136,6 @@ class ReactPlugin : Plugin<Project> {
|
||||
it.dependsOn(generateCodegenSchemaTask)
|
||||
it.reactNativeDir.set(extension.reactNativeDir)
|
||||
it.nodeExecutableAndArgs.set(extension.nodeExecutableAndArgs)
|
||||
it.codegenDir.set(extension.codegenDir)
|
||||
it.generatedSrcDir.set(generatedSrcDir)
|
||||
it.packageJsonFile.set(findPackageJsonFile(project, extension))
|
||||
it.codegenJavaPackageName.set(extension.codegenJavaPackageName)
|
||||
|
||||
-6
@@ -26,8 +26,6 @@ abstract class GenerateCodegenArtifactsTask : Exec() {
|
||||
|
||||
@get:Internal abstract val reactNativeDir: DirectoryProperty
|
||||
|
||||
@get:Internal abstract val codegenDir: DirectoryProperty
|
||||
|
||||
@get:Internal abstract val generatedSrcDir: DirectoryProperty
|
||||
|
||||
@get:InputFile abstract val packageJsonFile: RegularFileProperty
|
||||
@@ -38,10 +36,6 @@ abstract class GenerateCodegenArtifactsTask : Exec() {
|
||||
|
||||
@get:Input abstract val libraryName: Property<String>
|
||||
|
||||
@get:InputFile
|
||||
val combineJsToSchemaCli: Provider<RegularFile> =
|
||||
codegenDir.file("lib/cli/combine/combine-js-to-schema-cli.js")
|
||||
|
||||
@get:InputFile
|
||||
val generatedSchemaFile: Provider<RegularFile> = generatedSrcDir.file("schema.json")
|
||||
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.utils
|
||||
|
||||
import java.util.*
|
||||
import org.gradle.api.Project
|
||||
|
||||
internal object BackwardCompatUtils {
|
||||
|
||||
fun configureBackwardCompatibilityReactMap(project: Project) {
|
||||
if (project.extensions.extraProperties.has("react")) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val reactMap =
|
||||
project.extensions.extraProperties.get("react") as? Map<String, Any?> ?: mapOf()
|
||||
if (reactMap.isNotEmpty()) {
|
||||
project.logger.error(
|
||||
"""
|
||||
********************************************************************************
|
||||
|
||||
ERROR: Using old project.ext.react configuration.
|
||||
We identified that your project is using a old configuration block as:
|
||||
|
||||
project.ext.react = [
|
||||
// ...
|
||||
]
|
||||
|
||||
You should migrate to the new configuration:
|
||||
|
||||
react {
|
||||
// ...
|
||||
}
|
||||
You can find documentation inside `android/app/build.gradle` on how to use it.
|
||||
|
||||
********************************************************************************
|
||||
"""
|
||||
.trimIndent())
|
||||
}
|
||||
}
|
||||
|
||||
// We set an empty react[] map so if a library is reading it, they will find empty values.
|
||||
project.extensions.extraProperties.set("react", mapOf<String, String>())
|
||||
}
|
||||
}
|
||||
+43
-30
@@ -15,44 +15,57 @@ import org.gradle.api.artifacts.repositories.MavenArtifactRepository
|
||||
|
||||
internal object DependencyUtils {
|
||||
|
||||
/**
|
||||
* This method takes care of configuring the repositories{} block for both the app and all the 3rd
|
||||
* party libraries which are auto-linked.
|
||||
*/
|
||||
fun configureRepositories(project: Project, reactNativeDir: File) {
|
||||
with(project) {
|
||||
if (hasProperty("REACT_NATIVE_MAVEN_LOCAL_REPO")) {
|
||||
mavenRepoFromUrl("file://${property("REACT_NATIVE_MAVEN_LOCAL_REPO")}")
|
||||
project.rootProject.allprojects { eachProject ->
|
||||
with(eachProject) {
|
||||
if (hasProperty("REACT_NATIVE_MAVEN_LOCAL_REPO")) {
|
||||
mavenRepoFromUrl("file://${property("REACT_NATIVE_MAVEN_LOCAL_REPO")}")
|
||||
}
|
||||
// We add the snapshot for users on nightlies.
|
||||
mavenRepoFromUrl("https://oss.sonatype.org/content/repositories/snapshots/")
|
||||
repositories.mavenCentral()
|
||||
// Android JSC is installed from npm
|
||||
mavenRepoFromUrl(
|
||||
"file://${reactNativeDir}${File.separator}..${File.separator}jsc-android${File.separator}dist")
|
||||
repositories.google()
|
||||
mavenRepoFromUrl("https://www.jitpack.io")
|
||||
}
|
||||
// We add the snapshot for users on nightlies.
|
||||
mavenRepoFromUrl("https://oss.sonatype.org/content/repositories/snapshots/")
|
||||
repositories.mavenCentral()
|
||||
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
||||
mavenRepoFromUrl("file://${reactNativeDir}/android")
|
||||
// Android JSC is installed from npm
|
||||
mavenRepoFromUrl("file://${reactNativeDir}/../jsc-android/dist")
|
||||
repositories.google()
|
||||
mavenRepoFromUrl("https://www.jitpack.io")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method takes care of configuring the resolution strategy for both the app and all the 3rd
|
||||
* party libraries which are auto-linked. Specifically it takes care of:
|
||||
* - Forcing the react-android/hermes-android version to the one specified in the package.json
|
||||
* - Substituting `react-native` with `react-android` and `hermes-engine` with `hermes-android`.
|
||||
*/
|
||||
fun configureDependencies(project: Project, versionString: String) {
|
||||
if (versionString.isBlank()) return
|
||||
project.configurations.all { configuration ->
|
||||
// Here we set a dependencySubstitution for both react-native and hermes-engine as those
|
||||
// coordinates are voided due to https://github.com/facebook/react-native/issues/35210
|
||||
// This allows users to import libraries that are still using
|
||||
// implementation("com.facebook.react:react-native:+") and resolve the right dependency.
|
||||
configuration.resolutionStrategy.dependencySubstitution {
|
||||
it.substitute(it.module("com.facebook.react:react-native"))
|
||||
.using(it.module("com.facebook.react:react-android:${versionString}"))
|
||||
.because(
|
||||
"The react-native artifact was deprecated in favor of react-android due to https://github.com/facebook/react-native/issues/35210.")
|
||||
it.substitute(it.module("com.facebook.react:hermes-engine"))
|
||||
.using(it.module("com.facebook.react:hermes-android:${versionString}"))
|
||||
.because(
|
||||
"The hermes-engine artifact was deprecated in favor of hermes-android due to https://github.com/facebook/react-native/issues/35210.")
|
||||
project.rootProject.allprojects { eachProject ->
|
||||
eachProject.configurations.all { configuration ->
|
||||
// Here we set a dependencySubstitution for both react-native and hermes-engine as those
|
||||
// coordinates are voided due to https://github.com/facebook/react-native/issues/35210
|
||||
// This allows users to import libraries that are still using
|
||||
// implementation("com.facebook.react:react-native:+") and resolve the right dependency.
|
||||
configuration.resolutionStrategy.dependencySubstitution {
|
||||
it.substitute(it.module("com.facebook.react:react-native"))
|
||||
.using(it.module("com.facebook.react:react-android:${versionString}"))
|
||||
.because(
|
||||
"The react-native artifact was deprecated in favor of react-android due to https://github.com/facebook/react-native/issues/35210.")
|
||||
it.substitute(it.module("com.facebook.react:hermes-engine"))
|
||||
.using(it.module("com.facebook.react:hermes-android:${versionString}"))
|
||||
.because(
|
||||
"The hermes-engine artifact was deprecated in favor of hermes-android due to https://github.com/facebook/react-native/issues/35210.")
|
||||
}
|
||||
configuration.resolutionStrategy.force(
|
||||
"com.facebook.react:react-android:${versionString}",
|
||||
"com.facebook.react:hermes-android:${versionString}",
|
||||
)
|
||||
}
|
||||
configuration.resolutionStrategy.force(
|
||||
"com.facebook.react:react-android:${versionString}",
|
||||
"com.facebook.react:hermes-android:${versionString}",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-16
@@ -29,28 +29,16 @@ class GenerateCodegenArtifactsTaskTest {
|
||||
val codegenDir = tempFolder.newFolder("codegen")
|
||||
val outputDir = tempFolder.newFolder("output")
|
||||
|
||||
val task =
|
||||
createTestTask<GenerateCodegenArtifactsTask> {
|
||||
it.codegenDir.set(codegenDir)
|
||||
it.generatedSrcDir.set(outputDir)
|
||||
}
|
||||
val task = createTestTask<GenerateCodegenArtifactsTask> { it.generatedSrcDir.set(outputDir) }
|
||||
|
||||
assertEquals(
|
||||
File(codegenDir, "lib/cli/combine/combine-js-to-schema-cli.js"),
|
||||
task.combineJsToSchemaCli.get().asFile)
|
||||
assertEquals(File(outputDir, "schema.json"), task.generatedSchemaFile.get().asFile)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun generateCodegenSchema_outputFile_isSetCorrectly() {
|
||||
val codegenDir = tempFolder.newFolder("codegen")
|
||||
val outputDir = tempFolder.newFolder("output")
|
||||
|
||||
val task =
|
||||
createTestTask<GenerateCodegenArtifactsTask> {
|
||||
it.codegenDir.set(codegenDir)
|
||||
it.generatedSrcDir.set(outputDir)
|
||||
}
|
||||
val task = createTestTask<GenerateCodegenArtifactsTask> { it.generatedSrcDir.set(outputDir) }
|
||||
|
||||
assertEquals(File(outputDir, "java"), task.generatedJavaFiles.get().asFile)
|
||||
assertEquals(File(outputDir, "jni"), task.generatedJniFiles.get().asFile)
|
||||
@@ -80,13 +68,11 @@ class GenerateCodegenArtifactsTaskTest {
|
||||
@WithOs(OS.LINUX)
|
||||
fun setupCommandLine_willSetupCorrectly() {
|
||||
val reactNativeDir = tempFolder.newFolder("node_modules/react-native/")
|
||||
val codegenDir = tempFolder.newFolder("codegen")
|
||||
val outputDir = tempFolder.newFolder("output")
|
||||
|
||||
val task =
|
||||
createTestTask<GenerateCodegenArtifactsTask> {
|
||||
it.reactNativeDir.set(reactNativeDir)
|
||||
it.codegenDir.set(codegenDir)
|
||||
it.generatedSrcDir.set(outputDir)
|
||||
it.nodeExecutableAndArgs.set(listOf("--verbose"))
|
||||
}
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.utils
|
||||
|
||||
import com.facebook.react.tests.createProject
|
||||
import com.facebook.react.utils.BackwardCompatUtils.configureBackwardCompatibilityReactMap
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.TemporaryFolder
|
||||
|
||||
class BackwardCompatUtilsTest {
|
||||
|
||||
@get:Rule val tempFolder = TemporaryFolder()
|
||||
|
||||
@Test
|
||||
fun configureBackwardCompatibilityReactMap_addsEmptyReactMap() {
|
||||
val project = createProject()
|
||||
|
||||
configureBackwardCompatibilityReactMap(project)
|
||||
|
||||
assertTrue(project.extensions.extraProperties.has("react"))
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
assertTrue((project.extensions.extraProperties.get("react") as Map<String, Any?>).isEmpty())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun configureBackwardCompatibilityReactMap_withExistingMapSetByUser_wipesTheMap() {
|
||||
val project = createProject()
|
||||
project.extensions.extraProperties.set("react", mapOf("enableHermes" to true))
|
||||
|
||||
configureBackwardCompatibilityReactMap(project)
|
||||
|
||||
assertTrue(project.extensions.extraProperties.has("react"))
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
assertTrue((project.extensions.extraProperties.get("react") as Map<String, Any?>).isEmpty())
|
||||
}
|
||||
}
|
||||
+59
-15
@@ -14,6 +14,7 @@ import com.facebook.react.utils.DependencyUtils.mavenRepoFromUrl
|
||||
import com.facebook.react.utils.DependencyUtils.readVersionString
|
||||
import java.net.URI
|
||||
import org.gradle.api.artifacts.repositories.MavenArtifactRepository
|
||||
import org.gradle.testfixtures.ProjectBuilder
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
@@ -51,21 +52,6 @@ class DependencyUtilsTest {
|
||||
})
|
||||
}
|
||||
|
||||
@Test
|
||||
fun configureRepositories_containsReactNativeNpmLocalMavenRepo() {
|
||||
val projectFolder = tempFolder.newFolder()
|
||||
val reactNativeDir = tempFolder.newFolder("react-native")
|
||||
val repositoryURI = URI.create("file://${reactNativeDir}/android")
|
||||
val project = createProject(projectFolder)
|
||||
|
||||
configureRepositories(project, reactNativeDir)
|
||||
|
||||
assertNotNull(
|
||||
project.repositories.firstOrNull {
|
||||
it is MavenArtifactRepository && it.url == repositoryURI
|
||||
})
|
||||
}
|
||||
|
||||
@Test
|
||||
fun configureRepositories_containsJscLocalMavenRepo() {
|
||||
val projectFolder = tempFolder.newFolder()
|
||||
@@ -161,6 +147,46 @@ class DependencyUtilsTest {
|
||||
assertTrue(indexOfSnapshotRepo < indexOfMavenCentral)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun configureRepositories_appliesToAllProjects() {
|
||||
val repositoryURI = URI.create("https://repo.maven.apache.org/maven2/")
|
||||
val rootProject = ProjectBuilder.builder().build()
|
||||
val appProject = ProjectBuilder.builder().withName("app").withParent(rootProject).build()
|
||||
val libProject = ProjectBuilder.builder().withName("lib").withParent(rootProject).build()
|
||||
|
||||
configureRepositories(appProject, tempFolder.root)
|
||||
|
||||
assertNotNull(
|
||||
appProject.repositories.firstOrNull {
|
||||
it is MavenArtifactRepository && it.url == repositoryURI
|
||||
})
|
||||
assertNotNull(
|
||||
libProject.repositories.firstOrNull {
|
||||
it is MavenArtifactRepository && it.url == repositoryURI
|
||||
})
|
||||
}
|
||||
|
||||
@Test
|
||||
fun configureRepositories_withPreviousExclusionRulesOnMavenCentral_appliesCorrectly() {
|
||||
val repositoryURI = URI.create("https://repo.maven.apache.org/maven2/")
|
||||
val rootProject = ProjectBuilder.builder().build()
|
||||
val appProject = ProjectBuilder.builder().withName("app").withParent(rootProject).build()
|
||||
val libProject = ProjectBuilder.builder().withName("lib").withParent(rootProject).build()
|
||||
|
||||
// Let's emulate a library which set an `excludeGroup` on `com.facebook.react` for Central.
|
||||
libProject.repositories.mavenCentral { repo ->
|
||||
repo.content { content -> content.excludeGroup("com.facebook.react") }
|
||||
}
|
||||
|
||||
configureRepositories(appProject, tempFolder.root)
|
||||
|
||||
// We need to make sure we have Maven Central defined twice, one by the library,
|
||||
// and another is the override by RNGP.
|
||||
assertEquals(
|
||||
2,
|
||||
libProject.repositories.count { it is MavenArtifactRepository && it.url == repositoryURI })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun configureDependencies_withEmptyVersion_doesNothing() {
|
||||
val project = createProject()
|
||||
@@ -181,6 +207,24 @@ class DependencyUtilsTest {
|
||||
assertTrue(forcedModules.any { it.toString() == "com.facebook.react:hermes-android:1.2.3" })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun configureDependencies_withVersionString_appliesOnAllProjects() {
|
||||
val rootProject = ProjectBuilder.builder().build()
|
||||
val appProject = ProjectBuilder.builder().withName("app").withParent(rootProject).build()
|
||||
val libProject = ProjectBuilder.builder().withName("lib").withParent(rootProject).build()
|
||||
appProject.plugins.apply("com.android.application")
|
||||
libProject.plugins.apply("com.android.library")
|
||||
|
||||
configureDependencies(appProject, "1.2.3")
|
||||
|
||||
val appForcedModules = appProject.configurations.first().resolutionStrategy.forcedModules
|
||||
val libForcedModules = libProject.configurations.first().resolutionStrategy.forcedModules
|
||||
assertTrue(appForcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
|
||||
assertTrue(appForcedModules.any { it.toString() == "com.facebook.react:hermes-android:1.2.3" })
|
||||
assertTrue(libForcedModules.any { it.toString() == "com.facebook.react:react-android:1.2.3" })
|
||||
assertTrue(libForcedModules.any { it.toString() == "com.facebook.react:hermes-android:1.2.3" })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun readVersionString_withCorrectVersionString_returnsIt() {
|
||||
val propertiesFile =
|
||||
|
||||
Reference in new issue
Block a user