Skip to content
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
5 changes: 5 additions & 0 deletions .changeset/open-zoos-walk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@callstack/react-native-brownfield': patch
---

fix: merge classes to contain third party libs classes
2 changes: 1 addition & 1 deletion apps/RNApp/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ buildscript {
classpath("com.android.tools.build:gradle")
classpath("com.facebook.react:react-native-gradle-plugin")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin")
classpath("com.callstack.react:brownfield-gradle-plugin:2.0.0-alpha05-SNAPSHOT")
classpath("com.callstack.react:brownfield-gradle-plugin:2.0.0-alpha06-SNAPSHOT")
}
}

Expand Down
2 changes: 1 addition & 1 deletion apps/RNApp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"ios": "yarn brownfield:package:ios && brownfield codegen && react-native run-ios",
"build:example:android-rn": "react-native build-android",
"build:example:ios-rn": "react-native build-ios",
"brownfield:package:android": "brownfield package:android --variant release",
"brownfield:package:android": "brownfield package:android",
"brownfield:publish:android": "brownfield publish:android",
"brownfield:package:ios": "brownfield package:ios --configuration Release",
"lint": "eslint .",
Expand Down
2 changes: 1 addition & 1 deletion apps/scripts/prepare-android-build-gradle-for-ci.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ if (!projectDirName) {

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const SNAPSHOT_VERSION = '2.0.0-alpha05-SNAPSHOT';
const SNAPSHOT_VERSION = '2.0.0-alpha06-SNAPSHOT';
const targetPath = path.resolve(
__dirname,
'..',
Expand Down
2 changes: 1 addition & 1 deletion gradle-plugins/react/brownfield/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
PROJECT_ID=com.callstack.react.brownfield
ARTIFACT_ID=brownfield-gradle-plugin
VERSION=2.0.0-alpha05
VERSION=2.0.0-alpha06
GROUP=com.callstack.react
IMPLEMENTATION_CLASS=com.callstack.react.brownfield.plugin.RNBrownfieldPlugin

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.callstack.react.brownfield.processors.JNILibsProcessor
import com.callstack.react.brownfield.processors.ManifestTaskProcessor
import com.callstack.react.brownfield.processors.ProguardProcessor
import com.callstack.react.brownfield.processors.ResourceTaskProcessor
import com.callstack.react.brownfield.processors.VariantHelper
import com.callstack.react.brownfield.processors.VariantPackagesProperty
import com.callstack.react.brownfield.processors.VariantTaskProvider
import com.callstack.react.brownfield.shared.BaseProject
Expand Down Expand Up @@ -139,6 +140,12 @@ class RNBrownfieldPlugin : Plugin<Project> {

val aarLibraries = getAarLibraries(artifacts, variantName)

/** ======= MERGE CLASSES =========*/
val mergeClassesTask = variantTaskProvider.mergeClasses(aarLibraries, explodeTask, variantName)
project.tasks.named(VariantHelper.getAsmTransformTaskName(capitalizedVariantName)).configure {
it.dependsOn(mergeClassesTask)
}

/**
* Flat IDs to be put into the variant property, required for RClass Transformer
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.callstack.react.brownfield.plugin
import com.android.build.api.variant.LibraryAndroidComponentsExtension
import com.android.build.gradle.LibraryExtension
import com.callstack.react.brownfield.exceptions.NameSpaceNotFound
import com.callstack.react.brownfield.processors.VariantHelper
import com.callstack.react.brownfield.utils.Extension
import com.callstack.react.brownfield.utils.Utils
import com.callstack.react.brownfield.utils.capitalized
Expand Down Expand Up @@ -49,7 +50,7 @@ object RNSourceSets {
componentsExtension.onVariants { variant ->
val variantName = variant.name
val bundledAssetsVariantName =
Utils.getBundledAssetsVariantName(
VariantHelper.getBundledAssetsVariantName(
variantName = variantName,
buildTypeName = variant.buildType,
isDebuggable = variant.debuggable,
Expand All @@ -66,7 +67,7 @@ object RNSourceSets {
// outputs for RN >= 0.82
"react/$bundledAssetsVariantName",
)
val updateResourcesPathSegment = Utils.getExpoUpdatesResourcesTaskName(variant.name)
val updateResourcesPathSegment = VariantHelper.getExpoUpdatesResourcesTaskName(variant.name)

val appBuildDir = getAppBuildDir()
sourceSet.assets.srcDirs(bundlePathSegments.map { "$appBuildDir/generated/assets/$it" })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ object ExplodeTaskProvider {
ExplodeAarTask::class.java,
) { task ->
task.variantName.set(variant.name)
task.minifyEnabled.set(variant.buildType.isMinifyEnabled)

val finalArtifacts = mutableListOf<UnresolvedArtifactInfo>()
artifacts.forEach { art ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,48 +5,26 @@ import org.gradle.api.Project
import java.io.File

object MergeProcessor {
fun mergeClassesJarIntoClasses(
fun mergeClassesJarFilesIntoClasses(
project: Project,
androidLibraries: Collection<AndroidArchiveLibrary>,
classJarFiles: Collection<File>,
folderOut: File,
) {
val allJarFiles: MutableCollection<File> = ArrayList()
val filteredLibs = getFilteredAarLibs(androidLibraries)
filteredLibs.forEach {
allJarFiles.add(it.getClassesJarFile())
}

val filteredAllJarFiles = allJarFiles.filter { it.exists() }
filteredAllJarFiles.forEach { jarFile ->
classJarFiles.filter { it.exists() }.forEach { jarFile ->
project.copy {
it.from(project.zipTree(jarFile))
it.into(folderOut)
}
}
}

fun mergeLibsIntoClasses(
fun mergeClassesJarIntoClasses(
project: Project,
androidLibraries: Collection<AndroidArchiveLibrary>,
jarFiles: Collection<File>,
outputDir: File,
folderOut: File,
) {
val allJarFiles: MutableCollection<File> = ArrayList()
val filteredLibs = getFilteredAarLibs(androidLibraries)
filteredLibs.forEach {
allJarFiles.addAll(it.getLocalJars())
}

val filteredJarFiles = jarFiles.filter { it.exists() }
filteredJarFiles.forEach { allJarFiles.add(it) }

allJarFiles.forEach { jarFile ->
project.copy {
it.from(project.zipTree(jarFile))
it.into(outputDir)
it.exclude("META-INF/")
}
}
val classesJarFiles = getFilteredAarLibs(androidLibraries).map { it.getClassesJarFile() }
mergeClassesJarFilesIntoClasses(project, classesJarFiles, folderOut)
}

private fun getFilteredAarLibs(androidLibraries: Collection<AndroidArchiveLibrary>): Collection<AndroidArchiveLibrary> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,61 +1,59 @@
package com.callstack.react.brownfield.processors

import com.callstack.react.brownfield.shared.BaseProject
import com.callstack.react.brownfield.utils.AndroidArchiveLibrary
import com.callstack.react.brownfield.utils.DirectoryManager
import com.callstack.react.brownfield.utils.capitalized
import org.gradle.api.file.ConfigurableFileCollection
import java.io.File
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths

class VariantHelper : BaseProject() {
private fun getClassPathDirFiles(variantName: String): ConfigurableFileCollection {
return project.files(
"$buildDir/intermediates/javac/$variantName/compile${variantName.capitalized()}JavaWithJavac/classes",
)
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.tasks.TaskCollection

object VariantHelper {
fun getAsmTransformTaskName(capitalizedVariantName: String): String {
return "transform${capitalizedVariantName}ClassesWithAsm"
}

fun classesMergeTaskDoFirst(
outputDir: File,
variantName: String,
) {
val pathsToDelete = mutableListOf<Path>()
val javacDir = getClassPathDirFiles(variantName).first()
project.fileTree(outputDir).forEach { path ->
pathsToDelete.add(
Paths.get(outputDir.absolutePath).relativize(Paths.get(path.absolutePath)),
)
fun getBundledAssetsVariantName(
variantName: String?,
buildTypeName: String?,
isDebuggable: Boolean,
): String {
require(!variantName.isNullOrEmpty()) {
"getBundledAssetsVariantName: Variant name cannot be empty"
}
outputDir.deleteRecursively()
pathsToDelete.forEach { path ->
Files.deleteIfExists(Paths.get("$javacDir.absolutePath/$path"))

require(!buildTypeName.isNullOrEmpty()) {
"getBundledAssetsVariantName: Build Type cannot be empty"
}
}

fun classesMergeTaskDoLast(
outputDir: File,
aarLibraries: Collection<AndroidArchiveLibrary>,
jarFiles: MutableList<File>,
variantName: String,
isMinifyEnabled: Boolean,
) {
MergeProcessor.mergeClassesJarIntoClasses(project, aarLibraries, outputDir)
if (isMinifyEnabled) {
MergeProcessor.mergeLibsIntoClasses(project, aarLibraries, jarFiles, outputDir)
if (!isDebuggable) {
Comment on lines -44 to +26

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously, we used to check for isMinifyEnabled. I'm wondering: aren't we missing handling of this case? If any consumer enables minify on the brownfield library module, will embedded libs/*.jar from dependencies be merged?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check was not doing any work as the jarFiles would always contain an empty list. Verified locally by enabling minification for brownfieldlib and we only need to adjust the proguard-rules and add consumer-rules to our packages like brownie, navigation and brownfield, which I will do in a follow-up PR.

return variantName
}
val javacDir = getClassPathDirFiles(variantName).first()
project.copy { copyTask ->
copyTask.from(outputDir)
copyTask.into(javacDir)
copyTask.exclude("META-INF/")

if (variantName == buildTypeName) {
return "release"
}

project.copy { copyTask ->
copyTask.from("${outputDir.absolutePath}/META-INF")
copyTask.into(DirectoryManager.getKotlinMetaDirectory(variantName))
copyTask.include("*.kotlin_module")
val capitalizedBuildTypeName = buildTypeName.capitalized()
return if (variantName.endsWith(capitalizedBuildTypeName)) {
"${variantName.removeSuffix(capitalizedBuildTypeName)}Release"
} else {
"release"
}
}

fun getExpoUpdatesResourcesTaskName(variantName: String): String {
return "create${variantName.capitalized()}UpdatesResources"
}

fun getKotlinCompileTask(
project: Project,
capitalizedVariantName: String,
): TaskCollection<Task> {
return project.tasks.matching { it.name == "compile${capitalizedVariantName}Kotlin" }
}

fun getJavaCompileTask(
project: Project,
capitalizedVariantName: String,
): TaskCollection<Task> {
return project.tasks.matching { it.name == "compile${capitalizedVariantName}JavaWithJavac" }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.callstack.react.brownfield.processors
import com.android.build.gradle.internal.tasks.factory.dependsOn
import com.callstack.react.brownfield.exceptions.TaskNotFound
import com.callstack.react.brownfield.shared.ExplodeAarTask
import com.callstack.react.brownfield.shared.MergeClassesTask
import com.callstack.react.brownfield.utils.AndroidArchiveLibrary
import com.callstack.react.brownfield.utils.DirectoryManager
import com.callstack.react.brownfield.utils.Extension
Expand Down Expand Up @@ -83,7 +84,7 @@ class VariantTaskProvider(val project: Project) {
preBuildTask.dependsOn(explodeAarTask)

val bundledAssetsVariantName =
Utils.getBundledAssetsVariantName(
VariantHelper.getBundledAssetsVariantName(
variantName = variantName,
buildTypeName = buildTypeName,
isDebuggable = isVariantDebuggable,
Expand All @@ -95,10 +96,28 @@ class VariantTaskProvider(val project: Project) {
preBuildTask.dependsOn("${appProject.path}:createBundle${capitalizedBundledAssetsVariantName}JsAndAssets")

if (Utils.isExpoProject(project)) {
val updatesResourcesTaskName = Utils.getExpoUpdatesResourcesTaskName(variantName)
val updatesResourcesTaskName = VariantHelper.getExpoUpdatesResourcesTaskName(variantName)
if (Utils.hasExpoUpdates(appProject, variantName)) {
preBuildTask.dependsOn("${appProject.path}:$updatesResourcesTaskName")
}
}
}

fun mergeClasses(
aarLibraries: Collection<AndroidArchiveLibrary>,
explodeTasks: TaskProvider<ExplodeAarTask>,
variantName: String,
): TaskProvider<MergeClassesTask> {
val capitalizedVariantName = variantName.capitalized()
val mergeClassesTaskName = "mergeClasses$capitalizedVariantName"

return project.tasks.register(mergeClassesTaskName, MergeClassesTask::class.java) {
it.dependsOn(explodeTasks)
it.dependsOn(VariantHelper.getKotlinCompileTask(project, capitalizedVariantName))
it.dependsOn(VariantHelper.getJavaCompileTask(project, capitalizedVariantName))
it.variantName.set(variantName)
it.inputClassesJars.from(aarLibraries.map { aarLibrary -> aarLibrary.getClassesJarFile() })
it.outputDir.set(DirectoryManager.getMergeClassDirectory(variantName))
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.callstack.react.brownfield.shared

import com.callstack.react.brownfield.processors.VariantHelper
import com.callstack.react.brownfield.utils.AndroidArchiveLibrary
import com.callstack.react.brownfield.utils.DirectoryManager
import org.gradle.api.DefaultTask
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
Expand All @@ -17,25 +15,11 @@ abstract class ExplodeAarTask : DefaultTask() {
@get:Input
abstract val variantName: Property<String>

@get:Input
abstract val minifyEnabled: Property<Boolean>

@TaskAction
fun run() {
val artifacts = inputArtifacts.get()
val resolvedVariantName = variantName.get()

val variantHelper = VariantHelper()
variantHelper.project = project

// classes-merge
variantHelper.classesMergeTaskDoFirst(
DirectoryManager.getMergeClassDirectory(
resolvedVariantName,
),
resolvedVariantName,
)

val aarLibraries = mutableListOf<AndroidArchiveLibrary>()
artifacts.forEach { art ->
val artifactFile =
Expand Down Expand Up @@ -64,9 +48,5 @@ abstract class ExplodeAarTask : DefaultTask() {
it.into(zipFolder)
}
}

// classes-merge
val mergeClassesOutputDir = DirectoryManager.getMergeClassDirectory(resolvedVariantName)
variantHelper.classesMergeTaskDoLast(mergeClassesOutputDir, aarLibraries, mutableListOf(), resolvedVariantName, minifyEnabled.get())
}
}
Loading
Loading