@callstack/react-native-brownfield 4.0.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/gradle-plugin/brownfield/config/detekt/detekt.yml +1 -1
  2. package/gradle-plugin/brownfield/gradle.properties +1 -1
  3. package/gradle-plugin/brownfield/gradlew +0 -0
  4. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/expo/utils/LocalMavenUtils.kt +2 -5
  5. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/ProjectConfigurations.kt +3 -5
  6. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt +21 -26
  7. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNSourceSets.kt +23 -35
  8. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/AssetTaskProcessor.kt +4 -16
  9. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ExplodeTaskProvider.kt +6 -7
  10. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/JNILibsProcessor.kt +133 -108
  11. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ManifestTaskProcessor.kt +25 -61
  12. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/MergeProcessor.kt +7 -29
  13. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ProguardProcessor.kt +9 -46
  14. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ResourceTaskProcessor.kt +4 -13
  15. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantHelper.kt +52 -47
  16. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt +31 -63
  17. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/BundleTaskProvider.kt +72 -27
  18. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/Constants.kt +0 -1
  19. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ExplodeAarTask.kt +2 -20
  20. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/Logging.kt +1 -1
  21. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/MergeClassesTask.kt +70 -0
  22. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/MergeLibraryManifestTask.kt +178 -0
  23. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/AndroidArchiveLibrary.kt +0 -4
  24. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/DirectoryManager.kt +0 -5
  25. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/Extension.kt +8 -9
  26. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/Utils.kt +2 -34
  27. package/lib/commonjs/expo-config-plugin/android/utils/constants.js +1 -1
  28. package/lib/commonjs/expo-config-plugin/android/utils/formatHelpers.js +2 -0
  29. package/lib/commonjs/expo-config-plugin/android/utils/formatHelpers.js.map +1 -0
  30. package/lib/commonjs/expo-config-plugin/android/utils/gradleHelpers.js +1 -1
  31. package/lib/commonjs/expo-config-plugin/android/utils/gradleHelpers.js.map +1 -1
  32. package/lib/commonjs/expo-config-plugin/android/withAndroidModuleFiles.js +1 -1
  33. package/lib/commonjs/expo-config-plugin/android/withAndroidModuleFiles.js.map +1 -1
  34. package/lib/commonjs/expo-config-plugin/android/withBrownfieldAndroid.js +1 -1
  35. package/lib/commonjs/expo-config-plugin/android/withBrownfieldAndroid.js.map +1 -1
  36. package/lib/commonjs/expo-config-plugin/template/android/build.gradle.kts +6 -0
  37. package/lib/commonjs/scripts/brownfield.js +0 -0
  38. package/lib/module/expo-config-plugin/android/utils/constants.js +1 -1
  39. package/lib/module/expo-config-plugin/android/utils/formatHelpers.js +2 -0
  40. package/lib/module/expo-config-plugin/android/utils/formatHelpers.js.map +1 -0
  41. package/lib/module/expo-config-plugin/android/utils/gradleHelpers.js +1 -1
  42. package/lib/module/expo-config-plugin/android/utils/gradleHelpers.js.map +1 -1
  43. package/lib/module/expo-config-plugin/android/withAndroidModuleFiles.js +1 -1
  44. package/lib/module/expo-config-plugin/android/withAndroidModuleFiles.js.map +1 -1
  45. package/lib/module/expo-config-plugin/android/withBrownfieldAndroid.js +1 -1
  46. package/lib/module/expo-config-plugin/android/withBrownfieldAndroid.js.map +1 -1
  47. package/lib/module/expo-config-plugin/template/android/build.gradle.kts +6 -0
  48. package/lib/typescript/commonjs/src/expo-config-plugin/android/utils/constants.d.ts +2 -2
  49. package/lib/typescript/commonjs/src/expo-config-plugin/android/utils/formatHelpers.d.ts +2 -0
  50. package/lib/typescript/commonjs/src/expo-config-plugin/android/utils/formatHelpers.d.ts.map +1 -0
  51. package/lib/typescript/commonjs/src/expo-config-plugin/android/utils/gradleHelpers.d.ts +7 -0
  52. package/lib/typescript/commonjs/src/expo-config-plugin/android/utils/gradleHelpers.d.ts.map +1 -1
  53. package/lib/typescript/commonjs/src/expo-config-plugin/android/withAndroidModuleFiles.d.ts.map +1 -1
  54. package/lib/typescript/commonjs/src/expo-config-plugin/android/withBrownfieldAndroid.d.ts.map +1 -1
  55. package/lib/typescript/commonjs/src/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.d.ts +5 -0
  56. package/lib/typescript/commonjs/src/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.d.ts.map +1 -1
  57. package/lib/typescript/module/src/expo-config-plugin/android/utils/constants.d.ts +2 -2
  58. package/lib/typescript/module/src/expo-config-plugin/android/utils/formatHelpers.d.ts +2 -0
  59. package/lib/typescript/module/src/expo-config-plugin/android/utils/formatHelpers.d.ts.map +1 -0
  60. package/lib/typescript/module/src/expo-config-plugin/android/utils/gradleHelpers.d.ts +7 -0
  61. package/lib/typescript/module/src/expo-config-plugin/android/utils/gradleHelpers.d.ts.map +1 -1
  62. package/lib/typescript/module/src/expo-config-plugin/android/withAndroidModuleFiles.d.ts.map +1 -1
  63. package/lib/typescript/module/src/expo-config-plugin/android/withBrownfieldAndroid.d.ts.map +1 -1
  64. package/lib/typescript/module/src/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.d.ts +5 -0
  65. package/lib/typescript/module/src/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.d.ts.map +1 -1
  66. package/package.json +3 -3
  67. package/src/expo-config-plugin/android/utils/constants.ts +1 -1
  68. package/src/expo-config-plugin/android/utils/formatHelpers.ts +7 -0
  69. package/src/expo-config-plugin/android/utils/gradleHelpers.ts +41 -0
  70. package/src/expo-config-plugin/android/withAndroidModuleFiles.ts +20 -0
  71. package/src/expo-config-plugin/android/withBrownfieldAndroid.ts +16 -3
  72. package/src/expo-config-plugin/template/android/build.gradle.kts +6 -0
  73. package/src/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.ts +6 -0
  74. package/CHANGELOG.md +0 -300
@@ -844,7 +844,7 @@ style:
844
844
  ignoredCharacters: []
845
845
  ThrowsCount:
846
846
  active: true
847
- max: 2
847
+ max: 3
848
848
  excludeGuardClauses: false
849
849
  TrailingWhitespace:
850
850
  active: false
@@ -1,6 +1,6 @@
1
1
  PROJECT_ID=com.callstack.react.brownfield
2
2
  ARTIFACT_ID=brownfield-gradle-plugin
3
- VERSION=2.0.0-alpha05
3
+ VERSION=2.0.0-alpha07
4
4
  GROUP=com.callstack.react
5
5
  IMPLEMENTATION_CLASS=com.callstack.react.brownfield.plugin.RNBrownfieldPlugin
6
6
 
File without changes
@@ -1,6 +1,6 @@
1
1
  package com.callstack.react.brownfield.expo.utils
2
2
 
3
- import com.android.build.gradle.LibraryExtension
3
+ import com.android.build.api.dsl.LibraryExtension
4
4
  import org.gradle.api.Project
5
5
  import java.io.File
6
6
 
@@ -68,10 +68,7 @@ object LocalMavenUtils {
68
68
  BrownfieldPublishingInfo(
69
69
  groupId = groupId,
70
70
  artifactId = artifactId,
71
- version = (
72
- targetProjectAndroidLibExt.defaultConfig.versionName
73
- ?: targetProject.version.toString()
74
- ),
71
+ version = targetProject.version.toString(),
75
72
  )
76
73
  )
77
74
  }
@@ -1,7 +1,7 @@
1
1
  package com.callstack.react.brownfield.plugin
2
2
 
3
+ import com.android.build.api.dsl.LibraryExtension
3
4
  import com.android.build.api.variant.LibraryAndroidComponentsExtension
4
- import com.android.build.gradle.LibraryExtension
5
5
  import com.callstack.react.brownfield.shared.Logging
6
6
  import com.callstack.react.brownfield.utils.capitalized
7
7
  import org.gradle.api.Project
@@ -70,7 +70,6 @@ class ProjectConfigurations(private val project: Project) {
70
70
  val configuration = project.configurations.create(configName)
71
71
 
72
72
  configuration.extendsFrom(project.configurations.getByName("implementation"))
73
- configuration.isVisible = false
74
73
  configuration.isTransitive = false
75
74
 
76
75
  val androidComponents = project.extensions.getByType(LibraryAndroidComponentsExtension::class.java)
@@ -96,9 +95,8 @@ class ProjectConfigurations(private val project: Project) {
96
95
  from: AttributeContainer,
97
96
  into: AttributeContainer,
98
97
  ) {
99
- val value: T? = from.getAttribute(key)
100
- if (value != null) {
101
- into.attribute(key, value)
98
+ from.getAttribute(key)?.let {
99
+ into.attribute(key, it)
102
100
  }
103
101
  }
104
102
 
@@ -1,7 +1,7 @@
1
1
  package com.callstack.react.brownfield.plugin
2
2
 
3
- import com.android.build.gradle.LibraryExtension
4
- import com.android.build.gradle.api.LibraryVariant
3
+ import com.android.build.api.variant.LibraryAndroidComponentsExtension
4
+ import com.android.build.api.variant.LibraryVariant
5
5
  import com.callstack.react.brownfield.artifacts.ArtifactsResolver
6
6
  import com.callstack.react.brownfield.expo.ExpoPublishingHelper
7
7
  import com.callstack.react.brownfield.expo.utils.ExpoGradleProjectProjection
@@ -11,6 +11,7 @@ import com.callstack.react.brownfield.processors.JNILibsProcessor
11
11
  import com.callstack.react.brownfield.processors.ManifestTaskProcessor
12
12
  import com.callstack.react.brownfield.processors.ProguardProcessor
13
13
  import com.callstack.react.brownfield.processors.ResourceTaskProcessor
14
+ import com.callstack.react.brownfield.processors.VariantHelper
14
15
  import com.callstack.react.brownfield.processors.VariantPackagesProperty
15
16
  import com.callstack.react.brownfield.processors.VariantTaskProvider
16
17
  import com.callstack.react.brownfield.shared.BaseProject
@@ -21,6 +22,7 @@ import com.callstack.react.brownfield.utils.AndroidArchiveLibrary
21
22
  import com.callstack.react.brownfield.utils.DirectoryManager
22
23
  import com.callstack.react.brownfield.utils.Extension
23
24
  import com.callstack.react.brownfield.utils.Utils
25
+ import com.callstack.react.brownfield.utils.capitalized
24
26
  import org.gradle.api.Plugin
25
27
  import org.gradle.api.Project
26
28
  import org.gradle.api.ProjectConfigurationException
@@ -65,11 +67,14 @@ class RNBrownfieldPlugin : Plugin<Project> {
65
67
 
66
68
  val variantTaskProvider = VariantTaskProvider(project)
67
69
 
68
- /**
69
- * Configure Tasks
70
- */
71
- project.extensions.getByType(LibraryExtension::class.java).libraryVariants.all { variant ->
70
+ val androidComponents = project.extensions.getByType(LibraryAndroidComponentsExtension::class.java)
71
+ androidComponents.onVariants { variant ->
72
72
  configureTasks(variant, artifacts, variantTaskProvider)
73
+
74
+ val aarLibraries = getAarLibraries(artifacts, variant.name)
75
+ ManifestTaskProcessor.process(variant, project, aarLibraries)
76
+ AssetTaskProcessor.process(variant, aarLibraries)
77
+ ResourceTaskProcessor.process(variant, aarLibraries)
73
78
  }
74
79
  }
75
80
 
@@ -124,48 +129,38 @@ class RNBrownfieldPlugin : Plugin<Project> {
124
129
  variantTaskProvider: VariantTaskProvider,
125
130
  ) {
126
131
  val variantName = variant.name
127
- val capitalizedVariantName = variantName.replaceFirstChar(Char::titlecase)
132
+ val capitalizedVariantName = variantName.capitalized()
128
133
 
129
134
  /** ======= EXPLODE AAR =========*/
130
135
  val explodeTask = ExplodeTaskProvider.getTask(variant, project, artifacts)
131
136
 
132
137
  /** ======= Pre<Variant>Build =========*/
133
138
  variantTaskProvider.preBuildTaskByVariant(
134
- variantName,
135
- variant.buildType.name,
136
- variant.buildType.isDebuggable,
139
+ variant,
137
140
  explodeTask,
138
141
  )
139
142
 
140
143
  val aarLibraries = getAarLibraries(artifacts, variantName)
141
144
 
145
+ /** ======= MERGE CLASSES =========*/
146
+ val mergeClassesTask = variantTaskProvider.mergeClasses(aarLibraries, explodeTask, variantName)
147
+ VariantHelper.getAsmTransformTask(project, capitalizedVariantName).configureEach {
148
+ it.dependsOn(mergeClassesTask)
149
+ }
150
+
142
151
  /**
143
152
  * Flat IDs to be put into the variant property, required for RClass Transformer
144
153
  */
145
154
  val packageIDs = aarLibraries.map { it.getPackageName() }
146
155
  VariantPackagesProperty.getVariantPackagesProperty().put(variantName, packageIDs)
147
156
 
148
- /** ======= MANIFEST MERGER =========*/
149
- ManifestTaskProcessor.process(variant, project, aarLibraries)
150
-
151
- /** ======= GENERATE RESOURCES =========*/
152
- ResourceTaskProcessor.process(variant, project, aarLibraries)
153
-
154
- /** ======= GENERATE ASSETS ========= */
155
- AssetTaskProcessor.process(variant, project, aarLibraries)
156
-
157
157
  /** ===== jniLibsProcessor ===== */
158
158
  val jniLibsProcessor = JNILibsProcessor(project)
159
- jniLibsProcessor.processJniLibs(aarLibraries, variantName)
159
+ jniLibsProcessor.processJniLibs(aarLibraries, variant)
160
160
 
161
161
  /** ===== proguardProcessor ===== */
162
162
  val proguardProcessor = ProguardProcessor(project)
163
163
  val proguardRules = aarLibraries.map { it.getProguardRules() }
164
- proguardProcessor.processConsumerFiles(proguardRules, capitalizedVariantName)
165
- proguardProcessor.processGeneratedFiles(proguardRules, capitalizedVariantName)
166
-
167
- /** ===== processDataBinding ===== */
168
- val bundleTask = variantTaskProvider.bundleTaskProvider(project, variantName)
169
- variantTaskProvider.processDataBinding(bundleTask, aarLibraries, variantName)
164
+ proguardProcessor.processFiles(proguardRules, variantName.capitalized(), explodeTask)
170
165
  }
171
166
  }
@@ -1,8 +1,9 @@
1
1
  package com.callstack.react.brownfield.plugin
2
2
 
3
+ import com.android.build.api.dsl.LibraryExtension
3
4
  import com.android.build.api.variant.LibraryAndroidComponentsExtension
4
- import com.android.build.gradle.LibraryExtension
5
5
  import com.callstack.react.brownfield.exceptions.NameSpaceNotFound
6
+ import com.callstack.react.brownfield.processors.VariantHelper
6
7
  import com.callstack.react.brownfield.utils.Extension
7
8
  import com.callstack.react.brownfield.utils.Utils
8
9
  import com.callstack.react.brownfield.utils.capitalized
@@ -42,14 +43,14 @@ object RNSourceSets {
42
43
  // Move the non-variant-specific configuration out of the loop
43
44
  androidExtension.sourceSets.named("main") { sourceSet ->
44
45
  // This path is not variant-specific, so it's added once here.
45
- sourceSet.java.srcDir("${getModuleBuildDir()}/generated/autolinking/src/main/java")
46
+ sourceSet.java.directories.add("${getModuleBuildDir()}/generated/autolinking/src/main/java")
46
47
  }
47
48
 
48
- // 2. Use the onVariants block to configure each variant
49
+ // 2. Use the onVariants block to wire RN bundle outputs via the Variant Sources API
49
50
  componentsExtension.onVariants { variant ->
50
51
  val variantName = variant.name
51
52
  val bundledAssetsVariantName =
52
- Utils.getBundledAssetsVariantName(
53
+ VariantHelper.getBundledAssetsVariantName(
53
54
  variantName = variantName,
54
55
  buildTypeName = variant.buildType,
55
56
  isDebuggable = variant.debuggable,
@@ -57,37 +58,24 @@ object RNSourceSets {
57
58
  val capitalizedBundledAssetsVariantName = bundledAssetsVariantName.capitalized()
58
59
  val appProject = getAppProject()
59
60
 
60
- // 3. Lazily configure the 'variant-specific' source set using .named()
61
- androidExtension.sourceSets.named(variantName) { sourceSet ->
62
- val bundlePathSegments =
63
- listOf(
64
- // outputs for RN <= 0.81
65
- "createBundle${capitalizedBundledAssetsVariantName}JsAndAssets",
66
- // outputs for RN >= 0.82
67
- "react/$bundledAssetsVariantName",
68
- )
69
- val updateResourcesPathSegment = Utils.getExpoUpdatesResourcesTaskName(variant.name)
70
-
71
- val appBuildDir = getAppBuildDir()
72
- sourceSet.assets.srcDirs(bundlePathSegments.map { "$appBuildDir/generated/assets/$it" })
73
- sourceSet.res.srcDirs(bundlePathSegments.map { "$appBuildDir/generated/res/$it" })
74
- if (extension.useStrippedSoFiles) {
75
- val capitalizedVariantName = variantName.capitalized()
76
- val libsDir = project.layout.projectDirectory.dir("libs$capitalizedVariantName")
77
- val copyTaskName = "copy${capitalizedVariantName}LibSources"
78
- sourceSet.jniLibs.srcDir(
79
- project.files(libsDir).builtBy(copyTaskName),
80
- )
81
- }
82
- if (Utils.hasExpoUpdates(appProject, variant.name)) {
83
- val updateResourcesTask = appProject.tasks.named(updateResourcesPathSegment)
84
- sourceSet.assets.srcDir(
85
- project.files("$appBuildDir/generated/assets/$updateResourcesPathSegment").builtBy(updateResourcesTask),
86
- )
87
- sourceSet.res.srcDir(
88
- project.files("$appBuildDir/generated/res/$updateResourcesPathSegment").builtBy(updateResourcesTask),
89
- )
90
- }
61
+ val bundlePathSegments =
62
+ listOf(
63
+ // outputs for RN <= 0.81
64
+ "createBundle${capitalizedBundledAssetsVariantName}JsAndAssets",
65
+ // outputs for RN >= 0.82
66
+ "react/$bundledAssetsVariantName",
67
+ )
68
+
69
+ val appBuildDir = getAppBuildDir()
70
+ bundlePathSegments.forEach { segment ->
71
+ variant.sources.assets?.addStaticSourceDirectory("$appBuildDir/generated/assets/$segment")
72
+ variant.sources.res?.addStaticSourceDirectory("$appBuildDir/generated/res/$segment")
73
+ }
74
+
75
+ if (Utils.hasExpoUpdates(appProject, variantName)) {
76
+ val updateResourcesPathSegment = VariantHelper.getExpoUpdatesResourcesTaskName(variant.name)
77
+ variant.sources.assets?.addStaticSourceDirectory("$appBuildDir/generated/assets/$updateResourcesPathSegment")
78
+ variant.sources.res?.addStaticSourceDirectory("$appBuildDir/generated/res/$updateResourcesPathSegment")
91
79
  }
92
80
  }
93
81
  }
@@ -1,29 +1,17 @@
1
1
  package com.callstack.react.brownfield.processors
2
2
 
3
- import com.android.build.gradle.LibraryExtension
4
- import com.android.build.gradle.api.LibraryVariant
3
+ import com.android.build.api.variant.LibraryVariant
5
4
  import com.callstack.react.brownfield.utils.AndroidArchiveLibrary
6
- import org.gradle.api.Project
7
5
 
8
6
  object AssetTaskProcessor {
9
7
  fun process(
10
8
  variant: LibraryVariant,
11
- project: Project,
12
9
  aarLibraries: List<AndroidArchiveLibrary>,
13
10
  ) {
14
- val assetsTask = variant.mergeAssetsProvider.get()
11
+ val assetDirectories = aarLibraries.map { it.getAssetsDir() }.filter { it.exists() }
15
12
 
16
- val androidExtension = project.extensions.getByName("android") as LibraryExtension
17
- assetsTask.doFirst {
18
- val filteredSourceSets =
19
- androidExtension.sourceSets.filter { it.name == variant.name }
20
-
21
- filteredSourceSets.forEach { sourceSet ->
22
- val filteredAarLibs = aarLibraries.filter { it.getAssetsDir().exists() }
23
- if (!filteredAarLibs.isEmpty()) {
24
- sourceSet.assets.srcDirs(filteredAarLibs.map { it.getAssetsDir() })
25
- }
26
- }
13
+ assetDirectories.forEach { assetDirectory ->
14
+ variant.sources.assets?.addStaticSourceDirectory(assetDirectory.path)
27
15
  }
28
16
  }
29
17
  }
@@ -1,9 +1,10 @@
1
1
  package com.callstack.react.brownfield.processors
2
2
 
3
- import com.android.build.gradle.api.LibraryVariant
3
+ import com.android.build.api.variant.LibraryVariant
4
4
  import com.callstack.react.brownfield.shared.BundleTaskProvider
5
5
  import com.callstack.react.brownfield.shared.ExplodeAarTask
6
6
  import com.callstack.react.brownfield.shared.UnresolvedArtifactInfo
7
+ import com.callstack.react.brownfield.utils.Extension
7
8
  import com.callstack.react.brownfield.utils.capitalized
8
9
  import org.gradle.api.Project
9
10
  import org.gradle.api.Task
@@ -20,25 +21,23 @@ object ExplodeTaskProvider {
20
21
  val variantTaskProvider = VariantTaskProvider(project)
21
22
  val bundleProvider = BundleTaskProvider(variantTaskProvider)
22
23
  val capitalizedVariantName = variant.name.capitalized()
24
+ val projectExt = project.extensions.getByType(Extension::class.java)
23
25
 
24
26
  return project.tasks.register(
25
27
  "explode${capitalizedVariantName}Aar",
26
28
  ExplodeAarTask::class.java,
27
29
  ) { task ->
28
30
  task.variantName.set(variant.name)
29
- task.minifyEnabled.set(variant.buildType.isMinifyEnabled)
30
31
 
31
32
  val finalArtifacts = mutableListOf<UnresolvedArtifactInfo>()
32
33
  artifacts.forEach { art ->
33
34
  var artifactPath = art.file
34
35
  if (art.isExpoPublishDependency != true) {
35
- val defaultTaskName = "bundle${capitalizedVariantName}Aar"
36
36
  val dependencyProject = project.project(":${art.moduleName}")
37
- val bundleTaskProvider = bundleProvider.getBundleTask(dependencyProject, variant)
38
- val taskName = bundleTaskProvider?.name ?: defaultTaskName
39
-
37
+ val bundleTaskProvider = bundleProvider.getBundleTask(dependencyProject, variant, projectExt.missingDimensionStrategies)
38
+ val taskName = bundleTaskProvider.name
40
39
  dependencyProject.tasks.findByName(taskName)?.let { task.dependsOn(it) }
41
- artifactPath = createArtifactFile(bundleTaskProvider?.get() as Task).absolutePath
40
+ artifactPath = createArtifactFile(bundleTaskProvider.get()).absolutePath
42
41
  }
43
42
 
44
43
  finalArtifacts.add(
@@ -1,142 +1,134 @@
1
1
  package com.callstack.react.brownfield.processors
2
2
 
3
- import com.android.build.gradle.LibraryExtension
4
- import com.callstack.react.brownfield.exceptions.TaskNotFound
3
+ import com.android.build.api.variant.LibraryVariant
5
4
  import com.callstack.react.brownfield.shared.Logging
6
5
  import com.callstack.react.brownfield.utils.AndroidArchiveLibrary
7
6
  import com.callstack.react.brownfield.utils.Extension
8
7
  import com.callstack.react.brownfield.utils.capitalized
8
+ import org.gradle.api.DefaultTask
9
9
  import org.gradle.api.Project
10
- import org.gradle.api.tasks.Copy
11
- import org.gradle.api.tasks.TaskProvider
10
+ import org.gradle.api.file.ConfigurableFileCollection
11
+ import org.gradle.api.file.DirectoryProperty
12
+ import org.gradle.api.provider.Property
13
+ import org.gradle.api.tasks.CacheableTask
14
+ import org.gradle.api.tasks.Input
15
+ import org.gradle.api.tasks.InputDirectory
16
+ import org.gradle.api.tasks.InputFiles
17
+ import org.gradle.api.tasks.Optional
18
+ import org.gradle.api.tasks.OutputDirectory
19
+ import org.gradle.api.tasks.PathSensitive
20
+ import org.gradle.api.tasks.PathSensitivity
21
+ import org.gradle.api.tasks.TaskAction
12
22
  import java.io.File
13
-
14
- class JNILibsProcessor(val project: Project) {
15
- fun processJniLibs(
16
- aarLibraries: Collection<AndroidArchiveLibrary>,
17
- variantName: String,
18
- ) {
19
- val capitalizedVariantName = variantName.capitalized()
20
- val taskName = "merge${capitalizedVariantName}JniLibFolders"
21
- val mergeJniLibsTask = project.tasks.named(taskName)
22
-
23
- if (!mergeJniLibsTask.isPresent) {
24
- throw TaskNotFound("Task $taskName not found")
25
- }
26
-
27
- val androidExtension = project.extensions.getByName("android") as LibraryExtension
28
- copySoLibsTask(variantName)
29
-
30
- mergeJniLibsTask.configure {
31
- it.doFirst {
32
- val projectExt = project.extensions.getByType(Extension::class.java)
33
- val existingJNILibs =
34
- listOf("arm64-v8a", "armeabi-v7a", "x86_64", "x86")
35
- .associateWith { mutableListOf<String>() }
36
- .toMutableMap()
37
- for (archiveLibrary in aarLibraries) {
38
- val jniDir = archiveLibrary.getJniDir()
39
- processNestedLibs(jniDir.listFiles(), existingJNILibs)
40
- if (!projectExt.useStrippedSoFiles) {
41
- if (jniDir.exists()) {
42
- val filteredSourceSets =
43
- androidExtension.sourceSets.filter { sourceSet -> sourceSet.name == variantName }
44
- filteredSourceSets.forEach { sourceSet ->
45
- sourceSet.jniLibs.srcDir(
46
- jniDir,
47
- )
48
- }
49
- }
50
- }
51
- }
52
- if (projectExt.useStrippedSoFiles) {
53
- copyStrippedSoLibs(variantName, existingJNILibs)
23
+ import kotlin.collections.component1
24
+ import kotlin.collections.component2
25
+
26
+ /**
27
+ * Below contains a list of dynamic libs which we should not embed
28
+ * with the AAR as they are provided by the Gradle when AAR is
29
+ * consumed by the host App.
30
+ */
31
+ val IGNORE_EMBEDDED_LIBS =
32
+ listOf(
33
+ "libc++_shared.so", "libfbjni.so", "libhermestooling.so",
34
+ "libhermesvm.so", "libimagepipeline.so", "libjsi.so",
35
+ "libnative-filters.so", "libnative-imagetranscoder.so",
36
+ "libreactnative.so",
37
+ )
38
+
39
+ @CacheableTask
40
+ abstract class ProcessAndCopyJniLibsTask : DefaultTask() {
41
+ @get:InputFiles
42
+ @get:PathSensitive(PathSensitivity.RELATIVE)
43
+ abstract val aarJniDirs: ConfigurableFileCollection
44
+
45
+ @get:InputDirectory
46
+ @get:Optional
47
+ @get:PathSensitive(PathSensitivity.RELATIVE)
48
+ abstract val strippedLibsDir: DirectoryProperty
49
+
50
+ @get:Input
51
+ abstract val useStrippedSoFiles: Property<Boolean>
52
+
53
+ @get:OutputDirectory
54
+ abstract val outputDirectory: DirectoryProperty
55
+
56
+ @TaskAction
57
+ fun execute() {
58
+ val outDir = outputDirectory.get().asFile
59
+ // Clear out old data to ensure clean, reproducible builds
60
+ outDir.deleteRecursively()
61
+ outDir.mkdirs()
62
+
63
+ val existingJNILibs =
64
+ listOf("arm64-v8a", "armeabi-v7a", "x86_64", "x86")
65
+ .associateWith { mutableListOf<String>() }
66
+ .toMutableMap()
67
+
68
+ // 1. Scan and process duplicate libs from AAR paths
69
+ aarJniDirs.forEach { jniDir ->
70
+ if (jniDir.exists()) {
71
+ processNestedLibs(jniDir.listFiles(), existingJNILibs)
72
+
73
+ // If not using stripped files, copy the unstripped ones directly to our output
74
+ if (!useStrippedSoFiles.get()) {
75
+ jniDir.copyRecursively(outDir, overwrite = true)
54
76
  }
55
77
  }
56
78
  }
57
- }
58
-
59
- private fun getStrippedLibsPath(variantName: String): Pair<File, File> {
60
- val projectExt = project.extensions.getByType(Extension::class.java)
61
- val appProject = project.rootProject.project(projectExt.appProjectName)
62
- val appBuildDir = appProject.layout.buildDirectory.get()
63
-
64
- val capitalizedVariant = variantName.capitalized()
65
-
66
- val fromDir =
67
- appBuildDir
68
- .dir("intermediates/stripped_native_libs/$variantName/strip${capitalizedVariant}DebugSymbols/out/lib")
69
- .asFile
70
-
71
- val intoDir = project.rootProject.file("${project.name}/libs$capitalizedVariant")
72
-
73
- return Pair(fromDir, intoDir)
74
- }
75
-
76
- private fun copySoLibsTask(variantName: String): TaskProvider<Copy> {
77
- val capitalizedVariant = variantName.capitalized()
78
- val projectExt = project.extensions.getByType(Extension::class.java)
79
- val appProject = project.rootProject.project(projectExt.appProjectName)
80
-
81
- val stripTask = ":${appProject.name}:strip${capitalizedVariant}DebugSymbols"
82
- val codegenTask = ":${project.name}:generateCodegenSchemaFromJavaScript"
83
79
 
84
- val (fromDir, intoDir) = getStrippedLibsPath(variantName)
85
-
86
- return project.tasks.register("copy${capitalizedVariant}LibSources", Copy::class.java) {
87
- it.dependsOn(stripTask, codegenTask)
88
- it.from(fromDir)
89
- it.into(intoDir)
90
-
91
- it.include("**/libappmodules.so", "**/libreact_codegen_*.so")
92
- projectExt.dynamicLibs.forEach { lib -> it.include("**/$lib") }
80
+ // 2. If using stripped files, copy targeted files from the stripped directory
81
+ if (useStrippedSoFiles.get() && strippedLibsDir.isPresent) {
82
+ copyStrippedSoLibs(outDir, existingJNILibs)
93
83
  }
94
84
  }
95
85
 
96
86
  private fun copyStrippedSoLibs(
97
- variantName: String,
87
+ outDir: File,
98
88
  existingJNILibs: MutableMap<String, MutableList<String>>,
99
89
  ) {
100
- val (fromDir, intoDir) = getStrippedLibsPath(variantName)
90
+ val fromDir = strippedLibsDir.get().asFile
91
+ if (!fromDir.exists()) return
101
92
 
102
- existingJNILibs.forEach { (arch, libNames) ->
103
- copyLibsForArchitecture(fromDir, intoDir, arch, libNames)
93
+ existingJNILibs.keys.forEach { arch ->
94
+ copyArchStrippedSoLibs(fromDir, outDir, arch)
104
95
  }
105
96
  }
106
97
 
107
- private fun copyLibsForArchitecture(
98
+ private fun copyArchStrippedSoLibs(
108
99
  fromDir: File,
109
- intoDir: File,
100
+ outDir: File,
110
101
  arch: String,
111
- libNames: List<String>,
112
102
  ) {
113
103
  val sourceArchDir = File(fromDir, arch)
114
104
  if (!sourceArchDir.exists()) return
115
105
 
116
- val destArchDir = File(intoDir, arch).apply { mkdirs() }
117
-
118
- libNames.forEach { libName ->
119
- copyLibFile(sourceArchDir, destArchDir, libName)
106
+ val destArchDir = File(outDir, arch).apply { mkdirs() }
107
+ sourceArchDir.listFiles()?.forEach { file ->
108
+ copyIfAllowed(file, destArchDir)
120
109
  }
121
110
  }
122
111
 
123
- private fun copyLibFile(
124
- sourceArchDir: File,
112
+ private fun copyIfAllowed(
113
+ file: File,
125
114
  destArchDir: File,
126
- libName: String,
127
115
  ) {
128
- val sourceFile = File(sourceArchDir, libName)
129
- val destFile = File(destArchDir, libName)
130
-
131
- if (sourceFile.exists()) {
132
- try {
133
- sourceFile.copyTo(destFile, overwrite = true)
134
- } catch (e: java.io.IOException) {
135
- Logging.log("Failed to copy $libName: ${e.message}")
136
- }
116
+ val name = file.name
117
+ if (!matchesAllowedLib(name)) return
118
+
119
+ try {
120
+ file.copyTo(File(destArchDir, name), overwrite = true)
121
+ } catch (e: java.io.IOException) {
122
+ Logging.error("Failed to copy $name: ${e.message}", e.cause)
137
123
  }
138
124
  }
139
125
 
126
+ private fun matchesAllowedLib(name: String): Boolean {
127
+ val isCodegenLib = name.startsWith("libreact_codegen_") && name.endsWith(".so")
128
+ val isIgnoredLib = IGNORE_EMBEDDED_LIBS.any { lib -> name == lib || name.contains(lib) }
129
+ return name == "libappmodules.so" || isCodegenLib || !isIgnoredLib
130
+ }
131
+
140
132
  private fun processNestedLibs(
141
133
  files: Array<File>?,
142
134
  existingJNILibs: MutableMap<String, MutableList<String>>,
@@ -147,17 +139,50 @@ class JNILibsProcessor(val project: Project) {
147
139
 
148
140
  libFiles.forEach { file ->
149
141
  if (file.name in libList) {
150
- deleteFile(file)
142
+ file.delete()
151
143
  } else {
152
144
  libList.add(file.name)
153
145
  }
154
146
  }
155
147
  }
156
148
  }
149
+ }
157
150
 
158
- private fun deleteFile(file: File) {
159
- if (!file.delete()) {
160
- Logging.log("Failed to delete: ${file.name}")
161
- }
151
+ class JNILibsProcessor(val project: Project) {
152
+ fun processJniLibs(
153
+ aarLibraries: Collection<AndroidArchiveLibrary>,
154
+ variant: LibraryVariant,
155
+ ) {
156
+ val variantName = variant.name
157
+ val capitalizedVariantName = variantName.capitalized()
158
+ val projectExt = project.extensions.getByType(Extension::class.java)
159
+ val appProject = project.rootProject.project(projectExt.appProjectName)
160
+
161
+ val processJniTask =
162
+ project.tasks.register("processCustomJniLibsFor$capitalizedVariantName", ProcessAndCopyJniLibsTask::class.java) {
163
+ it.useStrippedSoFiles.set(projectExt.useStrippedSoFiles)
164
+
165
+ val jniDirs =
166
+ aarLibraries.map { aarLib ->
167
+ aarLib.getJniDir()
168
+ }
169
+
170
+ it.aarJniDirs.setFrom(jniDirs)
171
+
172
+ val fromDirProvider =
173
+ appProject.layout.buildDirectory.dir(
174
+ "intermediates/stripped_native_libs/$variantName/strip${capitalizedVariantName}DebugSymbols/out/lib",
175
+ )
176
+ it.strippedLibsDir.set(fromDirProvider)
177
+
178
+ val stripTaskPath = ":${appProject.name}:strip${capitalizedVariantName}DebugSymbols"
179
+ val codegenTaskPath = ":${project.name}:generateCodegenSchemaFromJavaScript"
180
+ it.dependsOn(stripTaskPath, codegenTaskPath)
181
+ }
182
+
183
+ variant.sources.jniLibs?.addGeneratedSourceDirectory(
184
+ taskProvider = processJniTask,
185
+ wiredWith = { it.outputDirectory },
186
+ )
162
187
  }
163
188
  }