From 3816288468ce46991314a333df3690dd6ffb0ff8 Mon Sep 17 00:00:00 2001 From: Hur Ali Date: Tue, 13 Jan 2026 23:57:26 +0500 Subject: [PATCH 01/12] feat: first approach - fails at not calling bundleRelaseAar for TPL --- apps/RNApp/android/build.gradle | 2 +- apps/RNApp/package.json | 3 + apps/TesterIntegrated/package.json | 2 +- gradle-plugins/publish-to-maven-local.sh | 2 +- .../react/brownfield/build.gradle.kts | 16 -- .../react/brownfield/gradle.properties | 2 +- .../brownfield/artifacts/ArtifactsResolver.kt | 151 ++++++++++++------ .../brownfield/artifacts/FlavorArtifact.kt | 66 +++++--- .../plugin/CustomDependencyResolver.kt | 2 +- .../plugin/ProjectConfigurations.kt | 38 ++++- .../brownfield/plugin/RClassTransformer.kt | 15 +- .../brownfield/plugin/RNBrownfieldPlugin.kt | 121 ++++++++------ .../react/brownfield/plugin/RNSourceSets.kt | 40 +++-- .../brownfield/processors/JNILibsProcessor.kt | 12 ++ .../brownfield/processors/VariantHelper.kt | 12 +- .../brownfield/processors/VariantProcessor.kt | 105 +++++++++--- .../processors/VariantTaskProvider.kt | 10 ++ .../shared/ArtifactRegistrationTask.kt | 27 ++++ .../react/brownfield/shared/ModuleInfo.kt | 26 +++ .../brownfield/shared/ProcessArtifactTask.kt | 4 + .../brownfield/utils/AndroidArchiveLibrary.kt | 10 +- 21 files changed, 469 insertions(+), 197 deletions(-) create mode 100644 gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ArtifactRegistrationTask.kt create mode 100644 gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ModuleInfo.kt create mode 100644 gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ProcessArtifactTask.kt diff --git a/apps/RNApp/android/build.gradle b/apps/RNApp/android/build.gradle index 675d09cc..09e5bfe0 100644 --- a/apps/RNApp/android/build.gradle +++ b/apps/RNApp/android/build.gradle @@ -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:0.6.3") + classpath("com.callstack.react:brownfield-gradle-plugin:0.6.3-local") } } diff --git a/apps/RNApp/package.json b/apps/RNApp/package.json index 2aaeb40b..9ea9b5d9 100644 --- a/apps/RNApp/package.json +++ b/apps/RNApp/package.json @@ -7,6 +7,9 @@ "ios": "react-native run-ios", "build:example:android-rn": "react-native build-android", "build:example:ios-rn": "react-native build-ios", + "build:aar:dryRun": "cd android && ./gradlew :brownfieldlib:assembleRelease --dry-run", + "build:aar": "cd android && ./gradlew :brownfieldlib:assembleRelease", + "build:scan": "cd android && ./gradlew :brownfieldlib:assembleRelease --scan", "lint": "eslint .", "start": "react-native start", "test": "jest" diff --git a/apps/TesterIntegrated/package.json b/apps/TesterIntegrated/package.json index f7cf6891..96ce755f 100644 --- a/apps/TesterIntegrated/package.json +++ b/apps/TesterIntegrated/package.json @@ -4,7 +4,7 @@ "private": true, "scripts": { "start": "react-native start", - "build:tester-integrated:android": "cd kotlin && ./gradlew assembleDebug", + "build:tester-integrated:android": "cd kotlin && ./gradlew installDebug", "build:tester-integrated:ios": "cd swift && xcodebuild -workspace SwiftExample.xcworkspace -scheme SwiftExample -configuration Release -sdk iphonesimulator build CODE_SIGNING_ALLOWED=NO -derivedDataPath ./build" }, "dependencies": { diff --git a/gradle-plugins/publish-to-maven-local.sh b/gradle-plugins/publish-to-maven-local.sh index 39db8b77..e56b888b 100755 --- a/gradle-plugins/publish-to-maven-local.sh +++ b/gradle-plugins/publish-to-maven-local.sh @@ -2,7 +2,7 @@ set -e -cd ./gradle-plugins/react +cd ./react ./gradlew clean ./gradlew build ./gradlew :brownfield:publishMavenLocalPublicationToMavenLocalRepository \ No newline at end of file diff --git a/gradle-plugins/react/brownfield/build.gradle.kts b/gradle-plugins/react/brownfield/build.gradle.kts index d250ce05..c4b0a2d1 100644 --- a/gradle-plugins/react/brownfield/build.gradle.kts +++ b/gradle-plugins/react/brownfield/build.gradle.kts @@ -64,18 +64,6 @@ publishing { distribution.set("repo") } } - developers { - developer { - id.set("callstack") - name.set("Callstack Team") - email.set("it-admin@callstack.com") - } - } - scm { - connection.set(property("SCM_CONNECTION").toString()) - developerConnection.set(property("SCM_DEV_CONNECTION").toString()) - url.set(property("GITHUB_URL").toString()) - } } } } @@ -85,10 +73,6 @@ publishing { } } -signing { - sign(publishing.publications["mavenLocal"]) -} - repositories { mavenCentral() google() diff --git a/gradle-plugins/react/brownfield/gradle.properties b/gradle-plugins/react/brownfield/gradle.properties index 800ce244..1b6b84ea 100644 --- a/gradle-plugins/react/brownfield/gradle.properties +++ b/gradle-plugins/react/brownfield/gradle.properties @@ -1,6 +1,6 @@ PROJECT_ID=com.callstack.react.brownfield ARTIFACT_ID=brownfield-gradle-plugin -VERSION=0.6.3 +VERSION=0.6.3-local GROUP=com.callstack.react IMPLEMENTATION_CLASS=com.callstack.react.brownfield.plugin.RNBrownfieldPlugin diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/ArtifactsResolver.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/ArtifactsResolver.kt index 47a10fcb..18bc44d4 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/ArtifactsResolver.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/ArtifactsResolver.kt @@ -19,12 +19,19 @@ import com.callstack.react.brownfield.processors.VariantProcessor import com.callstack.react.brownfield.processors.VariantTaskProvider import com.callstack.react.brownfield.shared.BaseProject import com.callstack.react.brownfield.shared.GradleProps +import com.callstack.react.brownfield.shared.UnresolvedArtifactInfo import com.callstack.react.brownfield.utils.Extension import com.callstack.react.brownfield.utils.Utils -import org.gradle.api.ProjectConfigurationException +import org.gradle.api.artifacts.ArtifactCollection import org.gradle.api.artifacts.Configuration -import org.gradle.api.artifacts.ResolvedArtifact +import org.gradle.api.artifacts.component.ModuleComponentIdentifier +import org.gradle.api.artifacts.component.ProjectComponentIdentifier +import org.gradle.api.artifacts.result.ResolvedDependencyResult +import org.gradle.api.attributes.Attribute import org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency +import org.gradle.internal.component.local.model.PublishArtifactLocalArtifactMetadata +import kotlin.collections.mutableListOf + class ArtifactsResolver( private val configurations: MutableCollection, @@ -37,18 +44,12 @@ class ArtifactsResolver( const val ARTIFACT_TYPE_JAR = "jar" } - fun processArtifacts() { + fun processDefaultDependencies() { embedDefaultDependencies("implementation") - setTransitiveToConfigurations() - generateArtifacts() } - private fun setTransitiveToConfigurations() { - configurations.forEach { - if (baseProject.project.extensions.getByType(Extension::class.java).transitive) { - it.isTransitive = true - } - } + fun processArtifacts() { + generateArtifacts() } private fun embedExpoDependencies() { @@ -72,19 +73,19 @@ class ArtifactsResolver( val expoProject = baseProject.project.rootProject.project("expo") val expoConfig = expoProject.configurations.findByName("api") expoConfig?.dependencies?.forEach { - if (extension.resolveLocalDependencies) { - if (it is DefaultProjectDependency) { - baseProject.project.dependencies.add( - CONFIG_NAME, - expoProject.dependencies.project(mapOf("path" to ":${it.name}")), - ) - } else { - baseProject.project.dependencies.add( - CONFIG_NAME, - it, - ) + if (extension.resolveLocalDependencies) { + if (it is DefaultProjectDependency) { + baseProject.project.dependencies.add( + CONFIG_NAME, + expoProject.dependencies.project(mapOf("path" to ":${it.name}")), + ) + } else { + baseProject.project.dependencies.add( + CONFIG_NAME, + it, + ) + } } - } } } @@ -96,23 +97,22 @@ class ArtifactsResolver( val config = baseProject.project.configurations.findByName(configName) val defaultDependencies = config?.dependencies?.filterIsInstance() defaultDependencies?.forEach { dependency -> - if (extension.resolveLocalDependencies) { - baseProject.project.dependencies.add( - CONFIG_NAME, - baseProject.project.dependencies.project(mapOf("path" to ":${dependency.name}")), - ) - } + if (extension.resolveLocalDependencies) { + baseProject.project.dependencies.add( + CONFIG_NAME, + baseProject.project.dependencies.project(mapOf("path" to ":${dependency.name}")), + ) + } } } private fun generateArtifacts() { baseProject.project.extensions.getByType(LibraryExtension::class.java).libraryVariants.all { variant -> - val artifacts: MutableCollection = ArrayList() + val artifacts = mutableListOf() configurations.forEach { configuration -> if (isEmbedConfig(configuration, variant)) { val resolvedArtifacts = resolveArtifacts(configuration) - artifacts.addAll(resolvedArtifacts) artifacts.addAll(handleUnResolvedArtifacts(configuration, variant, resolvedArtifacts)) } } @@ -134,47 +134,96 @@ class ArtifactsResolver( configuration.name == variant.name + CONFIG_SUFFIX } - private fun resolveArtifacts(configuration: Configuration): Collection { - val artifacts = ArrayList() - configuration.resolvedConfiguration.resolvedArtifacts.forEach { artifact -> - if (artifact.type != ARTIFACT_TYPE_AAR && artifact.type != ARTIFACT_TYPE_JAR) { - throw ProjectConfigurationException("Unsupported dependency. Please provide either Aar or Jar dependency", listOf()) + private fun resolveArtifacts(configuration: Configuration): ArtifactCollection { + println("\n==== Resolving Artifacts ${configuration.name} =======\n") + + // Prepare a view of the configuration that can resolve the correct variant + val componentArtifacts = configuration.incoming.artifactView { view -> + view.attributes { + // Do we always have to have AAR? or JAR in some cases? + it.attributes.attribute(Attribute.of("artifactType", String::class.java), "aar") +// it.attributes.attribute(Attribute.of("artifactType", String::class.java), "jar") } - artifacts.add(artifact) - } - return artifacts + }.artifacts + + return componentArtifacts } private fun handleUnResolvedArtifacts( configuration: Configuration, variant: LibraryVariant, - artifacts: Collection, - ): Collection { - val artifactList = ArrayList() - val unMatchedArtifacts = - configuration.resolvedConfiguration.firstLevelModuleDependencies.filter { - !artifacts.any { artifact -> - it.moduleName == artifact.moduleVersion.id.name + artifacts: ArtifactCollection, + ): List { + val unMatchedArtifacts = mutableListOf() + val firstLevelIds = + artifacts + .map { it.id.componentIdentifier.displayName } + .toSet() + + val resolutionResult = configuration.incoming.resolutionResult + resolutionResult.root.dependencies.forEach { + if (it is ResolvedDependencyResult) { + when (val id = it.selected.id) { + is ModuleComponentIdentifier -> { +// println("===----- module ${id.moduleIdentifier.name} ${id.displayName} === ${firstLevelIds}") + if (id.displayName !in firstLevelIds) { +// unMatchedArtifacts.add( +// UnresolvedArtifactInfo( +// id.group, +// id.module, +// id.version, +// ) +// ) + } + } + is ProjectComponentIdentifier -> { + val depProj = baseProject.project.project(id.projectPath) + if (id.displayName !in firstLevelIds) { +// id. + unMatchedArtifacts.add(UnresolvedArtifactInfo( + depProj.group.toString(), + depProj.name, + depProj.version.toString(), + baseProject.project.file(id.projectName), + mutableSetOf() + )) + } + } } } + } val variantHelper = VariantHelper(variant) variantHelper.project = baseProject.project val variantTaskProvider = VariantTaskProvider(variantHelper) variantTaskProvider.project = baseProject.project - val flavorArtifact = FlavorArtifact(variant, variantTaskProvider) + val flavorArtifact = FlavorArtifact(variant, variantTaskProvider, configuration) flavorArtifact.project = baseProject.project - unMatchedArtifacts.forEach { dependency -> + val unMatchedArtifacts1 = mutableListOf() + unMatchedArtifacts.forEach { artifact -> val resolvedArtifact = flavorArtifact.createFlavorArtifact( - dependency, + artifact, calculatedValueContainerFactory, fileResolver, taskDependencyFactory, ) - artifactList.add(resolvedArtifact) + + when (val asd = resolvedArtifact.id) { + is PublishArtifactLocalArtifactMetadata -> { + val deps = asd.buildDependencies.getDependencies(null) + unMatchedArtifacts1.add(UnresolvedArtifactInfo( + artifact.moduleGroup, + artifact.moduleName, + artifact.moduleVersion, + resolvedArtifact.file, + deps + )) + } + } } - return artifactList + + return unMatchedArtifacts1 } } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/FlavorArtifact.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/FlavorArtifact.kt index db91a447..9782309d 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/FlavorArtifact.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/FlavorArtifact.kt @@ -10,58 +10,89 @@ package com.callstack.react.brownfield.artifacts +import org.gradle.api.component.Artifact import com.android.build.gradle.LibraryExtension import com.android.build.gradle.api.LibraryVariant import com.android.build.gradle.internal.tasks.factory.dependsOn import com.callstack.react.brownfield.processors.VariantTaskProvider import com.callstack.react.brownfield.shared.BaseProject +import com.callstack.react.brownfield.shared.UnresolvedArtifactInfo import org.gradle.api.Project import org.gradle.api.Task +import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.ResolvedArtifact -import org.gradle.api.artifacts.ResolvedDependency +import org.gradle.api.artifacts.result.ResolvedArtifactResult import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier import org.gradle.api.internal.artifacts.DefaultResolvedArtifact import org.gradle.api.internal.artifacts.dsl.LazyPublishArtifact +import org.gradle.api.internal.artifacts.result.DefaultResolvedArtifactResult import org.gradle.api.internal.file.FileResolver import org.gradle.api.internal.tasks.TaskDependencyFactory import org.gradle.api.tasks.TaskProvider import org.gradle.api.tasks.bundling.Zip import org.gradle.internal.Describables +import org.gradle.internal.component.external.model.ImmutableCapabilities import org.gradle.internal.component.local.model.PublishArtifactLocalArtifactMetadata import org.gradle.internal.component.model.DefaultIvyArtifactName import org.gradle.internal.model.CalculatedValueContainerFactory import java.io.File -class FlavorArtifact(private val variant: LibraryVariant, private val variantTaskProvider: VariantTaskProvider) : BaseProject() { +class FlavorArtifact(private val variant: LibraryVariant, + private val variantTaskProvider: VariantTaskProvider, + private val configuration: Configuration) : BaseProject() { fun createFlavorArtifact( - unResolvedArtifact: ResolvedDependency, + unResolvedArtifact: UnresolvedArtifactInfo, calculatedValueContainerFactory: CalculatedValueContainerFactory, fileResolver: FileResolver, taskDependencyFactory: TaskDependencyFactory, - ): ResolvedArtifact { + ): ResolvedArtifactResult { val artifactProject = getArtifactProject(unResolvedArtifact) val bundleProvider: TaskProvider? = artifactProject?.let { getBundleTaskProvider(it, variant) } - project.tasks.named("preBuild").dependsOn("${artifactProject?.path}:${bundleProvider?.name}") + val capitalizedName = variant.name.replaceFirstChar(Char::titlecase) + +// val bTask = project.tasks.named("transform${capitalizedName}ClassesWithAsm") +// bTask.configure { +// it.mustRunAfter("${artifactProject?.path}:${bundleProvider?.name}") +// } + + val mTask = artifactProject?.tasks?.named("${bundleProvider?.name}") + mTask?.configure { + println("\n==== ${artifactProject.path}${mTask.name} Configured\n") + + it.doFirst { + println("\n=== ${artifactProject.path}${mTask.name} doFirst\n") + } + + it.doLast { + println("\n=== ${artifactProject.path}${mTask.name} doLast\n") + } + } + + // preBuild -- transform${capitalizedName}ClassesWithAsm + project.tasks.named("preBuild").configure { + println("\n==== preBuild Configured Second\n") + it.dependsOn(mTask) + + it.doLast { + println("\n==== preBuild Configured Second -> doLast\n") + } + } - val identifier = - DefaultModuleVersionIdentifier.newId( - unResolvedArtifact.moduleGroup, - unResolvedArtifact.moduleName, - unResolvedArtifact.moduleVersion, - ) val artifactFile = createArtifactFile(bundleProvider?.get() as Task) val artifactName = DefaultIvyArtifactName(artifactFile.name, "aar", "") - return DefaultResolvedArtifact( + return DefaultResolvedArtifactResult( PublishArtifactLocalArtifactMetadata( { artifactName.name }, LazyPublishArtifact(bundleProvider, fileResolver, taskDependencyFactory), ), - calculatedValueContainerFactory.create(Describables.of(artifactFile.name), artifactFile), - identifier, - artifactName, + configuration.attributes, + ImmutableCapabilities.EMPTY, + Describables.of(variant.name), + Artifact::class.java, + artifactFile ) } @@ -107,8 +138,7 @@ class FlavorArtifact(private val variant: LibraryVariant, private val variantTas false } != null } != null - } catch (ignore: Exception) { - } + } catch (_: Exception) {} } bundleTaskProvider != null @@ -117,7 +147,7 @@ class FlavorArtifact(private val variant: LibraryVariant, private val variantTas return bundleTaskProvider } - private fun getArtifactProject(unResolvedArtifact: ResolvedDependency): Project? { + private fun getArtifactProject(unResolvedArtifact: UnresolvedArtifactInfo): Project? { return project.rootProject.allprojects.find { p -> unResolvedArtifact.moduleName == p.name && unResolvedArtifact.moduleGroup == p.group.toString() } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/CustomDependencyResolver.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/CustomDependencyResolver.kt index faf66b07..6f6162e3 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/CustomDependencyResolver.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/CustomDependencyResolver.kt @@ -19,7 +19,7 @@ class CustomDependencyResolver( private fun getCompileOnlyConfigName(configurationName: String): String { val configSuffix = ProjectConfigurations.CONFIG_SUFFIX if (configurationName.endsWith(configSuffix)) { - val configName = configurationName.substring(0, configurationName.length - configSuffix.length) + val configName = configurationName.dropLast(configSuffix.length) return "${configName}CompileOnly" } else { return "compileOnly" diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/ProjectConfigurations.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/ProjectConfigurations.kt index 85613539..28c869f5 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/ProjectConfigurations.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/ProjectConfigurations.kt @@ -1,9 +1,18 @@ package com.callstack.react.brownfield.plugin +import com.android.build.api.attributes.AgpVersionAttr +import com.android.build.api.attributes.BuildTypeAttr +import com.android.build.api.variant.LibraryAndroidComponentsExtension import com.android.build.gradle.LibraryExtension +import com.android.build.gradle.internal.attributes.VariantAttr import com.callstack.react.brownfield.shared.Logging import org.gradle.api.Project import org.gradle.api.artifacts.Configuration +import org.gradle.api.attributes.Attribute +import org.gradle.api.attributes.AttributeContainer +import org.gradle.api.attributes.Usage +import org.gradle.api.attributes.java.TargetJvmEnvironment +import org.gradle.api.internal.artifacts.ArtifactAttributes class ProjectConfigurations(private val project: Project) { private val configurations: MutableCollection = mutableListOf() @@ -26,10 +35,9 @@ class ProjectConfigurations(private val project: Project) { * 3. creates configs for flavours * 4. creates configs for flavours with buildTypes */ - fun setup() { + fun configure() { // create main configuration createConfiguration(CONFIG_NAME) - val androidExtension = project.extensions.getByName("android") as LibraryExtension createBuildTypesConfiguration(androidExtension) createFlavorConfigurations(androidExtension) @@ -63,13 +71,35 @@ class ProjectConfigurations(private val project: Project) { * creates configuration based on `configName`. Also attaches a resolution listener. */ private fun createConfiguration(configName: String) { - Logging.log("creating configuration $configName") + Logging.log("creating configuration $configName ⌛️") val configuration = project.configurations.create(configName) + + configuration.extendsFrom(project.configurations.getByName("implementation")) configuration.isVisible = false configuration.isTransitive = false + + val androidComponents = project.extensions.getByType(LibraryAndroidComponentsExtension::class.java) + androidComponents.onVariants { variant -> + + val runtimeAttributes = variant.runtimeConfiguration.attributes + runtimeAttributes.keySet().forEach { key -> + copyAttribute( + key, + runtimeAttributes, + configuration.attributes + ) + } + } + project.gradle.addListener(CustomDependencyResolver(project, configuration)) configurations.add(configuration) - Logging.log("created configuration $configName") + Logging.log("created configuration $configName ✅") + } + + private fun copyAttribute(key: Attribute, from: AttributeContainer, into: AttributeContainer) { + from.getAttribute(key)?.let { + into.attribute(key, it) + } } private fun getConfigName(prefix: String): String { diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RClassTransformer.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RClassTransformer.kt index c9f483ed..81690178 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RClassTransformer.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RClassTransformer.kt @@ -9,6 +9,7 @@ import com.android.build.api.instrumentation.InstrumentationScope import com.android.build.api.variant.AndroidComponentsExtension import com.callstack.react.brownfield.processors.VariantPackagesProperty import com.callstack.react.brownfield.shared.BaseProject +import com.callstack.react.brownfield.utils.Utils import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Property import org.gradle.api.tasks.Input @@ -29,17 +30,22 @@ object RClassTransformer : BaseProject() { fun registerASMTransformation() { val components = project.extensions.getByType(AndroidComponentsExtension::class.java) val variantPackagesProperty = VariantPackagesProperty.getVariantPackagesProperty() + variantPackagesProperty.get().forEach { + println("=== variantPackagesProperty $it") + } components.onVariants(components.selector().all()) { variant -> variant.instrumentation.transformClassesWith( RClassAsmTransformerFactory::class.java, InstrumentationScope.PROJECT, ) { params -> params.namespace.set(variant.namespace) - params.libraryNamespaces.set( - variantPackagesProperty.getting(variant.name) - .map { list -> list.map { it.getPackageName() }.toList() }, - ) +// params.libraryNamespaces.set( +// variantPackagesProperty.getting(variant.name) +// .map { list -> list.map { it.getPackageName() }.toList() }, +// ) } + + println("=== project variant -- ${variant.name}") variant.instrumentation.setAsmFramesComputationMode(FramesComputationMode.COPY_FRAMES) } } @@ -65,6 +71,7 @@ object RClassTransformer : BaseProject() { classContext: ClassContext, nextClassVisitor: ClassVisitor, ): ClassVisitor { + println("\n==== INN HEREEE\n") val params = parameters.get() val namespace = params.namespace.get() val libraryNamespaces = params.libraryNamespaces.orElse(Collections.emptyList()).get() diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt index b060b2e6..b9fdd494 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt @@ -1,5 +1,7 @@ package com.callstack.react.brownfield.plugin +import com.android.build.api.variant.LibraryAndroidComponentsExtension +import com.android.build.gradle.internal.crash.afterEvaluate import com.callstack.react.brownfield.artifacts.ArtifactsResolver import com.callstack.react.brownfield.processors.VariantPackagesProperty import com.callstack.react.brownfield.shared.BaseProject @@ -7,6 +9,7 @@ import com.callstack.react.brownfield.shared.Constants.PROJECT_ID import com.callstack.react.brownfield.shared.Logging import com.callstack.react.brownfield.utils.DirectoryManager import com.callstack.react.brownfield.utils.Extension +import com.callstack.react.brownfield.utils.Utils import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.ProjectConfigurationException @@ -16,46 +19,91 @@ import org.gradle.internal.model.CalculatedValueContainerFactory import javax.inject.Inject class RNBrownfieldPlugin - @Inject - constructor( - private val calculatedValueContainerFactory: CalculatedValueContainerFactory, - private val taskDependencyFactory: TaskDependencyFactory, - private val fileResolver: FileResolver, - ) : Plugin { - private lateinit var project: Project - private lateinit var extension: Extension - private lateinit var projectConfigurations: ProjectConfigurations +@Inject +constructor( + private val calculatedValueContainerFactory: CalculatedValueContainerFactory, + private val taskDependencyFactory: TaskDependencyFactory, + private val fileResolver: FileResolver, +) : Plugin { + private lateinit var extension: Extension + private lateinit var projectConfigurations: ProjectConfigurations + private lateinit var artifactsResolver: ArtifactsResolver - override fun apply(project: Project) { + + override fun apply(project: Project) { verifyAndroidPluginApplied(project) initializers(project) - /** - * Make sure that expo project is evaluated before the android library. - * This ensures that the expo modules are available to link with the - * android library, when it is evaluated. - */ - val expoProjectPath = ":expo" - val hasExpoProject = project.findProject(expoProjectPath) != null - if (hasExpoProject) { - project.evaluationDependsOn(expoProjectPath) - } + println("=== Applying $PROJECT_ID ===") + // Configure + projectConfigurations.configure() RNSourceSets.configure(project, extension) - projectConfigurations.setup() - registerRClassTransformer() + RClassTransformer.registerASMTransformation() - project.afterEvaluate { - afterEvaluate() + if (Utils.isExampleLibrary(project.name)) { + return } + // Register tasks +// project.tasks.named("preDebugBuild").configure { +// println("==== Hello Debug ====") +// } +// +// project.tasks.named("preReleaseBuild").configure { +// println("==== Hello Release ====") +// } + + val baseProject = BaseProject() + baseProject.project = project + artifactsResolver = ArtifactsResolver(projectConfigurations.getConfigurations(), baseProject, extension) + artifactsResolver.calculatedValueContainerFactory = calculatedValueContainerFactory + artifactsResolver.taskDependencyFactory = taskDependencyFactory + artifactsResolver.fileResolver = fileResolver + + artifactsResolver.processDefaultDependencies() + + + artifactsResolver.processArtifacts() +// project.tasks.register("processArtifacts") { +// it.doFirst { +// artifactsResolver.processArtifacts() +// } +// } + +// val processArtifactsTask = project.tasks.register("processArtifacts") { +// println("==== processArtifact Configured ====") +// +//// it.dependsOn(":react-native-safe-area-context:bundleReleaseAar") +// it.doFirst { +// println("==== processArtifact doFirst ====") +// val baseProject = BaseProject() +// baseProject.project = project +// val artifactsResolver = ArtifactsResolver(projectConfigurations.getConfigurations(), baseProject, extension) +// artifactsResolver.calculatedValueContainerFactory = calculatedValueContainerFactory +// artifactsResolver.taskDependencyFactory = taskDependencyFactory +// artifactsResolver.fileResolver = fileResolver +// artifactsResolver.processArtifacts() +// } +// +// it.doLast { +// println("\n==== processArtifact doLast ====\n") +// } +// } +// +// +// project.tasks.named("preBuild").configure { +// println("==== preBuild Configured first ====") +// it.dependsOn(processArtifactsTask) +// +// it.doLast { +// println("\n==== preBuild first -> doLast ====\n") +// } +// } } private fun initializers(project: Project) { - this.project = project - Logging.project = project - DirectoryManager.project = project - RClassTransformer.project = project this.extension = project.extensions.create(Extension.NAME, Extension::class.java) + RClassTransformer.project = project projectConfigurations = ProjectConfigurations(project) VariantPackagesProperty.setVariantPackagesProperty(project) } @@ -71,21 +119,4 @@ class RNBrownfieldPlugin ) } } - - /** - * Transforms RClass - */ - private fun registerRClassTransformer() { - RClassTransformer.registerASMTransformation() - } - - private fun afterEvaluate() { - val baseProject = BaseProject() - baseProject.project = project - val artifactsResolver = ArtifactsResolver(projectConfigurations.getConfigurations(), baseProject, extension) - artifactsResolver.calculatedValueContainerFactory = calculatedValueContainerFactory - artifactsResolver.taskDependencyFactory = taskDependencyFactory - artifactsResolver.fileResolver = fileResolver - artifactsResolver.processArtifacts() - } } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNSourceSets.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNSourceSets.kt index ac1873c1..25b5b850 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNSourceSets.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNSourceSets.kt @@ -1,5 +1,6 @@ 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.utils.Extension @@ -34,39 +35,52 @@ object RNSourceSets { this.project = project this.extension = extension - androidExtension = RNSourceSets.project.extensions.getByName("android") as LibraryExtension - appProject = RNSourceSets.project.rootProject.project(RNSourceSets.extension.appProjectName) + androidExtension = this.project.extensions.getByType(LibraryExtension::class.java) + appProject = this.project.rootProject.project(RNSourceSets.extension.appProjectName) appBuildDir = appProject.layout.buildDirectory.get() - moduleBuildDir = RNSourceSets.project.layout.buildDirectory.get() + moduleBuildDir = this.project.layout.buildDirectory.get() configureSourceSets() configureTasks() } private fun configureSourceSets() { - project.extensions.getByType(LibraryExtension::class.java).libraryVariants.all { variant -> + // 1. Get the 'androidComponents' extension for the new Variant API + val componentsExtension = project.extensions.getByType(LibraryAndroidComponentsExtension::class.java) + + // Move the non-variant-specific configuration out of the loop + androidExtension.sourceSets.named("main") { sourceSet -> + // This path is not variant-specific, so it's added once here. + sourceSet.java.srcDir("$moduleBuildDir/generated/autolinking/src/main/java") + } + + // 2. Use the onVariants block to configure each variant + componentsExtension.onVariants { variant -> + // The variant name is directly available val capitalizedVariantName = variant.name.replaceFirstChar(Char::titlecase) - androidExtension.sourceSets.getByName("main") { sourceSet -> - for (bundlePathSegment in listOf( + // 3. Lazily configure the 'main' source set using .named() + androidExtension.sourceSets.named("main") { sourceSet -> + // Paths are collected and added, similar to your improved version + val bundlePathSegments = listOf( // outputs for RN <= 0.81 "createBundle${capitalizedVariantName}JsAndAssets", // outputs for RN >= 0.82 "react/${variant.name}", - )) { - sourceSet.assets.srcDirs("$appBuildDir/generated/assets/$bundlePathSegment") - sourceSet.res.srcDirs("$appBuildDir/generated/res/$bundlePathSegment") - } + ) - sourceSet.java.srcDirs("$moduleBuildDir/generated/autolinking/src/main/java") + // Add the variant-specific generated asset and resource directories + sourceSet.assets.srcDirs(bundlePathSegments.map { "$appBuildDir/generated/assets/$it" }) + sourceSet.res.srcDirs(bundlePathSegments.map { "$appBuildDir/generated/res/$it" }) } } - androidExtension.sourceSets.getByName("release") { + // These remain the same, but using .named() is the modern, lazy approach + androidExtension.sourceSets.named("release") { it.jniLibs.srcDirs("libsRelease") } - androidExtension.sourceSets.getByName("debug") { + androidExtension.sourceSets.named("debug") { it.jniLibs.srcDirs("libsDebug") } } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/JNILibsProcessor.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/JNILibsProcessor.kt index 6a30affe..82760b3b 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/JNILibsProcessor.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/JNILibsProcessor.kt @@ -40,6 +40,8 @@ class JNILibsProcessor : BaseProject() { val copyTask = copySoLibsTask(variant) mergeJniLibsTask.configure { + println("\n=== $taskName configured\n") + it.dependsOn(explodeTasks) it.dependsOn(copyTask) @@ -58,6 +60,10 @@ class JNILibsProcessor : BaseProject() { } } } + + it.doLast { + println("\n==== mergeJniLibsTask doLast ====\n") + } } } @@ -82,12 +88,18 @@ class JNILibsProcessor : BaseProject() { .file("${project.name}/libs$capitalizedVariant") return project.tasks.register("copy${capitalizedVariant}LibSources", Copy::class.java) { + println("\n=== copy${capitalizedVariant}LibSource configured\n") + it.dependsOn(stripTask, codegenTask) it.from(fromDir) it.into(intoDir) it.include("**/libappmodules.so", "**/libreact_codegen_*.so") projectExt.dynamicLibs.forEach { lib -> it.include("**/$lib") } + + it.doLast { + println("\n==== copy${capitalizedVariant}LibSource doLast ====\n") + } } } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantHelper.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantHelper.kt index 7a0bfdf7..6633da12 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantHelper.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantHelper.kt @@ -15,6 +15,7 @@ import com.android.build.gradle.api.LibraryVariant import com.android.build.gradle.tasks.ManifestProcessorTask import com.callstack.react.brownfield.exceptions.TaskNotFound import com.callstack.react.brownfield.shared.BaseProject +import com.callstack.react.brownfield.shared.UnresolvedArtifactInfo import com.callstack.react.brownfield.utils.AndroidArchiveLibrary import com.callstack.react.brownfield.utils.DirectoryManager import groovy.lang.MissingPropertyException @@ -38,16 +39,6 @@ class VariantHelper(private val variant: LibraryVariant) : BaseProject() { return variant.javaCompileProvider.get() } - fun getTaskDependencies(artifact: ResolvedArtifact): Set { - return try { - val publishArtifact = artifact::class.members.find { it.name == "publishArtifact" }?.call(artifact) - val buildDependencies = publishArtifact?.javaClass?.getMethod("getBuildDependencies")?.invoke(publishArtifact) - buildDependencies as? Set ?: emptySet() - } catch (ignore: MissingPropertyException) { - emptySet() - } - } - fun getSyncLibJarsTaskPath(): String { return "sync${variant.name.replaceFirstChar(Char::titlecase)}LibJars" } @@ -125,6 +116,7 @@ class VariantHelper(private val variant: LibraryVariant) : BaseProject() { } resourceGenTask.configure { + println("\n=== generate${capitalizedVariantName}Resources configured\n") it.dependsOn(explodeTasks) } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt index 5b57e990..afdef6ff 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt @@ -16,6 +16,7 @@ import com.callstack.react.brownfield.artifacts.ArtifactsResolver.Companion.ARTI import com.callstack.react.brownfield.artifacts.ArtifactsResolver.Companion.ARTIFACT_TYPE_JAR import com.callstack.react.brownfield.exceptions.TaskNotFound import com.callstack.react.brownfield.shared.BaseProject +import com.callstack.react.brownfield.shared.UnresolvedArtifactInfo import com.callstack.react.brownfield.utils.AndroidArchiveLibrary import org.gradle.api.Task import org.gradle.api.artifacts.ResolvedArtifact @@ -46,7 +47,7 @@ class VariantProcessor(private val variant: LibraryVariant) : BaseProject() { VariantPackagesProperty.getVariantPackagesProperty().put(variant.name, aarLibrariesProperty) } - fun processVariant(artifacts: Collection) { + fun processVariant(artifacts: List) { setup() val preBuildTaskPath = "pre${capitalizedVariantName}Build" val prepareTask = project.tasks.named(preBuildTaskPath) @@ -60,6 +61,7 @@ class VariantProcessor(private val variant: LibraryVariant) : BaseProject() { } val bundleTask = variantTaskProvider.bundleTaskProvider(project, variant.name) + explodeArtifactFiles(artifacts, prepareTask, bundleTask) mergeClassesAndJars(bundleTask) @@ -81,46 +83,73 @@ class VariantProcessor(private val variant: LibraryVariant) : BaseProject() { mergeClassTask = variantTaskProvider.classesMergeTask(aarLibraries, jarFiles, explodeTasks) syncLibTask.configure { + println("\n==== syncLibTask Configured\n") it.dependsOn(mergeClassTask) it.inputs.files(aarLibraries.map { aarLib -> aarLib.getLibsDir() }).withPathSensitivity( PathSensitivity.RELATIVE, ) it.inputs.files(jarFiles).withPathSensitivity(PathSensitivity.RELATIVE) + + it.doLast { + println("\n==== syncLibTask doLast ====\n") + } } project.tasks.named("transform${capitalizedVariantName}ClassesWithAsm").configure { + println("\n==== transformAsm Configured\n") it.dependsOn(mergeClassTask) + + it.doLast { + println("\n==== transformAsm doLast ====\n") + } } + extractAnnotationsTask.configure { + println("\n==== extractAnnotationsTask Configured\n") it.mustRunAfter(mergeClassTask) + + it.doLast { + println("\n==== extractAnnotationsTask doLast ====\n") + } } if (!variant.buildType.isMinifyEnabled) { val mergeJars = variantTaskProvider.jarMergeTask(syncLibTask, aarLibraries, jarFiles, explodeTasks) project.tasks.named("bundle${capitalizedVariantName}LocalLintAar").configure { + println("\n==== bundle${capitalizedVariantName}LocalLintAar Configured\n") it.dependsOn(mergeJars) + + it.doLast { + println("\n==== bundle${capitalizedVariantName}LocalLintAar doLast ====\n") + } } bundleTask.configure { + println("\n==== mergeClassesAndJars ${bundleTask.name} Configured\n") it.dependsOn(mergeJars) + + it.doLast { + println("\n==== mergeClassesAndJars ${bundleTask.name} doLast ====\n") + } } } } private fun explodeArtifactFiles( - artifacts: Collection, + artifacts: List, prepareTask: TaskProvider, bundleTask: TaskProvider, ) { for (artifact in artifacts) { - when (artifact.type) { - ARTIFACT_TYPE_JAR -> jarFiles.add(artifact.file) - ARTIFACT_TYPE_AAR -> processAar(artifact, prepareTask, bundleTask) - } +// when (artifact.type) { +// ARTIFACT_TYPE_JAR -> jarFiles.add(artifact.file) +// ARTIFACT_TYPE_AAR -> processAar(artifact, prepareTask, bundleTask) +// } + processAar(artifact, prepareTask, bundleTask) } } private fun processAar( - artifact: ResolvedArtifact, + artifact: UnresolvedArtifactInfo, prepareTask: TaskProvider, bundleTask: TaskProvider, ) { @@ -130,41 +159,65 @@ class VariantProcessor(private val variant: LibraryVariant) : BaseProject() { artifact, variant.name, ) + aarLibraries.add(archiveLibrary) aarLibrariesProperty.add(archiveLibrary) - val dependencies = variantHelper.getTaskDependencies(artifact) val zipFolder = archiveLibrary.getExplodedAarRootDir() zipFolder.mkdirs() val explodeTask = getExplodeTask(zipFolder, artifact) - explodeTask.dependsOn(if (dependencies.isEmpty()) prepareTask else dependencies.first()) + if (explodeTask != null) { + val dependencies = artifact.dependencies + + val selectedTask = if (dependencies?.isEmpty() == true) prepareTask else dependencies?.first() + + println("=== selectedTask $selectedTask") + explodeTask.dependsOn(selectedTask) + + val javacTask = variantHelper.getJavaCompileTask() + javacTask.dependsOn(explodeTask) + + bundleTask.configure { + println("\n==== processAar ${bundleTask.name} Configured\n") + it.dependsOn(explodeTask) - val javacTask = variantHelper.getJavaCompileTask() - javacTask.dependsOn(explodeTask) + it.doLast { + println("\n==== processAar ${bundleTask.name} doLast ====\n") + } + } - bundleTask.configure { - it.dependsOn(explodeTask) + explodeTasks.add(explodeTask) } - explodeTasks.add(explodeTask) } private fun getExplodeTask( zipFolder: File, - artifact: ResolvedArtifact, - ): Copy { - val group = artifact.moduleVersion.id.group.replaceFirstChar(Char::titlecase) - val name = artifact.name.replaceFirstChar(Char::titlecase) + artifact: UnresolvedArtifactInfo, + ): Copy? { + val group = artifact.moduleGroup.replaceFirstChar(Char::titlecase) + val name = artifact.moduleName.replaceFirstChar(Char::titlecase) val taskName = "explode$group$name$capitalizedVariantName" - val explodeTask = - project.tasks.create(taskName, Copy::class.java) { - it.from(project.zipTree(artifact.file.absolutePath)) - it.into(zipFolder) - it.doFirst { - zipFolder.deleteRecursively() + if (project.tasks.findByName(taskName) == null) { + val explodeTask = + project.tasks.create(taskName, Copy::class.java) { + println("\n==== $taskName Configured\n") + it.from(project.zipTree(artifact.file.absolutePath)) + it.into(zipFolder) + + it.doFirst { + println("\n==== $taskName -- doFirst\n") + zipFolder.deleteRecursively() + } + + it.doLast { + println("\n==== $taskName -- doLast\n") + } } - } - return explodeTask + return explodeTask + } + + return null } } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt index 891de00f..64382853 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt @@ -102,11 +102,16 @@ class VariantTaskProvider(private val variantHelper: VariantHelper) : BaseProjec "merge${capitalizedVariantName}Manifest", ManifestMerger::class.java, ) { + println("\n==== merge${capitalizedVariantName}Manifest Configured\n") it.setGradleVersion(project.gradle.gradleVersion) it.setGradlePluginVersion(Utils.getAGPVersion()) it.setMainManifestFile(manifestOutput) it.setSecondaryManifestFiles(inputManifests) it.setOutputFile(manifestOutput) + + it.doLast { + println("\n==== merge${capitalizedVariantName}Manifest doLast ====\n") + } } processManifestTask.dependsOn(explodeTasks) @@ -156,7 +161,12 @@ class VariantTaskProvider(private val variantHelper: VariantHelper) : BaseProjec } extractDeepLinks.configure { + println("\n==== extractDeepLinks Configured\n") it.dependsOn(explodeTasks) + + it.doLast { + println("\n==== extractDeepLinks doLast ====\n") + } } } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ArtifactRegistrationTask.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ArtifactRegistrationTask.kt new file mode 100644 index 00000000..0a5cf8fc --- /dev/null +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ArtifactRegistrationTask.kt @@ -0,0 +1,27 @@ +package com.callstack.react.brownfield.shared + +import com.callstack.react.brownfield.artifacts.ArtifactsResolver +import org.gradle.api.DefaultTask +import org.gradle.api.artifacts.Configuration +import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.OutputFile +import org.gradle.api.tasks.TaskAction +import java.io.File + +abstract class ProcessArtifactsTask: DefaultTask() { + + @get:OutputFile + val outputArtifacts: ListProperty = project.objects.listProperty(UnresolvedArtifactInfo::class.java) + + @InputFiles + val artifactsResolver: Property = project.objects.property(ArtifactsResolver::class.java) + + + @TaskAction + fun run() { + println("=== ProcessArtifactsTask ===") + artifactsResolver.get().processDefaultDependencies() + } +} \ No newline at end of file diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ModuleInfo.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ModuleInfo.kt new file mode 100644 index 00000000..312b6a2a --- /dev/null +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ModuleInfo.kt @@ -0,0 +1,26 @@ +package com.callstack.react.brownfield.shared + +import org.gradle.api.Task +import java.io.File + +interface ModuleInfo { + val moduleGroup: String + val moduleName: String + val moduleVersion: String + + val file: File + + val type: String + get() = "aar" + + val dependencies: Set? +} + +data class UnresolvedArtifactInfo( + override val moduleGroup: String, + override val moduleName: String, + override val moduleVersion: String, + override val file: File, + override val dependencies: Set? +) : ModuleInfo + diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ProcessArtifactTask.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ProcessArtifactTask.kt new file mode 100644 index 00000000..b44faa55 --- /dev/null +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ProcessArtifactTask.kt @@ -0,0 +1,4 @@ +package com.callstack.react.brownfield.shared + +class ProcessArtifactTask { +} \ No newline at end of file diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/AndroidArchiveLibrary.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/AndroidArchiveLibrary.kt index c83a669e..bf776b27 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/AndroidArchiveLibrary.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/AndroidArchiveLibrary.kt @@ -1,6 +1,7 @@ package com.callstack.react.brownfield.utils import com.callstack.react.brownfield.shared.Logging +import com.callstack.react.brownfield.shared.UnresolvedArtifactInfo import org.gradle.api.Project import org.gradle.api.artifacts.ResolvedArtifact import java.io.File @@ -9,21 +10,20 @@ import javax.xml.parsers.DocumentBuilderFactory class AndroidArchiveLibrary( private val project: Project, - artifact: ResolvedArtifact, + artifact: UnresolvedArtifactInfo, private val variantName: String, ) { private var packageName: String? = null - private val artifact: ResolvedArtifact = + private val artifact: UnresolvedArtifactInfo = requireNotNull(artifact.takeIf { it.type == "aar" }) { "Only Aar is accepted as an artifact" } - private fun getArtifactName() = artifact.moduleVersion.id.name + private fun getArtifactName() = artifact.moduleName fun getExplodedAarRootDir(): File { val explodedRootDir = File("${project.layout.buildDirectory.get()}/intermediates/exploded-aar") - val id = artifact.moduleVersion.id - return File(explodedRootDir, "${id.group}/${id.name}/${id.version}/$variantName") + return File(explodedRootDir, "${artifact.moduleGroup}/${artifact.moduleName}/${artifact.moduleVersion}/$variantName") } @Synchronized From 93f742d5bf213521ccc01b78b8836d46e15b6309 Mon Sep 17 00:00:00 2001 From: Hur Ali Date: Mon, 19 Jan 2026 21:32:25 +0500 Subject: [PATCH 02/12] feat: second approach by exposing custom tasks - WIP --- apps/RNApp/package.json | 2 +- .../react/brownfield/build.gradle.kts | 2 + .../brownfield/artifacts/ArtifactsResolver.kt | 65 +++-- .../brownfield/artifacts/FlavorArtifact.kt | 95 +------ .../brownfield/plugin/RClassTransformer.kt | 8 +- .../brownfield/plugin/RNBrownfieldPlugin.kt | 247 ++++++++++++++++-- .../react/brownfield/plugin/RNSourceSets.kt | 1 + .../brownfield/processors/JNILibsProcessor.kt | 4 +- .../processors/ProguardProcessor.kt | 4 - .../brownfield/processors/VariantHelper.kt | 10 +- .../brownfield/processors/VariantProcessor.kt | 166 +----------- .../processors/VariantTaskProvider.kt | 33 +-- .../shared/ArtifactRegistrationTask.kt | 56 +++- .../brownfield/shared/BundleTaskProvider.kt | 57 ++++ .../react/brownfield/shared/ExplodeAarTask.kt | 11 + .../react/brownfield/shared/GenerateTPLAar.kt | 11 + .../react/brownfield/shared/JsonInstance.kt | 11 + .../shared/MergeClassesAndJarsTask.kt | 11 + .../react/brownfield/shared/ModuleInfo.kt | 12 +- .../brownfield/shared/ProcessArtifactTask.kt | 47 +++- .../brownfield/utils/AndroidArchiveLibrary.kt | 18 +- .../brownfield/utils/DirectoryManager.kt | 2 +- 22 files changed, 514 insertions(+), 359 deletions(-) create mode 100644 gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/BundleTaskProvider.kt create mode 100644 gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ExplodeAarTask.kt create mode 100644 gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/GenerateTPLAar.kt create mode 100644 gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/JsonInstance.kt create mode 100644 gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/MergeClassesAndJarsTask.kt diff --git a/apps/RNApp/package.json b/apps/RNApp/package.json index 9ea9b5d9..6899cac5 100644 --- a/apps/RNApp/package.json +++ b/apps/RNApp/package.json @@ -8,7 +8,7 @@ "build:example:android-rn": "react-native build-android", "build:example:ios-rn": "react-native build-ios", "build:aar:dryRun": "cd android && ./gradlew :brownfieldlib:assembleRelease --dry-run", - "build:aar": "cd android && ./gradlew :brownfieldlib:assembleRelease", + "build:aar": "cd android && ./gradlew :brownfieldlib:processArtifacts :brownfieldlib:assembleRelease", "build:scan": "cd android && ./gradlew :brownfieldlib:assembleRelease --scan", "lint": "eslint .", "start": "react-native start", diff --git a/gradle-plugins/react/brownfield/build.gradle.kts b/gradle-plugins/react/brownfield/build.gradle.kts index c4b0a2d1..6736de98 100644 --- a/gradle-plugins/react/brownfield/build.gradle.kts +++ b/gradle-plugins/react/brownfield/build.gradle.kts @@ -5,6 +5,7 @@ plugins { alias(libs.plugins.detekt) `maven-publish` signing + kotlin("plugin.serialization") version "1.9.24" } ktlint { @@ -82,6 +83,7 @@ dependencies { implementation(libs.agp) implementation(libs.common) implementation(libs.asm.commons) + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3") } tasks.named("detekt").configure { diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/ArtifactsResolver.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/ArtifactsResolver.kt index 18bc44d4..e6ac2e57 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/ArtifactsResolver.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/ArtifactsResolver.kt @@ -10,6 +10,7 @@ package com.callstack.react.brownfield.artifacts +import com.android.build.api.variant.AndroidComponentsExtension import com.android.build.gradle.LibraryExtension import com.android.build.gradle.api.LibraryVariant import com.callstack.react.brownfield.plugin.ProjectConfigurations.Companion.CONFIG_NAME @@ -18,10 +19,12 @@ import com.callstack.react.brownfield.processors.VariantHelper import com.callstack.react.brownfield.processors.VariantProcessor import com.callstack.react.brownfield.processors.VariantTaskProvider import com.callstack.react.brownfield.shared.BaseProject +import com.callstack.react.brownfield.shared.BundleTaskProvider import com.callstack.react.brownfield.shared.GradleProps import com.callstack.react.brownfield.shared.UnresolvedArtifactInfo import com.callstack.react.brownfield.utils.Extension import com.callstack.react.brownfield.utils.Utils +import org.gradle.api.Project import org.gradle.api.artifacts.ArtifactCollection import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.component.ModuleComponentIdentifier @@ -48,8 +51,8 @@ class ArtifactsResolver( embedDefaultDependencies("implementation") } - fun processArtifacts() { - generateArtifacts() + fun processArtifacts(): MutableList { + return generateArtifacts() } private fun embedExpoDependencies() { @@ -106,23 +109,29 @@ class ArtifactsResolver( } } - private fun generateArtifacts() { + private fun generateArtifacts(): MutableList { + // store the artifacts which can be variant aware including flavors + val artifacts = mutableSetOf() baseProject.project.extensions.getByType(LibraryExtension::class.java).libraryVariants.all { variant -> - val artifacts = mutableListOf() + val artifacts1 = mutableListOf() configurations.forEach { configuration -> if (isEmbedConfig(configuration, variant)) { - val resolvedArtifacts = resolveArtifacts(configuration) - artifacts.addAll(handleUnResolvedArtifacts(configuration, variant, resolvedArtifacts)) +// val resolvedArtifacts = resolveArtifacts(configuration) + val res = handleUnResolvedArtifacts(configuration, variant) + artifacts.addAll(res) + artifacts1.addAll(res) } } if (artifacts.isNotEmpty()) { val processor = VariantProcessor(variant) processor.project = baseProject.project - processor.processVariant(artifacts) + processor.processVariant(artifacts1) } } + + return artifacts.toMutableList() } private fun isEmbedConfig( @@ -152,20 +161,20 @@ class ArtifactsResolver( private fun handleUnResolvedArtifacts( configuration: Configuration, variant: LibraryVariant, - artifacts: ArtifactCollection, ): List { val unMatchedArtifacts = mutableListOf() - val firstLevelIds = - artifacts - .map { it.id.componentIdentifier.displayName } - .toSet() +// val firstLevelIds = +// artifacts +// .map { it.id.componentIdentifier.displayName } +// .toSet() + val firstLevelIds = setOf() val resolutionResult = configuration.incoming.resolutionResult resolutionResult.root.dependencies.forEach { if (it is ResolvedDependencyResult) { when (val id = it.selected.id) { is ModuleComponentIdentifier -> { -// println("===----- module ${id.moduleIdentifier.name} ${id.displayName} === ${firstLevelIds}") +// println("===----- module ${id.moduleIdentifier.name} ${id.displayName} ") if (id.displayName !in firstLevelIds) { // unMatchedArtifacts.add( // UnresolvedArtifactInfo( @@ -178,14 +187,15 @@ class ArtifactsResolver( } is ProjectComponentIdentifier -> { val depProj = baseProject.project.project(id.projectPath) +// println("===----- project ${id.projectName} ${id.displayName} -- path ${baseProject.project.file(id.projectName).absolutePath}") if (id.displayName !in firstLevelIds) { -// id. unMatchedArtifacts.add(UnresolvedArtifactInfo( depProj.group.toString(), depProj.name, depProj.version.toString(), - baseProject.project.file(id.projectName), - mutableSetOf() + baseProject.project.file(id.projectName).absolutePath, + mutableSetOf(), + null, )) } } @@ -197,17 +207,22 @@ class ArtifactsResolver( variantHelper.project = baseProject.project val variantTaskProvider = VariantTaskProvider(variantHelper) variantTaskProvider.project = baseProject.project - val flavorArtifact = FlavorArtifact(variant, variantTaskProvider, configuration) + val flavorArtifact = FlavorArtifact(variant, configuration) flavorArtifact.project = baseProject.project + val bundleTaskProvider = BundleTaskProvider(variantTaskProvider) + val unMatchedArtifacts1 = mutableListOf() unMatchedArtifacts.forEach { artifact -> + val artifactProject = getArtifactProject(artifact) + val bundleProvider = artifactProject?.let { bundleTaskProvider.getBundleTask(it, variant) } + val resolvedArtifact = flavorArtifact.createFlavorArtifact( artifact, - calculatedValueContainerFactory, fileResolver, taskDependencyFactory, + bundleProvider, ) when (val asd = resolvedArtifact.id) { @@ -217,13 +232,23 @@ class ArtifactsResolver( artifact.moduleGroup, artifact.moduleName, artifact.moduleVersion, - resolvedArtifact.file, - deps + resolvedArtifact.file.absolutePath, + deps.map { it.path }.toSet(), + bundleProvider?.name, )) + +// println("\n=== resolved artttt ${resolvedArtifact.file.absolutePath} -- ${deps.first().name}\n") } } } return unMatchedArtifacts1 } + + + private fun getArtifactProject(unResolvedArtifact: UnresolvedArtifactInfo): Project? { + return baseProject.project.rootProject.allprojects.find { p -> + unResolvedArtifact.moduleName == p.name && unResolvedArtifact.moduleGroup == p.group.toString() + } + } } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/FlavorArtifact.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/FlavorArtifact.kt index 9782309d..c4a3c7e0 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/FlavorArtifact.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/FlavorArtifact.kt @@ -38,55 +38,22 @@ import org.gradle.internal.model.CalculatedValueContainerFactory import java.io.File class FlavorArtifact(private val variant: LibraryVariant, - private val variantTaskProvider: VariantTaskProvider, private val configuration: Configuration) : BaseProject() { fun createFlavorArtifact( unResolvedArtifact: UnresolvedArtifactInfo, - calculatedValueContainerFactory: CalculatedValueContainerFactory, fileResolver: FileResolver, taskDependencyFactory: TaskDependencyFactory, + bundleTaskProvider: TaskProvider?, ): ResolvedArtifactResult { - val artifactProject = getArtifactProject(unResolvedArtifact) - val bundleProvider: TaskProvider? = - artifactProject?.let { getBundleTaskProvider(it, variant) } - - val capitalizedName = variant.name.replaceFirstChar(Char::titlecase) - -// val bTask = project.tasks.named("transform${capitalizedName}ClassesWithAsm") -// bTask.configure { -// it.mustRunAfter("${artifactProject?.path}:${bundleProvider?.name}") -// } - - val mTask = artifactProject?.tasks?.named("${bundleProvider?.name}") - mTask?.configure { - println("\n==== ${artifactProject.path}${mTask.name} Configured\n") - - it.doFirst { - println("\n=== ${artifactProject.path}${mTask.name} doFirst\n") - } - - it.doLast { - println("\n=== ${artifactProject.path}${mTask.name} doLast\n") - } - } - - // preBuild -- transform${capitalizedName}ClassesWithAsm - project.tasks.named("preBuild").configure { - println("\n==== preBuild Configured Second\n") - it.dependsOn(mTask) - - it.doLast { - println("\n==== preBuild Configured Second -> doLast\n") - } - } - - val artifactFile = createArtifactFile(bundleProvider?.get() as Task) + val artifactFile = createArtifactFile(bundleTaskProvider?.get() as Task) val artifactName = DefaultIvyArtifactName(artifactFile.name, "aar", "") +// "${artifactProject?.path}:${bundleProvider?.name}" + return DefaultResolvedArtifactResult( PublishArtifactLocalArtifactMetadata( { artifactName.name }, - LazyPublishArtifact(bundleProvider, fileResolver, taskDependencyFactory), + LazyPublishArtifact(bundleTaskProvider, fileResolver, taskDependencyFactory), ), configuration.attributes, ImmutableCapabilities.EMPTY, @@ -100,56 +67,4 @@ class FlavorArtifact(private val variant: LibraryVariant, val packageLibraryProvider = bundle as Zip return File(packageLibraryProvider.destinationDirectory.get().asFile, packageLibraryProvider.archiveFileName.get()) } - - private fun getBundleTaskProvider( - project: Project, - variant: LibraryVariant, - ): TaskProvider? { - var bundleTaskProvider: TaskProvider? = null - val androidExtension = project.extensions.getByType(LibraryExtension::class.java) - - androidExtension.libraryVariants.find { - if (it.name == variant.name || it.name == variant.buildType.name) { - bundleTaskProvider = variantTaskProvider.bundleTaskProvider(project, it.name) - } - - if (bundleTaskProvider == null) { - val flavor = if (variant.productFlavors.isEmpty()) variant.mergedFlavor else variant.productFlavors.first() - try { - val missingDimensionStrategies = androidExtension.productFlavors.getByName(flavor.name).missingDimensionStrategies - - missingDimensionStrategies.entries.find { entry -> - val toDimension = entry.key - val requestedValues = listOf(entry.value.requested) - val toFlavors = requestedValues + entry.value.fallbacks - val subFlavor = - if (it.productFlavors.isEmpty()) { - it.mergedFlavor - } else { - it.productFlavors.first() - } - toFlavors.firstOrNull { toFlavor -> - val isDimensionEqual = toDimension == subFlavor.dimension - val isFlavorEqual = toFlavor == subFlavor.name - val isBuildTypeEqual = variant.buildType.name == it.buildType.name - if (isDimensionEqual && isFlavorEqual && isBuildTypeEqual) { - bundleTaskProvider = variantTaskProvider.bundleTaskProvider(project, it.name) - } - false - } != null - } != null - } catch (_: Exception) {} - } - - bundleTaskProvider != null - } - - return bundleTaskProvider - } - - private fun getArtifactProject(unResolvedArtifact: UnresolvedArtifactInfo): Project? { - return project.rootProject.allprojects.find { p -> - unResolvedArtifact.moduleName == p.name && unResolvedArtifact.moduleGroup == p.group.toString() - } - } } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RClassTransformer.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RClassTransformer.kt index 81690178..f9b4dee4 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RClassTransformer.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RClassTransformer.kt @@ -39,10 +39,10 @@ object RClassTransformer : BaseProject() { InstrumentationScope.PROJECT, ) { params -> params.namespace.set(variant.namespace) -// params.libraryNamespaces.set( -// variantPackagesProperty.getting(variant.name) -// .map { list -> list.map { it.getPackageName() }.toList() }, -// ) + params.libraryNamespaces.set( + variantPackagesProperty.getting(variant.name) + .map { list -> list.map { it.getPackageName() }.toList() }, + ) } println("=== project variant -- ${variant.name}") diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt index b9fdd494..89d0d6e7 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt @@ -1,21 +1,37 @@ package com.callstack.react.brownfield.plugin import com.android.build.api.variant.LibraryAndroidComponentsExtension +import com.android.build.gradle.LibraryExtension import com.android.build.gradle.internal.crash.afterEvaluate +import com.android.build.gradle.internal.tasks.factory.dependsOn import com.callstack.react.brownfield.artifacts.ArtifactsResolver +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.ArtifactRegistrationTask import com.callstack.react.brownfield.shared.BaseProject import com.callstack.react.brownfield.shared.Constants.PROJECT_ID +import com.callstack.react.brownfield.shared.ExplodeAarTask +import com.callstack.react.brownfield.shared.GenerateTPLAar +import com.callstack.react.brownfield.shared.JsonInstance import com.callstack.react.brownfield.shared.Logging +import com.callstack.react.brownfield.shared.MergeClassesAndJarsTask +import com.callstack.react.brownfield.shared.ProcessArtifactsTask +import com.callstack.react.brownfield.shared.UnresolvedArtifactInfo +import com.callstack.react.brownfield.utils.AndroidArchiveLibrary import com.callstack.react.brownfield.utils.DirectoryManager import com.callstack.react.brownfield.utils.Extension import com.callstack.react.brownfield.utils.Utils import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.ProjectConfigurationException +import org.gradle.api.Task import org.gradle.api.internal.file.FileResolver import org.gradle.api.internal.tasks.TaskDependencyFactory +import org.gradle.api.tasks.Copy +import org.gradle.api.tasks.TaskProvider import org.gradle.internal.model.CalculatedValueContainerFactory +import java.io.File import javax.inject.Inject class RNBrownfieldPlugin @@ -29,6 +45,8 @@ constructor( private lateinit var projectConfigurations: ProjectConfigurations private lateinit var artifactsResolver: ArtifactsResolver + private lateinit var project: Project + override fun apply(project: Project) { verifyAndroidPluginApplied(project) @@ -36,6 +54,7 @@ constructor( println("=== Applying $PROJECT_ID ===") + this.project = project // Configure projectConfigurations.configure() RNSourceSets.configure(project, extension) @@ -55,52 +74,226 @@ constructor( val baseProject = BaseProject() baseProject.project = project + DirectoryManager.project = project artifactsResolver = ArtifactsResolver(projectConfigurations.getConfigurations(), baseProject, extension) artifactsResolver.calculatedValueContainerFactory = calculatedValueContainerFactory artifactsResolver.taskDependencyFactory = taskDependencyFactory artifactsResolver.fileResolver = fileResolver artifactsResolver.processDefaultDependencies() +// artifactsResolver.processArtifacts() + + val processArtifactsTask = project.tasks.register("processArtifacts", ProcessArtifactsTask::class.java) { + it.artifactsResolver.set(artifactsResolver) + it.outputFile.set(project.layout.buildDirectory.file("artifacts.txt")) + it.artifactOutput.set(project.layout.buildDirectory.file("artifacts-list.jsonl")) + } + + val artifactRegistrationTask = project.tasks.register("artifactRegistration", + ArtifactRegistrationTask::class.java) { +// it.dependsOn(processArtifactsTask) +// it.inputArtifacts.set(processArtifactsTask.get().outputArtifacts) + it.inputFile.set(processArtifactsTask.flatMap { t -> t.outputFile }) - artifactsResolver.processArtifacts() -// project.tasks.register("processArtifacts") { -// it.doFirst { -// artifactsResolver.processArtifacts() +// processArtifactsTask.get().outputArtifacts.get().forEach { it1 -> +// it.dependsOn(":${it1.moduleName}:bundleReleaseAar") // } -// } + } + + + /** + * Trigger the processVariants internal here to register the tasks + * - Can not do this because they require artifacts and we only get those in preBuild + * - let's try invoking those in preBuild configuration phase? + * + * - add explode tasks to explode.txt as part of processArtifacts + * - read that file to register task dependency in preBuild + * - basically what can be evaluated earlier in processArtifacts should be moved there and later read in preBuild + * - Also once this is done, invoke a function like processVariant directly in preBuild.configure phase to register + * all the tasks required. + * */ + + project.tasks.register("generateTPLAar", GenerateTPLAar::class.java) { task -> + task.inputTaskList.set(processArtifactsTask.get().outputFile) + + val file = task.inputTaskList.get().asFile + if (file.exists()) { + file.readLines().forEach { line -> + val lineSplits = line.split(",") + + val projectPath = lineSplits[0] + val taskName = lineSplits[1] + val artifactProject = project.rootProject.project(projectPath) + + artifactProject.tasks.findByName(taskName)?.let { task.dependsOn(it) } + } + } + } + + project.tasks.register("explodeAarTask", ExplodeAarTask::class.java) { task -> + task.inputArtifactListFile.set(processArtifactsTask.get().artifactOutput) + + task.doFirst { + project.extensions.getByType(LibraryExtension::class.java).libraryVariants.all { variant -> + val variantHelper = VariantHelper(variant) + variantHelper.project = project + + variantHelper.classesMergeTaskDoFirst( + DirectoryManager.getMergeClassDirectory( + variant + ) + ) + } + } + + task.doLast { + val file = task.inputArtifactListFile.get().asFile + val artifacts = readArtifacts(file) + project.extensions.getByType(LibraryExtension::class.java).libraryVariants.all { variant -> + val variantHelper = VariantHelper(variant) + variantHelper.project = project + + val aarLibraries = mutableListOf() + artifacts.forEach { art -> + val archiveLibrary = + AndroidArchiveLibrary( + this.project, + art, + variant.name, + ) + + aarLibraries.add(archiveLibrary) -// val processArtifactsTask = project.tasks.register("processArtifacts") { -// println("==== processArtifact Configured ====") + val zipFolder = archiveLibrary.getExplodedAarRootDir() + zipFolder.mkdirs() + + project.copy { it1 -> + zipFolder.deleteRecursively() + it1.from(project.zipTree(art.file)) + it1.into(zipFolder) + } + } + + variantHelper.classesMergeTaskDoLast(DirectoryManager.getMergeClassDirectory(variant), aarLibraries, mutableListOf()) + } + } + } + +// project.extensions.getByType(LibraryExtension::class.java).libraryVariants.all { variant -> +// val variantHelper = VariantHelper(variant) +// variantHelper.project = project +// val capitalizedVariantName = variant.name.replaceFirstChar(Char::titlecase) // -//// it.dependsOn(":react-native-safe-area-context:bundleReleaseAar") -// it.doFirst { -// println("==== processArtifact doFirst ====") -// val baseProject = BaseProject() -// baseProject.project = project -// val artifactsResolver = ArtifactsResolver(projectConfigurations.getConfigurations(), baseProject, extension) -// artifactsResolver.calculatedValueContainerFactory = calculatedValueContainerFactory -// artifactsResolver.taskDependencyFactory = taskDependencyFactory -// artifactsResolver.fileResolver = fileResolver -// artifactsResolver.processArtifacts() -// } +// val mergeClassesTaskName = "mergeClasses$capitalizedVariantName" +// project.tasks.register(mergeClassesTaskName, MergeClassesAndJarsTask::class.java) { task -> +// task.inputArtifactListFile.set(processArtifactsTask.get().artifactOutput) // -// it.doLast { -// println("\n==== processArtifact doLast ====\n") +// task.doFirst { +// variantHelper.classesMergeTaskDoFirst( DirectoryManager.getMergeClassDirectory(variant)) +// } +// task.doLast { +// val file = task.inputArtifactListFile.get().asFile +// val artifacts = readArtifacts(file) +// +// val aarLibraries = mutableListOf() +// artifacts.forEach { +// aarLibraries.add(AndroidArchiveLibrary( +// project, +// it, +// variant.name, +// )) +// } +// variantHelper.classesMergeTaskDoLast(DirectoryManager.getMergeClassDirectory(variant), aarLibraries, mutableListOf()) +// } // } // } // + + project.tasks.named("preBuild").configure { preBuild -> + println("==== preBuild Configured first ====") + preBuild.doLast { + println("\n==== preBuild first -> doLast ====\n") + } + } + } + + private fun readArtifacts(file: File): List { + if (!file.exists()) return emptyList() + + return file.readLines() + .filter { it.isNotBlank() } + .map { JsonInstance.json.decodeFromString(it) } + } + + private fun processAar( + artifact: UnresolvedArtifactInfo, + bundleTask: TaskProvider, + variantName: String, + variantHelper: VariantHelper + ) { + val archiveLibrary = + AndroidArchiveLibrary( + this.project, + artifact, + variantName, + ) + +// aarLibraries.add(archiveLibrary) +// aarLibrariesProperty.add(archiveLibrary) + + val zipFolder = archiveLibrary.getExplodedAarRootDir() + zipFolder.mkdirs() + +// val explodeTask = getExplodeTask(zipFolder, artifact, variantName.replaceFirstChar(Char::titlecase)) +// if (explodeTask != null) { +// val dependencies = artifact.dependencies // -// project.tasks.named("preBuild").configure { -// println("==== preBuild Configured first ====") -// it.dependsOn(processArtifactsTask) -// -// it.doLast { -// println("\n==== preBuild first -> doLast ====\n") -// } +// if (dependencies?.isEmpty() == false) { +// println("=== selectedTask ${dependencies.first()}") +// explodeTask.dependsOn(dependencies.first()) // } +// +// val javacTask = variantHelper.getJavaCompileTask() +// javacTask.dependsOn(explodeTask) +// +//// bundleTask.dependsOn(explodeTask.name) +// +//// explodeTasks.add(explodeTask) +// } + } + + private fun getExplodeTask( + zipFolder: File, + artifact: UnresolvedArtifactInfo, + capitalizedVariantName: String + ): Copy? { + val group = artifact.moduleGroup.replaceFirstChar(Char::titlecase) + val name = artifact.moduleName.replaceFirstChar(Char::titlecase) + val taskName = "explode$group$name$capitalizedVariantName" + + if (project.tasks.findByName(taskName) == null) { + val explodeTask = + project.tasks.create(taskName, Copy::class.java) { + println("\n==== $taskName Configured\n") + it.from(project.zipTree(artifact.file)) + it.into(zipFolder) + + it.doFirst { + println("\n==== $taskName -- doFirst\n") + zipFolder.deleteRecursively() + } + + it.doLast { + println("\n==== $taskName -- doLast\n") + } + } + return explodeTask } + return null + } + private fun initializers(project: Project) { this.extension = project.extensions.create(Extension.NAME, Extension::class.java) RClassTransformer.project = project diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNSourceSets.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNSourceSets.kt index 25b5b850..0d08baf2 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNSourceSets.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNSourceSets.kt @@ -126,6 +126,7 @@ object RNSourceSets { val appProjectName = appProject.name project.tasks.register("copyAutolinkingSources", Copy::class.java) { + println("==== copyAutolink configured") val path = "generated/autolinking/src/main/java" it.dependsOn(":$appProjectName:generateAutolinkingPackageList") it.from("$appBuildDir/$path") diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/JNILibsProcessor.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/JNILibsProcessor.kt index 82760b3b..8522f70b 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/JNILibsProcessor.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/JNILibsProcessor.kt @@ -25,7 +25,6 @@ import java.io.File class JNILibsProcessor : BaseProject() { fun processJniLibs( aarLibraries: Collection, - explodeTasks: MutableList, variant: LibraryVariant, ) { val capitalizedVariantName = variant.name.replaceFirstChar(Char::titlecase) @@ -42,7 +41,6 @@ class JNILibsProcessor : BaseProject() { mergeJniLibsTask.configure { println("\n=== $taskName configured\n") - it.dependsOn(explodeTasks) it.dependsOn(copyTask) it.doFirst { @@ -87,6 +85,8 @@ class JNILibsProcessor : BaseProject() { project.rootProject .file("${project.name}/libs$capitalizedVariant") + println("==== IN copy so lib task") + return project.tasks.register("copy${capitalizedVariant}LibSources", Copy::class.java) { println("\n=== copy${capitalizedVariant}LibSource configured\n") diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ProguardProcessor.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ProguardProcessor.kt index 4c326f72..d29e4de4 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ProguardProcessor.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ProguardProcessor.kt @@ -26,7 +26,6 @@ class ProguardProcessor(variant: LibraryVariant) : BaseProject() { fun processConsumerFiles( aarLibs: Collection, - explodeTasks: MutableList, ) { val mergeTaskName = "merge${capitalizedVariantName}ConsumerProguardFiles" val mergeFileTask = project.tasks.named(mergeTaskName) @@ -36,7 +35,6 @@ class ProguardProcessor(variant: LibraryVariant) : BaseProject() { } mergeFileTask.configure { task -> - task.dependsOn(explodeTasks) task.doLast { val files = aarLibs.map { aarLib -> aarLib.getProguardRules() } val outputFile = it.outputs.files.singleFile @@ -47,14 +45,12 @@ class ProguardProcessor(variant: LibraryVariant) : BaseProject() { fun processGeneratedFiles( aarLibs: Collection, - explodeTasks: MutableList, ) { val mergeGenerateProguardTask: TaskProvider<*>? val mergeName = "merge${capitalizedVariantName}GeneratedProguardFiles" mergeGenerateProguardTask = project.tasks.named(mergeName) mergeGenerateProguardTask?.configure { task -> - task.dependsOn(explodeTasks) task.doLast { val files = aarLibs.map { it.getProguardRules() } val outputFile = it.outputs.files.singleFile diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantHelper.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantHelper.kt index 6633da12..d2c0c59b 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantHelper.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantHelper.kt @@ -73,7 +73,7 @@ class VariantHelper(private val variant: LibraryVariant) : BaseProject() { fun classesMergeTaskDoLast( outputDir: File, - aarLibraries: Collection, + aarLibraries: Collection, jarFiles: MutableList, ) { MergeProcessor.mergeClassesJarIntoClasses(project, aarLibraries, outputDir) @@ -106,7 +106,6 @@ class VariantHelper(private val variant: LibraryVariant) : BaseProject() { fun processResources( aarLibraries: Collection, - explodeTasks: MutableList, ) { val taskPath = "generate${capitalizedVariantName}Resources" val resourceGenTask = project.tasks.named(taskPath) @@ -115,11 +114,6 @@ class VariantHelper(private val variant: LibraryVariant) : BaseProject() { throw TaskNotFound("Task $taskPath not found") } - resourceGenTask.configure { - println("\n=== generate${capitalizedVariantName}Resources configured\n") - it.dependsOn(explodeTasks) - } - aarLibraries.forEach { variant.registerGeneratedResFolders( project.files(it.getResDir()), @@ -129,11 +123,9 @@ class VariantHelper(private val variant: LibraryVariant) : BaseProject() { fun processAssets( aarLibraries: Collection, - explodeTasks: MutableList, ) { val assetsTask = variant.mergeAssetsProvider.get() - assetsTask.dependsOn(explodeTasks) val androidExtension = project.extensions.getByName("android") as LibraryExtension assetsTask.doFirst { val filteredSourceSets = androidExtension.sourceSets.filter { it.name == variant.name } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt index afdef6ff..9853a538 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt @@ -36,7 +36,6 @@ class VariantProcessor(private val variant: LibraryVariant) : BaseProject() { private val aarLibraries = mutableListOf() private lateinit var aarLibrariesProperty: ListProperty private val jarFiles = mutableListOf() - private var mergeClassTask: TaskProvider? = null private fun setup() { variantHelper.project = project @@ -60,164 +59,17 @@ class VariantProcessor(private val variant: LibraryVariant) : BaseProject() { prepareTask.dependsOn(":app:createBundle${capitalizedVariantName}JsAndAssets") } - val bundleTask = variantTaskProvider.bundleTaskProvider(project, variant.name) - - explodeArtifactFiles(artifacts, prepareTask, bundleTask) - mergeClassesAndJars(bundleTask) +// val bundleTask = variantTaskProvider.bundleTaskProvider(project, variant.name) if (aarLibraries.isEmpty()) return - variantTaskProvider.processManifestTask(aarLibraries, explodeTasks) - variantHelper.processResources(aarLibraries, explodeTasks) - variantHelper.processAssets(aarLibraries, explodeTasks) - jniLibsProcessor.processJniLibs(aarLibraries, explodeTasks, variant) - proguardProcessor.processConsumerFiles(aarLibraries, explodeTasks) - proguardProcessor.processGeneratedFiles(aarLibraries, explodeTasks) - variantTaskProvider.processDataBinding(bundleTask, aarLibraries) - variantTaskProvider.processDeepLinkTasks(explodeTasks) - } - - private fun mergeClassesAndJars(bundleTask: TaskProvider) { - val syncLibTask = project.tasks.named(variantHelper.getSyncLibJarsTaskPath()) - val extractAnnotationsTask = project.tasks.named("extract${capitalizedVariantName}Annotations") - - mergeClassTask = variantTaskProvider.classesMergeTask(aarLibraries, jarFiles, explodeTasks) - syncLibTask.configure { - println("\n==== syncLibTask Configured\n") - it.dependsOn(mergeClassTask) - it.inputs.files(aarLibraries.map { aarLib -> aarLib.getLibsDir() }).withPathSensitivity( - PathSensitivity.RELATIVE, - ) - it.inputs.files(jarFiles).withPathSensitivity(PathSensitivity.RELATIVE) - - it.doLast { - println("\n==== syncLibTask doLast ====\n") - } - } - - project.tasks.named("transform${capitalizedVariantName}ClassesWithAsm").configure { - println("\n==== transformAsm Configured\n") - it.dependsOn(mergeClassTask) - - it.doLast { - println("\n==== transformAsm doLast ====\n") - } - } - - extractAnnotationsTask.configure { - println("\n==== extractAnnotationsTask Configured\n") - it.mustRunAfter(mergeClassTask) - - it.doLast { - println("\n==== extractAnnotationsTask doLast ====\n") - } - } - - if (!variant.buildType.isMinifyEnabled) { - val mergeJars = variantTaskProvider.jarMergeTask(syncLibTask, aarLibraries, jarFiles, explodeTasks) - project.tasks.named("bundle${capitalizedVariantName}LocalLintAar").configure { - println("\n==== bundle${capitalizedVariantName}LocalLintAar Configured\n") - it.dependsOn(mergeJars) - - it.doLast { - println("\n==== bundle${capitalizedVariantName}LocalLintAar doLast ====\n") - } - } - bundleTask.configure { - println("\n==== mergeClassesAndJars ${bundleTask.name} Configured\n") - it.dependsOn(mergeJars) - - it.doLast { - println("\n==== mergeClassesAndJars ${bundleTask.name} doLast ====\n") - } - } - } - } - - private fun explodeArtifactFiles( - artifacts: List, - prepareTask: TaskProvider, - bundleTask: TaskProvider, - ) { - for (artifact in artifacts) { -// when (artifact.type) { -// ARTIFACT_TYPE_JAR -> jarFiles.add(artifact.file) -// ARTIFACT_TYPE_AAR -> processAar(artifact, prepareTask, bundleTask) -// } - processAar(artifact, prepareTask, bundleTask) - } - } - - private fun processAar( - artifact: UnresolvedArtifactInfo, - prepareTask: TaskProvider, - bundleTask: TaskProvider, - ) { - val archiveLibrary = - AndroidArchiveLibrary( - project, - artifact, - variant.name, - ) - - aarLibraries.add(archiveLibrary) - aarLibrariesProperty.add(archiveLibrary) - - val zipFolder = archiveLibrary.getExplodedAarRootDir() - zipFolder.mkdirs() - - val explodeTask = getExplodeTask(zipFolder, artifact) - if (explodeTask != null) { - val dependencies = artifact.dependencies - - val selectedTask = if (dependencies?.isEmpty() == true) prepareTask else dependencies?.first() - - println("=== selectedTask $selectedTask") - explodeTask.dependsOn(selectedTask) - - val javacTask = variantHelper.getJavaCompileTask() - javacTask.dependsOn(explodeTask) - - bundleTask.configure { - println("\n==== processAar ${bundleTask.name} Configured\n") - it.dependsOn(explodeTask) - - it.doLast { - println("\n==== processAar ${bundleTask.name} doLast ====\n") - } - } - - explodeTasks.add(explodeTask) - } - } - - private fun getExplodeTask( - zipFolder: File, - artifact: UnresolvedArtifactInfo, - ): Copy? { - val group = artifact.moduleGroup.replaceFirstChar(Char::titlecase) - val name = artifact.moduleName.replaceFirstChar(Char::titlecase) - val taskName = "explode$group$name$capitalizedVariantName" - - if (project.tasks.findByName(taskName) == null) { - val explodeTask = - project.tasks.create(taskName, Copy::class.java) { - println("\n==== $taskName Configured\n") - it.from(project.zipTree(artifact.file.absolutePath)) - it.into(zipFolder) - - it.doFirst { - println("\n==== $taskName -- doFirst\n") - zipFolder.deleteRecursively() - } - - it.doLast { - println("\n==== $taskName -- doLast\n") - } - } - return explodeTask - } - - return null +// variantTaskProvider.processManifestTask(aarLibraries) +// variantHelper.processResources(aarLibraries) +// variantHelper.processAssets(aarLibraries) +// jniLibsProcessor.processJniLibs(aarLibraries, variant) +// proguardProcessor.processConsumerFiles(aarLibraries) +// proguardProcessor.processGeneratedFiles(aarLibraries) +// variantTaskProvider.processDataBinding(bundleTask, aarLibraries) +// variantTaskProvider.processDeepLinkTasks() } } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt index 64382853..cdbe6688 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt @@ -1,5 +1,6 @@ package com.callstack.react.brownfield.processors +import com.android.build.gradle.internal.tasks.factory.registerTask import com.callstack.react.brownfield.exceptions.TaskNotFound import com.callstack.react.brownfield.plugin.ManifestMerger import com.callstack.react.brownfield.shared.BaseProject @@ -20,15 +21,13 @@ class VariantTaskProvider(private val variantHelper: VariantHelper) : BaseProjec fun classesMergeTask( aarLibraries: Collection, jarFiles: MutableList, - explodeTasks: MutableList, - ): TaskProvider { + ): Task { val mergeClassesTaskName = "mergeClasses$capitalizedVariantName" val kotlinCompileTaskName = "compile${capitalizedVariantName}Kotlin" - return project.tasks.register(mergeClassesTaskName) { + return project.tasks.create(mergeClassesTaskName, Task::class.java) { it.outputs.upToDateWhen { false } - it.dependsOn(explodeTasks) it.dependsOn(variantHelper.getJavaCompileTask()) it.dependsOn(project.tasks.named(kotlinCompileTaskName)) @@ -37,14 +36,21 @@ class VariantTaskProvider(private val variantHelper: VariantHelper) : BaseProjec if (variant.buildType.isMinifyEnabled) { it.inputs.files(variantHelper.getLocalJarFiles(aarLibraries)).withPathSensitivity(PathSensitivity.RELATIVE) - it.inputs.files(jarFiles).withPathSensitivity(PathSensitivity.RELATIVE) +// it.inputs.files(jarFiles).withPathSensitivity(PathSensitivity.RELATIVE) } - val outputDir = DirectoryManager.getMergeClassDirectory(variant) - it.outputs.dir(outputDir) - - it.doFirst { variantHelper.classesMergeTaskDoFirst(outputDir) } - it.doLast { variantHelper.classesMergeTaskDoLast(outputDir, aarLibraries, jarFiles) } +// val outputDir = DirectoryManager.getMergeClassDirectory(variant) +// it.outputs.dir(outputDir) +// +// it.doFirst { +// println("===== DO FIRST CLASSES MERGE") +// +// variantHelper.classesMergeTaskDoFirst( DirectoryManager.getMergeClassDirectory(variant)) +// } +// it.doLast { +// println("===== DO LAST CLASSES MERGE") +// variantHelper.classesMergeTaskDoLast( DirectoryManager.getMergeClassDirectory(variant), aarLibraries, jarFiles) +// } } } @@ -52,10 +58,8 @@ class VariantTaskProvider(private val variantHelper: VariantHelper) : BaseProjec syncLibTask: TaskProvider, aarLibraries: Collection, jarFiles: MutableList, - explodeTasks: MutableList, ): TaskProvider { return project.tasks.register("mergeJars$capitalizedVariantName") { - it.dependsOn(explodeTasks) it.dependsOn(variantHelper.getJavaCompileTask()) it.mustRunAfter(syncLibTask) @@ -87,7 +91,6 @@ class VariantTaskProvider(private val variantHelper: VariantHelper) : BaseProjec fun processManifestTask( aarLibraries: Collection, - explodeTasks: MutableList, ) { val processManifestTask = variantHelper.getProcessManifest() val manifestOutput = @@ -114,7 +117,6 @@ class VariantTaskProvider(private val variantHelper: VariantHelper) : BaseProjec } } - processManifestTask.dependsOn(explodeTasks) processManifestTask.inputs.files(inputManifests) processManifestTask.doLast { manifestsMergeTask.get().doTaskAction() @@ -152,7 +154,7 @@ class VariantTaskProvider(private val variantHelper: VariantHelper) : BaseProjec } } - fun processDeepLinkTasks(explodeTasks: MutableList) { + fun processDeepLinkTasks() { val taskName = "extractDeepLinksForAar$capitalizedVariantName" val extractDeepLinks = project.tasks.named(taskName) @@ -162,7 +164,6 @@ class VariantTaskProvider(private val variantHelper: VariantHelper) : BaseProjec extractDeepLinks.configure { println("\n==== extractDeepLinks Configured\n") - it.dependsOn(explodeTasks) it.doLast { println("\n==== extractDeepLinks doLast ====\n") diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ArtifactRegistrationTask.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ArtifactRegistrationTask.kt index 0a5cf8fc..03019dc7 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ArtifactRegistrationTask.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ArtifactRegistrationTask.kt @@ -3,25 +3,65 @@ package com.callstack.react.brownfield.shared import com.callstack.react.brownfield.artifacts.ArtifactsResolver import org.gradle.api.DefaultTask import org.gradle.api.artifacts.Configuration +import org.gradle.api.file.RegularFileProperty import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Property +import org.gradle.api.tasks.InputFile import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.Internal import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.TaskAction import java.io.File -abstract class ProcessArtifactsTask: DefaultTask() { +abstract class ArtifactRegistrationTask: DefaultTask() { - @get:OutputFile - val outputArtifacts: ListProperty = project.objects.listProperty(UnresolvedArtifactInfo::class.java) - - @InputFiles - val artifactsResolver: Property = project.objects.property(ArtifactsResolver::class.java) + @get:Internal + abstract val inputArtifacts: ListProperty + @get:InputFile + abstract val inputFile: RegularFileProperty @TaskAction fun run() { - println("=== ProcessArtifactsTask ===") - artifactsResolver.get().processDefaultDependencies() + println("=== ArtifactRegistrationTask ===") + val lines = inputFile.get().asFile.readLines() + + lines.forEach { line -> + println("==== Line $line") + val lineSplits = line.split(",") + println("=== splits -- $lineSplits") + val projectPath = lineSplits[0] + val taskName = lineSplits[1] + println("=== proj name $projectPath") + val task = project.rootProject.project(projectPath).tasks.findByName(taskName) + if (task != null) { + println("Executing $line") + task.actions.forEach { action -> + action.execute(task) + } + } else { + println("Task $line not found") + } + } + +// project.gradle.taskGraph.whenReady { graph -> +// lines.forEach { name -> +// val task = project.tasks.findByName(name) +// if (task != null) { +// if (!graph.hasTask(task)) { +// println("Enqueueing task: $name") +// task.actions.forEach { action -> action.execute(task) } +// } else { +// println("Task $name is already in the graph, skipping manual execution") +// } +// } else { +// println("Task $name not found") +// } +// } +// } + +// inputArtifacts.get().forEach { +// println("====== From artifact reg task ${it.moduleName} - ${it.moduleGroup} - ${it.file.absolutePath}") +// } } } \ No newline at end of file diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/BundleTaskProvider.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/BundleTaskProvider.kt new file mode 100644 index 00000000..cae0210c --- /dev/null +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/BundleTaskProvider.kt @@ -0,0 +1,57 @@ +package com.callstack.react.brownfield.shared + +import com.android.build.gradle.LibraryExtension +import com.android.build.gradle.api.LibraryVariant +import com.callstack.react.brownfield.processors.VariantTaskProvider +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.tasks.TaskProvider + +class BundleTaskProvider(private val variantTaskProvider: VariantTaskProvider) { + fun getBundleTask( + project: Project, + variant: LibraryVariant, + ): TaskProvider? { + var bundleTaskProvider: TaskProvider? = null + val androidExtension = project.extensions.getByType(LibraryExtension::class.java) + + androidExtension.libraryVariants.find { + if (it.name == variant.name || it.name == variant.buildType.name) { + bundleTaskProvider = variantTaskProvider.bundleTaskProvider(project, it.name) + } + + if (bundleTaskProvider == null) { + val flavor = if (variant.productFlavors.isEmpty()) variant.mergedFlavor else variant.productFlavors.first() + try { + val missingDimensionStrategies = androidExtension.productFlavors.getByName(flavor.name).missingDimensionStrategies + + missingDimensionStrategies.entries.find { entry -> + val toDimension = entry.key + val requestedValues = listOf(entry.value.requested) + val toFlavors = requestedValues + entry.value.fallbacks + val subFlavor = + if (it.productFlavors.isEmpty()) { + it.mergedFlavor + } else { + it.productFlavors.first() + } + toFlavors.firstOrNull { toFlavor -> + val isDimensionEqual = toDimension == subFlavor.dimension + val isFlavorEqual = toFlavor == subFlavor.name + val isBuildTypeEqual = variant.buildType.name == it.buildType.name + if (isDimensionEqual && isFlavorEqual && isBuildTypeEqual) { + bundleTaskProvider = variantTaskProvider.bundleTaskProvider(project, it.name) + } + false + } != null + } != null + } catch (_: Exception) {} + } + + bundleTaskProvider != null + } + + return bundleTaskProvider + } + +} \ No newline at end of file diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ExplodeAarTask.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ExplodeAarTask.kt new file mode 100644 index 00000000..5c655f19 --- /dev/null +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ExplodeAarTask.kt @@ -0,0 +1,11 @@ +package com.callstack.react.brownfield.shared + +import org.gradle.api.DefaultTask +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.tasks.InputFile + +abstract class ExplodeAarTask: DefaultTask() { + + @get:InputFile + abstract val inputArtifactListFile: RegularFileProperty +} \ No newline at end of file diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/GenerateTPLAar.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/GenerateTPLAar.kt new file mode 100644 index 00000000..3242bfc1 --- /dev/null +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/GenerateTPLAar.kt @@ -0,0 +1,11 @@ +package com.callstack.react.brownfield.shared + +import org.gradle.api.DefaultTask +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.tasks.InputFile + +abstract class GenerateTPLAar: DefaultTask() { + + @get:InputFile + abstract val inputTaskList: RegularFileProperty +} \ No newline at end of file diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/JsonInstance.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/JsonInstance.kt new file mode 100644 index 00000000..fcb3eaa8 --- /dev/null +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/JsonInstance.kt @@ -0,0 +1,11 @@ +package com.callstack.react.brownfield.shared + +import kotlinx.serialization.json.Json + +object JsonInstance { + val json = Json { + prettyPrint = false + encodeDefaults = true + ignoreUnknownKeys = true + } +} \ No newline at end of file diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/MergeClassesAndJarsTask.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/MergeClassesAndJarsTask.kt new file mode 100644 index 00000000..cd8f36e0 --- /dev/null +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/MergeClassesAndJarsTask.kt @@ -0,0 +1,11 @@ +package com.callstack.react.brownfield.shared + +import org.gradle.api.DefaultTask +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.tasks.InputFile + +abstract class MergeClassesAndJarsTask: DefaultTask() { + + @get:InputFile + abstract val inputArtifactListFile: RegularFileProperty +} \ No newline at end of file diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ModuleInfo.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ModuleInfo.kt index 312b6a2a..1275859c 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ModuleInfo.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ModuleInfo.kt @@ -2,25 +2,29 @@ package com.callstack.react.brownfield.shared import org.gradle.api.Task import java.io.File +import kotlinx.serialization.Serializable interface ModuleInfo { val moduleGroup: String val moduleName: String val moduleVersion: String - val file: File + val file: String val type: String get() = "aar" - val dependencies: Set? + val dependencies: Set? + val bundleTaskName: String? } +@Serializable data class UnresolvedArtifactInfo( override val moduleGroup: String, override val moduleName: String, override val moduleVersion: String, - override val file: File, - override val dependencies: Set? + override val file: String, + override val dependencies: Set?, + override val bundleTaskName: String?, ) : ModuleInfo diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ProcessArtifactTask.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ProcessArtifactTask.kt index b44faa55..316b3c45 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ProcessArtifactTask.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ProcessArtifactTask.kt @@ -1,4 +1,49 @@ package com.callstack.react.brownfield.shared -class ProcessArtifactTask { +import com.callstack.react.brownfield.artifacts.ArtifactsResolver +import kotlinx.serialization.encodeToString +import org.gradle.api.DefaultTask +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.OutputFile +import org.gradle.api.tasks.TaskAction + +abstract class ProcessArtifactsTask: DefaultTask() { + + @get:OutputFile + abstract val outputFile: RegularFileProperty + + @get:OutputFile + abstract val artifactOutput: RegularFileProperty + + @get:Internal + abstract var artifactsList: ListProperty + + + @TaskAction + fun run() { + println("=== ProcessArtifactsTask ===") + val artifacts = artifactsResolver.get().processArtifacts() + val metaList = mutableListOf() + artifacts.forEach { +// if (it.bundleTaskName?.contains("Release") == true) { +// metaList.add("${it.moduleName},${it.bundleTaskName}") +// } + metaList.add("${it.moduleName},${it.bundleTaskName}") + } + outputFile.get().asFile.writeText(metaList.joinToString("\n")) + artifactOutput.get().asFile.writeText( + artifacts.joinToString("\n") { + JsonInstance.json.encodeToString(it) + } + ) +// artifactOutput.get().asFile.writeText(artifacts.joinToString("\n") { it.toString() }) + } + + @get:Internal + abstract val artifactsResolver: Property + } \ No newline at end of file diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/AndroidArchiveLibrary.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/AndroidArchiveLibrary.kt index bf776b27..3bac5d1a 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/AndroidArchiveLibrary.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/AndroidArchiveLibrary.kt @@ -1,5 +1,6 @@ package com.callstack.react.brownfield.utils +import com.android.build.gradle.LibraryExtension import com.callstack.react.brownfield.shared.Logging import com.callstack.react.brownfield.shared.UnresolvedArtifactInfo import org.gradle.api.Project @@ -28,21 +29,8 @@ class AndroidArchiveLibrary( @Synchronized fun getPackageName(): String { - if (packageName == null) { - val manifestFile = getManifestFile() - if (!manifestFile.exists()) { - throw FileNotFoundException("${getArtifactName()} module's AndroidManifest file not found") - } - - try { - val documentBuilderFactory = DocumentBuilderFactory.newInstance() - val document = documentBuilderFactory.newDocumentBuilder().parse(manifestFile) - packageName = document.documentElement.getAttribute("package") - } catch (e: IllegalStateException) { - Logging.log(e.stackTraceToString()) - } - } - return packageName!! + val androidExtension = project.rootProject.project(":${artifact.moduleName}").extensions.getByType(LibraryExtension::class.java) + return androidExtension.namespace!! } fun getManifestFile() = File(getExplodedAarRootDir(), "AndroidManifest.xml") diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/DirectoryManager.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/DirectoryManager.kt index aa40a0d2..bac333d5 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/DirectoryManager.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/DirectoryManager.kt @@ -18,7 +18,7 @@ import java.io.File object DirectoryManager : BaseProject() { fun getMergeClassDirectory(variant: LibraryVariant): File { - return project.file("$buildDir/intermediates/$INTERMEDIATES_TEMP_DIR/merge_classes/${variant.name}") + return File("$buildDir/intermediates/$INTERMEDIATES_TEMP_DIR/merge_classes/${variant.name}") } fun getKotlinMetaDirectory(variant: LibraryVariant): File { From b44fea1309f105417926f8cc5b9b3b15d82fe4e9 Mon Sep 17 00:00:00 2001 From: Hur Ali Date: Wed, 21 Jan 2026 20:40:47 +0500 Subject: [PATCH 03/12] feat: migrate manifest-merger and move others to explode-aar task --- .../brownfield/plugin/RClassTransformer.kt | 6 +- .../brownfield/plugin/RNBrownfieldPlugin.kt | 301 ++++++------------ .../react/brownfield/shared/ExplodeAarTask.kt | 57 ++++ ...geClassesAndJarsTask.kt => GeneralTask.kt} | 4 +- 4 files changed, 154 insertions(+), 214 deletions(-) rename gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/{MergeClassesAndJarsTask.kt => GeneralTask.kt} (61%) diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RClassTransformer.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RClassTransformer.kt index f9b4dee4..e2cd0e13 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RClassTransformer.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RClassTransformer.kt @@ -30,9 +30,7 @@ object RClassTransformer : BaseProject() { fun registerASMTransformation() { val components = project.extensions.getByType(AndroidComponentsExtension::class.java) val variantPackagesProperty = VariantPackagesProperty.getVariantPackagesProperty() - variantPackagesProperty.get().forEach { - println("=== variantPackagesProperty $it") - } + components.onVariants(components.selector().all()) { variant -> variant.instrumentation.transformClassesWith( RClassAsmTransformerFactory::class.java, @@ -45,7 +43,6 @@ object RClassTransformer : BaseProject() { ) } - println("=== project variant -- ${variant.name}") variant.instrumentation.setAsmFramesComputationMode(FramesComputationMode.COPY_FRAMES) } } @@ -71,7 +68,6 @@ object RClassTransformer : BaseProject() { classContext: ClassContext, nextClassVisitor: ClassVisitor, ): ClassVisitor { - println("\n==== INN HEREEE\n") val params = parameters.get() val namespace = params.namespace.get() val libraryNamespaces = params.libraryNamespaces.orElse(Collections.emptyList()).get() diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt index 89d0d6e7..df4716ec 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt @@ -1,21 +1,19 @@ package com.callstack.react.brownfield.plugin -import com.android.build.api.variant.LibraryAndroidComponentsExtension import com.android.build.gradle.LibraryExtension -import com.android.build.gradle.internal.crash.afterEvaluate -import com.android.build.gradle.internal.tasks.factory.dependsOn +import com.android.build.gradle.internal.LoggerWrapper +import com.android.build.gradle.internal.coverage.JacocoReportTask.JacocoReportWorkerAction.Companion.logger +import com.android.manifmerger.ManifestMerger2 +import com.android.manifmerger.ManifestProvider +import com.android.manifmerger.MergingReport +import com.android.utils.ILogger import com.callstack.react.brownfield.artifacts.ArtifactsResolver -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.ArtifactRegistrationTask import com.callstack.react.brownfield.shared.BaseProject import com.callstack.react.brownfield.shared.Constants.PROJECT_ID import com.callstack.react.brownfield.shared.ExplodeAarTask import com.callstack.react.brownfield.shared.GenerateTPLAar import com.callstack.react.brownfield.shared.JsonInstance -import com.callstack.react.brownfield.shared.Logging -import com.callstack.react.brownfield.shared.MergeClassesAndJarsTask import com.callstack.react.brownfield.shared.ProcessArtifactsTask import com.callstack.react.brownfield.shared.UnresolvedArtifactInfo import com.callstack.react.brownfield.utils.AndroidArchiveLibrary @@ -25,13 +23,13 @@ import com.callstack.react.brownfield.utils.Utils import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.ProjectConfigurationException -import org.gradle.api.Task import org.gradle.api.internal.file.FileResolver import org.gradle.api.internal.tasks.TaskDependencyFactory -import org.gradle.api.tasks.Copy -import org.gradle.api.tasks.TaskProvider import org.gradle.internal.model.CalculatedValueContainerFactory +import java.io.BufferedWriter import java.io.File +import java.io.FileOutputStream +import java.io.OutputStreamWriter import javax.inject.Inject class RNBrownfieldPlugin @@ -49,58 +47,38 @@ constructor( override fun apply(project: Project) { - verifyAndroidPluginApplied(project) - initializers(project) + verifyAndroidPluginApplied(project) + initializers(project) - println("=== Applying $PROJECT_ID ===") + println("=== Applying $PROJECT_ID ===") - this.project = project - // Configure - projectConfigurations.configure() - RNSourceSets.configure(project, extension) - RClassTransformer.registerASMTransformation() + this.project = project + // Configure + projectConfigurations.configure() + RNSourceSets.configure(project, extension) + RClassTransformer.registerASMTransformation() - if (Utils.isExampleLibrary(project.name)) { - return - } - // Register tasks -// project.tasks.named("preDebugBuild").configure { -// println("==== Hello Debug ====") -// } -// -// project.tasks.named("preReleaseBuild").configure { -// println("==== Hello Release ====") -// } + if (Utils.isExampleLibrary(project.name)) { + return + } val baseProject = BaseProject() baseProject.project = project DirectoryManager.project = project - artifactsResolver = ArtifactsResolver(projectConfigurations.getConfigurations(), baseProject, extension) + artifactsResolver = + ArtifactsResolver(projectConfigurations.getConfigurations(), baseProject, extension) artifactsResolver.calculatedValueContainerFactory = calculatedValueContainerFactory artifactsResolver.taskDependencyFactory = taskDependencyFactory artifactsResolver.fileResolver = fileResolver artifactsResolver.processDefaultDependencies() -// artifactsResolver.processArtifacts() - - val processArtifactsTask = project.tasks.register("processArtifacts", ProcessArtifactsTask::class.java) { - it.artifactsResolver.set(artifactsResolver) - it.outputFile.set(project.layout.buildDirectory.file("artifacts.txt")) - it.artifactOutput.set(project.layout.buildDirectory.file("artifacts-list.jsonl")) - } - - val artifactRegistrationTask = project.tasks.register("artifactRegistration", - ArtifactRegistrationTask::class.java) { -// it.dependsOn(processArtifactsTask) -// it.inputArtifacts.set(processArtifactsTask.get().outputArtifacts) - it.inputFile.set(processArtifactsTask.flatMap { t -> t.outputFile }) - - -// processArtifactsTask.get().outputArtifacts.get().forEach { it1 -> -// it.dependsOn(":${it1.moduleName}:bundleReleaseAar") -// } - } + val processArtifactsTask = + project.tasks.register("processArtifacts", ProcessArtifactsTask::class.java) { + it.artifactsResolver.set(artifactsResolver) + it.outputFile.set(project.layout.buildDirectory.file("artifacts.txt")) + it.artifactOutput.set(project.layout.buildDirectory.file("artifacts-list.jsonl")) + } /** * Trigger the processVariants internal here to register the tasks @@ -131,92 +109,45 @@ constructor( } } - project.tasks.register("explodeAarTask", ExplodeAarTask::class.java) { task -> - task.inputArtifactListFile.set(processArtifactsTask.get().artifactOutput) - - task.doFirst { - project.extensions.getByType(LibraryExtension::class.java).libraryVariants.all { variant -> - val variantHelper = VariantHelper(variant) - variantHelper.project = project - - variantHelper.classesMergeTaskDoFirst( - DirectoryManager.getMergeClassDirectory( - variant - ) - ) - } - } - - task.doLast { - val file = task.inputArtifactListFile.get().asFile - val artifacts = readArtifacts(file) - project.extensions.getByType(LibraryExtension::class.java).libraryVariants.all { variant -> - val variantHelper = VariantHelper(variant) - variantHelper.project = project - - val aarLibraries = mutableListOf() - artifacts.forEach { art -> - val archiveLibrary = - AndroidArchiveLibrary( - this.project, - art, - variant.name, - ) - - aarLibraries.add(archiveLibrary) + project.tasks.register("explodeAarTask", ExplodeAarTask::class.java) { task -> + task.inputArtifactListFile.set(processArtifactsTask.get().artifactOutput) + } - val zipFolder = archiveLibrary.getExplodedAarRootDir() - zipFolder.mkdirs() + // process manifest & merger task + project.extensions.getByType(LibraryExtension::class.java).libraryVariants.all { variant -> + val capitalizedVariantName = variant.name.replaceFirstChar(Char::titlecase) + val processManifestTask = variant.outputs.first().processManifestProvider.get() + + processManifestTask.doLast { + val artifacts = readArtifacts(processArtifactsTask.get().artifactOutput.get().asFile) + val aarLibraries = mutableListOf() + artifacts.forEach { art -> + val archiveLibrary = + AndroidArchiveLibrary( + this.project, + art, + variant.name, + ) + + aarLibraries.add(archiveLibrary) + } - project.copy { it1 -> - zipFolder.deleteRecursively() - it1.from(project.zipTree(art.file)) - it1.into(zipFolder) - } - } + // manifest-merger + val buildDir = project.layout.buildDirectory.get() + val manifestOutput = + project.file( + "$buildDir/intermediates/merged_manifest/${variant.name}/process${capitalizedVariantName}Manifest/AndroidManifest.xml", + ) - variantHelper.classesMergeTaskDoLast(DirectoryManager.getMergeClassDirectory(variant), aarLibraries, mutableListOf()) - } + val inputManifests = aarLibraries.map { it.getManifestFile() } + manifestMerger(manifestOutput, inputManifests, manifestOutput) } } -// project.extensions.getByType(LibraryExtension::class.java).libraryVariants.all { variant -> -// val variantHelper = VariantHelper(variant) -// variantHelper.project = project -// val capitalizedVariantName = variant.name.replaceFirstChar(Char::titlecase) -// -// val mergeClassesTaskName = "mergeClasses$capitalizedVariantName" -// project.tasks.register(mergeClassesTaskName, MergeClassesAndJarsTask::class.java) { task -> -// task.inputArtifactListFile.set(processArtifactsTask.get().artifactOutput) -// -// task.doFirst { -// variantHelper.classesMergeTaskDoFirst( DirectoryManager.getMergeClassDirectory(variant)) -// } -// task.doLast { -// val file = task.inputArtifactListFile.get().asFile -// val artifacts = readArtifacts(file) -// -// val aarLibraries = mutableListOf() -// artifacts.forEach { -// aarLibraries.add(AndroidArchiveLibrary( -// project, -// it, -// variant.name, -// )) -// } -// variantHelper.classesMergeTaskDoLast(DirectoryManager.getMergeClassDirectory(variant), aarLibraries, mutableListOf()) -// } -// } -// } -// - - project.tasks.named("preBuild").configure { preBuild -> - println("==== preBuild Configured first ====") - preBuild.doLast { - println("\n==== preBuild first -> doLast ====\n") - } - } + project.tasks.register("general", ExplodeAarTask::class.java) { task -> + task.inputArtifactListFile.set(processArtifactsTask.get().artifactOutput) } + } private fun readArtifacts(file: File): List { if (!file.exists()) return emptyList() @@ -226,90 +157,46 @@ constructor( .map { JsonInstance.json.decodeFromString(it) } } - private fun processAar( - artifact: UnresolvedArtifactInfo, - bundleTask: TaskProvider, - variantName: String, - variantHelper: VariantHelper - ) { - val archiveLibrary = - AndroidArchiveLibrary( - this.project, - artifact, - variantName, + private fun manifestMerger(mainManifestFile: File, secondaryManifestFiles: List, outputFile: File) { + val iLogger: ILogger = LoggerWrapper(logger) + val mergerInvoker = ManifestMerger2.newMerger(mainManifestFile, iLogger, ManifestMerger2.MergeType.LIBRARY) + val manifestProviders = mutableListOf() + + val filteredSecondaryManifests = secondaryManifestFiles.filter { it.exists() } + filteredSecondaryManifests.forEach { file -> + manifestProviders.add( + object : ManifestProvider { + override fun getManifest(): File = file.absoluteFile + override fun getName(): String = file.name + }, ) + } -// aarLibraries.add(archiveLibrary) -// aarLibrariesProperty.add(archiveLibrary) - - val zipFolder = archiveLibrary.getExplodedAarRootDir() - zipFolder.mkdirs() - -// val explodeTask = getExplodeTask(zipFolder, artifact, variantName.replaceFirstChar(Char::titlecase)) -// if (explodeTask != null) { -// val dependencies = artifact.dependencies -// -// if (dependencies?.isEmpty() == false) { -// println("=== selectedTask ${dependencies.first()}") -// explodeTask.dependsOn(dependencies.first()) -// } -// -// val javacTask = variantHelper.getJavaCompileTask() -// javacTask.dependsOn(explodeTask) -// -//// bundleTask.dependsOn(explodeTask.name) -// -//// explodeTasks.add(explodeTask) -// } - } - - private fun getExplodeTask( - zipFolder: File, - artifact: UnresolvedArtifactInfo, - capitalizedVariantName: String - ): Copy? { - val group = artifact.moduleGroup.replaceFirstChar(Char::titlecase) - val name = artifact.moduleName.replaceFirstChar(Char::titlecase) - val taskName = "explode$group$name$capitalizedVariantName" - - if (project.tasks.findByName(taskName) == null) { - val explodeTask = - project.tasks.create(taskName, Copy::class.java) { - println("\n==== $taskName Configured\n") - it.from(project.zipTree(artifact.file)) - it.into(zipFolder) - - it.doFirst { - println("\n==== $taskName -- doFirst\n") - zipFolder.deleteRecursively() - } + mergerInvoker.addManifestProviders(manifestProviders) + val mergingReport: MergingReport = mergerInvoker.merge() - it.doLast { - println("\n==== $taskName -- doLast\n") - } - } - return explodeTask + BufferedWriter(OutputStreamWriter(FileOutputStream(outputFile), "UTF-8")).use { writer -> + writer.append(mergingReport.getMergedDocument(MergingReport.MergedManifestKind.MERGED)) + writer.flush() } - - return null } - private fun initializers(project: Project) { - this.extension = project.extensions.create(Extension.NAME, Extension::class.java) - RClassTransformer.project = project - projectConfigurations = ProjectConfigurations(project) - VariantPackagesProperty.setVariantPackagesProperty(project) - } + private fun initializers(project: Project) { + this.extension = project.extensions.create(Extension.NAME, Extension::class.java) + RClassTransformer.project = project + projectConfigurations = ProjectConfigurations(project) + VariantPackagesProperty.setVariantPackagesProperty(project) + } - /** - * Verifies and throws error if `com.android.library` plugin is not applied - */ - private fun verifyAndroidPluginApplied(project: Project) { - if (!project.plugins.hasPlugin("com.android.library")) { - throw ProjectConfigurationException( - "$PROJECT_ID must be applied to an android library project", - Throwable("Apply $PROJECT_ID"), - ) - } + /** + * Verifies and throws error if `com.android.library` plugin is not applied + */ + private fun verifyAndroidPluginApplied(project: Project) { + if (!project.plugins.hasPlugin("com.android.library")) { + throw ProjectConfigurationException( + "$PROJECT_ID must be applied to an android library project", + Throwable("Apply $PROJECT_ID"), + ) } } +} diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ExplodeAarTask.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ExplodeAarTask.kt index 5c655f19..74f201d6 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ExplodeAarTask.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ExplodeAarTask.kt @@ -1,11 +1,68 @@ package com.callstack.react.brownfield.shared +import com.android.build.gradle.LibraryExtension +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.file.RegularFileProperty import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.TaskAction +import java.io.File abstract class ExplodeAarTask: DefaultTask() { @get:InputFile abstract val inputArtifactListFile: RegularFileProperty + + @TaskAction + fun run() { + val file = inputArtifactListFile.get().asFile + val artifacts = readArtifacts(file) + + project.extensions.getByType(LibraryExtension::class.java).libraryVariants.all { variant -> + val variantHelper = VariantHelper(variant) + variantHelper.project = project + + // classes-merge + variantHelper.classesMergeTaskDoFirst( + DirectoryManager.getMergeClassDirectory( + variant + ) + ) + + val aarLibraries = mutableListOf() + artifacts.forEach { art -> + val archiveLibrary = + AndroidArchiveLibrary( + this.project, + art, + variant.name, + ) + + aarLibraries.add(archiveLibrary) + + // explode-aar + val zipFolder = archiveLibrary.getExplodedAarRootDir() + zipFolder.mkdirs() + + project.copy { + zipFolder.deleteRecursively() + it.from(project.zipTree(art.file)) + it.into(zipFolder) + } + } + + // classes-merge + variantHelper.classesMergeTaskDoLast(DirectoryManager.getMergeClassDirectory(variant), aarLibraries, mutableListOf()) + } + } + + private fun readArtifacts(file: File): List { + if (!file.exists()) return emptyList() + + return file.readLines() + .filter { it.isNotBlank() } + .map { JsonInstance.json.decodeFromString(it) } + } } \ No newline at end of file diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/MergeClassesAndJarsTask.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/GeneralTask.kt similarity index 61% rename from gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/MergeClassesAndJarsTask.kt rename to gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/GeneralTask.kt index cd8f36e0..20621ad8 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/MergeClassesAndJarsTask.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/GeneralTask.kt @@ -4,8 +4,8 @@ import org.gradle.api.DefaultTask import org.gradle.api.file.RegularFileProperty import org.gradle.api.tasks.InputFile -abstract class MergeClassesAndJarsTask: DefaultTask() { +abstract class GeneralTask: DefaultTask() { @get:InputFile - abstract val inputArtifactListFile: RegularFileProperty + abstract val inputTaskList: RegularFileProperty } \ No newline at end of file From 3fd052621d98df6cc592ff08c14f9e51c066ee2f Mon Sep 17 00:00:00 2001 From: Hur Ali Date: Tue, 27 Jan 2026 23:12:38 +0500 Subject: [PATCH 04/12] feat: migrate processResources and processAssets --- .../brownfield/plugin/RNBrownfieldPlugin.kt | 63 +++++++++++++++---- .../brownfield/processors/VariantProcessor.kt | 4 -- 2 files changed, 50 insertions(+), 17 deletions(-) diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt index df4716ec..9c6b047d 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt @@ -8,6 +8,7 @@ import com.android.manifmerger.ManifestProvider import com.android.manifmerger.MergingReport import com.android.utils.ILogger import com.callstack.react.brownfield.artifacts.ArtifactsResolver +import com.callstack.react.brownfield.exceptions.TaskNotFound import com.callstack.react.brownfield.processors.VariantPackagesProperty import com.callstack.react.brownfield.shared.BaseProject import com.callstack.react.brownfield.shared.Constants.PROJECT_ID @@ -118,20 +119,20 @@ constructor( val capitalizedVariantName = variant.name.replaceFirstChar(Char::titlecase) val processManifestTask = variant.outputs.first().processManifestProvider.get() - processManifestTask.doLast { - val artifacts = readArtifacts(processArtifactsTask.get().artifactOutput.get().asFile) - val aarLibraries = mutableListOf() - artifacts.forEach { art -> - val archiveLibrary = - AndroidArchiveLibrary( - this.project, - art, - variant.name, - ) - - aarLibraries.add(archiveLibrary) - } + val artifacts = readArtifacts(processArtifactsTask.get().artifactOutput.get().asFile) + val filteredArtifacts = artifacts.filter { it.bundleTaskName?.contains(capitalizedVariantName) == true } + val aarLibraries = mutableListOf() + filteredArtifacts.forEach { art -> + val archiveLibrary = + AndroidArchiveLibrary( + this.project, + art, + variant.name, + ) + aarLibraries.add(archiveLibrary) + } + processManifestTask.doLast { // manifest-merger val buildDir = project.layout.buildDirectory.get() val manifestOutput = @@ -142,6 +143,42 @@ constructor( val inputManifests = aarLibraries.map { it.getManifestFile() } manifestMerger(manifestOutput, inputManifests, manifestOutput) } + + /** ======= GENERATE RESOURCES =========*/ + + /** + * See if we can move this block to configure phase of prebuild or resourceGenTask + * + * Tried adding to resourceGenTask configure, doFirst and doLast. PreBuild doFirst and doLast + * but it does not take effect. Adding to preBuild.configure, works. + */ + val taskPath = "generate${capitalizedVariantName}Resources" + val resourceGenTask = project.tasks.named(taskPath) + + if (!resourceGenTask.isPresent) { + throw TaskNotFound("Task $taskPath not found") + } + + aarLibraries.forEach { + variant.registerGeneratedResFolders( + project.files(it.getResDir()), + ) + } + + /** ======= GENERATE ASSETS ========= */ + val assetsTask = variant.mergeAssetsProvider.get() + + val androidExtension = project.extensions.getByName("android") as LibraryExtension + assetsTask.doFirst { + val filteredSourceSets = androidExtension.sourceSets.filter { it.name == variant.name } + + filteredSourceSets.forEach { sourceSet -> + val filteredAarLibs = aarLibraries.filter { it.getAssetsDir().exists() } + filteredAarLibs.forEach { + sourceSet.assets.srcDir(it.getAssetsDir()) + } + } + } } project.tasks.register("general", ExplodeAarTask::class.java) { task -> diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt index 9853a538..65f6bbb3 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt @@ -59,12 +59,8 @@ class VariantProcessor(private val variant: LibraryVariant) : BaseProject() { prepareTask.dependsOn(":app:createBundle${capitalizedVariantName}JsAndAssets") } -// val bundleTask = variantTaskProvider.bundleTaskProvider(project, variant.name) - if (aarLibraries.isEmpty()) return -// variantTaskProvider.processManifestTask(aarLibraries) -// variantHelper.processResources(aarLibraries) // variantHelper.processAssets(aarLibraries) // jniLibsProcessor.processJniLibs(aarLibraries, variant) // proguardProcessor.processConsumerFiles(aarLibraries) From fe2bbc1d696e5f08b19f0f1648ae4d81f6a1488b Mon Sep 17 00:00:00 2001 From: Hur Ali Date: Wed, 28 Jan 2026 10:36:42 +0500 Subject: [PATCH 05/12] feat: migrate jni libs processor --- .../react/brownfield/plugin/RNBrownfieldPlugin.kt | 6 ++++++ .../brownfield/processors/JNILibsProcessor.kt | 14 -------------- .../brownfield/processors/VariantProcessor.kt | 12 ------------ 3 files changed, 6 insertions(+), 26 deletions(-) diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt index 9c6b047d..42e78a85 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt @@ -9,6 +9,7 @@ import com.android.manifmerger.MergingReport import com.android.utils.ILogger import com.callstack.react.brownfield.artifacts.ArtifactsResolver import com.callstack.react.brownfield.exceptions.TaskNotFound +import com.callstack.react.brownfield.processors.JNILibsProcessor import com.callstack.react.brownfield.processors.VariantPackagesProperty import com.callstack.react.brownfield.shared.BaseProject import com.callstack.react.brownfield.shared.Constants.PROJECT_ID @@ -114,6 +115,9 @@ constructor( task.inputArtifactListFile.set(processArtifactsTask.get().artifactOutput) } + val jniLibsProcessor = JNILibsProcessor() + jniLibsProcessor.project = project + // process manifest & merger task project.extensions.getByType(LibraryExtension::class.java).libraryVariants.all { variant -> val capitalizedVariantName = variant.name.replaceFirstChar(Char::titlecase) @@ -179,6 +183,8 @@ constructor( } } } + + jniLibsProcessor.processJniLibs(aarLibraries, variant) } project.tasks.register("general", ExplodeAarTask::class.java) { task -> diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/JNILibsProcessor.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/JNILibsProcessor.kt index 8522f70b..5ea6e4d3 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/JNILibsProcessor.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/JNILibsProcessor.kt @@ -17,7 +17,6 @@ import com.callstack.react.brownfield.shared.BaseProject import com.callstack.react.brownfield.shared.Logging import com.callstack.react.brownfield.utils.AndroidArchiveLibrary import com.callstack.react.brownfield.utils.Extension -import org.gradle.api.Task import org.gradle.api.tasks.Copy import org.gradle.api.tasks.TaskProvider import java.io.File @@ -39,8 +38,6 @@ class JNILibsProcessor : BaseProject() { val copyTask = copySoLibsTask(variant) mergeJniLibsTask.configure { - println("\n=== $taskName configured\n") - it.dependsOn(copyTask) it.doFirst { @@ -58,10 +55,6 @@ class JNILibsProcessor : BaseProject() { } } } - - it.doLast { - println("\n==== mergeJniLibsTask doLast ====\n") - } } } @@ -85,21 +78,14 @@ class JNILibsProcessor : BaseProject() { project.rootProject .file("${project.name}/libs$capitalizedVariant") - println("==== IN copy so lib task") return project.tasks.register("copy${capitalizedVariant}LibSources", Copy::class.java) { - println("\n=== copy${capitalizedVariant}LibSource configured\n") - it.dependsOn(stripTask, codegenTask) it.from(fromDir) it.into(intoDir) it.include("**/libappmodules.so", "**/libreact_codegen_*.so") projectExt.dynamicLibs.forEach { lib -> it.include("**/$lib") } - - it.doLast { - println("\n==== copy${capitalizedVariant}LibSource doLast ====\n") - } } } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt index 65f6bbb3..fd416a2e 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt @@ -12,27 +12,18 @@ package com.callstack.react.brownfield.processors import com.android.build.gradle.api.LibraryVariant import com.android.build.gradle.internal.tasks.factory.dependsOn -import com.callstack.react.brownfield.artifacts.ArtifactsResolver.Companion.ARTIFACT_TYPE_AAR -import com.callstack.react.brownfield.artifacts.ArtifactsResolver.Companion.ARTIFACT_TYPE_JAR import com.callstack.react.brownfield.exceptions.TaskNotFound import com.callstack.react.brownfield.shared.BaseProject import com.callstack.react.brownfield.shared.UnresolvedArtifactInfo import com.callstack.react.brownfield.utils.AndroidArchiveLibrary -import org.gradle.api.Task -import org.gradle.api.artifacts.ResolvedArtifact import org.gradle.api.provider.ListProperty -import org.gradle.api.tasks.Copy -import org.gradle.api.tasks.PathSensitivity -import org.gradle.api.tasks.TaskProvider import java.io.File class VariantProcessor(private val variant: LibraryVariant) : BaseProject() { private val capitalizedVariantName = variant.name.replaceFirstChar(Char::titlecase) private val variantHelper = VariantHelper(variant) private val variantTaskProvider = VariantTaskProvider(variantHelper) - private val jniLibsProcessor = JNILibsProcessor() private val proguardProcessor = ProguardProcessor(variant) - private val explodeTasks = mutableListOf() private val aarLibraries = mutableListOf() private lateinit var aarLibrariesProperty: ListProperty private val jarFiles = mutableListOf() @@ -40,7 +31,6 @@ class VariantProcessor(private val variant: LibraryVariant) : BaseProject() { private fun setup() { variantHelper.project = project variantTaskProvider.project = project - jniLibsProcessor.project = project proguardProcessor.project = project aarLibrariesProperty = project.objects.listProperty(AndroidArchiveLibrary::class.java) VariantPackagesProperty.getVariantPackagesProperty().put(variant.name, aarLibrariesProperty) @@ -61,8 +51,6 @@ class VariantProcessor(private val variant: LibraryVariant) : BaseProject() { if (aarLibraries.isEmpty()) return -// variantHelper.processAssets(aarLibraries) -// jniLibsProcessor.processJniLibs(aarLibraries, variant) // proguardProcessor.processConsumerFiles(aarLibraries) // proguardProcessor.processGeneratedFiles(aarLibraries) // variantTaskProvider.processDataBinding(bundleTask, aarLibraries) From 25fb9819e70a140ded0425c0ca34d9265ea412ab Mon Sep 17 00:00:00 2001 From: Hur Ali Date: Wed, 28 Jan 2026 11:52:32 +0500 Subject: [PATCH 06/12] feat: migrate proguard processor --- .../brownfield/plugin/RNBrownfieldPlugin.kt | 8 ++++++++ .../brownfield/processors/ProguardProcessor.kt | 18 ++++++++---------- .../brownfield/processors/VariantProcessor.kt | 4 ---- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt index 42e78a85..80362f39 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt @@ -10,6 +10,7 @@ import com.android.utils.ILogger import com.callstack.react.brownfield.artifacts.ArtifactsResolver import com.callstack.react.brownfield.exceptions.TaskNotFound import com.callstack.react.brownfield.processors.JNILibsProcessor +import com.callstack.react.brownfield.processors.ProguardProcessor import com.callstack.react.brownfield.processors.VariantPackagesProperty import com.callstack.react.brownfield.shared.BaseProject import com.callstack.react.brownfield.shared.Constants.PROJECT_ID @@ -118,6 +119,9 @@ constructor( val jniLibsProcessor = JNILibsProcessor() jniLibsProcessor.project = project + val proguardProcessor = ProguardProcessor() + proguardProcessor.project = project + // process manifest & merger task project.extensions.getByType(LibraryExtension::class.java).libraryVariants.all { variant -> val capitalizedVariantName = variant.name.replaceFirstChar(Char::titlecase) @@ -185,6 +189,10 @@ constructor( } jniLibsProcessor.processJniLibs(aarLibraries, variant) + val proguardRules = aarLibraries.map { it.getProguardRules() } + + proguardProcessor.processConsumerFiles(proguardRules, capitalizedVariantName) + proguardProcessor.processGeneratedFiles(proguardRules, capitalizedVariantName) } project.tasks.register("general", ExplodeAarTask::class.java) { task -> diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ProguardProcessor.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ProguardProcessor.kt index d29e4de4..b7f4cc53 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ProguardProcessor.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ProguardProcessor.kt @@ -21,11 +21,10 @@ import org.gradle.api.file.RegularFileProperty import org.gradle.api.tasks.TaskProvider import java.io.File -class ProguardProcessor(variant: LibraryVariant) : BaseProject() { - private val capitalizedVariantName = variant.name.replaceFirstChar(Char::titlecase) - +class ProguardProcessor : BaseProject() { fun processConsumerFiles( - aarLibs: Collection, + proguardRules: List, + capitalizedVariantName: String ) { val mergeTaskName = "merge${capitalizedVariantName}ConsumerProguardFiles" val mergeFileTask = project.tasks.named(mergeTaskName) @@ -36,25 +35,24 @@ class ProguardProcessor(variant: LibraryVariant) : BaseProject() { mergeFileTask.configure { task -> task.doLast { - val files = aarLibs.map { aarLib -> aarLib.getProguardRules() } val outputFile = it.outputs.files.singleFile - doLast(files, outputFile) + doLast(proguardRules, outputFile) } } } fun processGeneratedFiles( - aarLibs: Collection, + proguardRules: List, + capitalizedVariantName: String ) { val mergeGenerateProguardTask: TaskProvider<*>? val mergeName = "merge${capitalizedVariantName}GeneratedProguardFiles" mergeGenerateProguardTask = project.tasks.named(mergeName) - mergeGenerateProguardTask?.configure { task -> + mergeGenerateProguardTask.configure { task -> task.doLast { - val files = aarLibs.map { it.getProguardRules() } val outputFile = it.outputs.files.singleFile - doLast(files, outputFile) + doLast(proguardRules, outputFile) } } } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt index fd416a2e..f9b0076c 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt @@ -23,7 +23,6 @@ class VariantProcessor(private val variant: LibraryVariant) : BaseProject() { private val capitalizedVariantName = variant.name.replaceFirstChar(Char::titlecase) private val variantHelper = VariantHelper(variant) private val variantTaskProvider = VariantTaskProvider(variantHelper) - private val proguardProcessor = ProguardProcessor(variant) private val aarLibraries = mutableListOf() private lateinit var aarLibrariesProperty: ListProperty private val jarFiles = mutableListOf() @@ -31,7 +30,6 @@ class VariantProcessor(private val variant: LibraryVariant) : BaseProject() { private fun setup() { variantHelper.project = project variantTaskProvider.project = project - proguardProcessor.project = project aarLibrariesProperty = project.objects.listProperty(AndroidArchiveLibrary::class.java) VariantPackagesProperty.getVariantPackagesProperty().put(variant.name, aarLibrariesProperty) } @@ -51,8 +49,6 @@ class VariantProcessor(private val variant: LibraryVariant) : BaseProject() { if (aarLibraries.isEmpty()) return -// proguardProcessor.processConsumerFiles(aarLibraries) -// proguardProcessor.processGeneratedFiles(aarLibraries) // variantTaskProvider.processDataBinding(bundleTask, aarLibraries) // variantTaskProvider.processDeepLinkTasks() } From 22f7e93a9fb0bc3c0df031463e5b604765f03c9e Mon Sep 17 00:00:00 2001 From: Hur Ali Date: Wed, 28 Jan 2026 20:50:46 +0500 Subject: [PATCH 07/12] feat: migrate data binding and cleanup --- .../brownfield/artifacts/ArtifactsResolver.kt | 9 +- .../brownfield/plugin/RClassTransformer.kt | 1 - .../brownfield/plugin/RNBrownfieldPlugin.kt | 9 ++ .../brownfield/processors/VariantProcessor.kt | 29 +--- .../processors/VariantTaskProvider.kt | 129 +----------------- .../brownfield/utils/AndroidArchiveLibrary.kt | 7 - 6 files changed, 22 insertions(+), 162 deletions(-) diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/ArtifactsResolver.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/ArtifactsResolver.kt index e6ac2e57..65de67eb 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/ArtifactsResolver.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/ArtifactsResolver.kt @@ -113,21 +113,18 @@ class ArtifactsResolver( // store the artifacts which can be variant aware including flavors val artifacts = mutableSetOf() baseProject.project.extensions.getByType(LibraryExtension::class.java).libraryVariants.all { variant -> - val artifacts1 = mutableListOf() configurations.forEach { configuration -> if (isEmbedConfig(configuration, variant)) { -// val resolvedArtifacts = resolveArtifacts(configuration) val res = handleUnResolvedArtifacts(configuration, variant) artifacts.addAll(res) - artifacts1.addAll(res) } } if (artifacts.isNotEmpty()) { - val processor = VariantProcessor(variant) + val processor = VariantProcessor() processor.project = baseProject.project - processor.processVariant(artifacts1) + processor.processVariant(variant) } } @@ -205,7 +202,7 @@ class ArtifactsResolver( val variantHelper = VariantHelper(variant) variantHelper.project = baseProject.project - val variantTaskProvider = VariantTaskProvider(variantHelper) + val variantTaskProvider = VariantTaskProvider() variantTaskProvider.project = baseProject.project val flavorArtifact = FlavorArtifact(variant, configuration) flavorArtifact.project = baseProject.project diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RClassTransformer.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RClassTransformer.kt index e2cd0e13..e89647c3 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RClassTransformer.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RClassTransformer.kt @@ -9,7 +9,6 @@ import com.android.build.api.instrumentation.InstrumentationScope import com.android.build.api.variant.AndroidComponentsExtension import com.callstack.react.brownfield.processors.VariantPackagesProperty import com.callstack.react.brownfield.shared.BaseProject -import com.callstack.react.brownfield.utils.Utils import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Property import org.gradle.api.tasks.Input diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt index 80362f39..b8b7cbbf 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt @@ -11,7 +11,9 @@ import com.callstack.react.brownfield.artifacts.ArtifactsResolver import com.callstack.react.brownfield.exceptions.TaskNotFound import com.callstack.react.brownfield.processors.JNILibsProcessor import com.callstack.react.brownfield.processors.ProguardProcessor +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 import com.callstack.react.brownfield.shared.Constants.PROJECT_ID import com.callstack.react.brownfield.shared.ExplodeAarTask @@ -122,6 +124,9 @@ constructor( val proguardProcessor = ProguardProcessor() proguardProcessor.project = project + val variantTaskProvider = VariantTaskProvider() + variantTaskProvider.project = project + // process manifest & merger task project.extensions.getByType(LibraryExtension::class.java).libraryVariants.all { variant -> val capitalizedVariantName = variant.name.replaceFirstChar(Char::titlecase) @@ -193,6 +198,10 @@ constructor( proguardProcessor.processConsumerFiles(proguardRules, capitalizedVariantName) proguardProcessor.processGeneratedFiles(proguardRules, capitalizedVariantName) + + /** ===== processDataBinding ===== */ + val bundleTask = variantTaskProvider.bundleTaskProvider(project, variant.name) + variantTaskProvider.processDataBinding(bundleTask, aarLibraries, variant) } project.tasks.register("general", ExplodeAarTask::class.java) { task -> diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt index f9b0076c..8b380d01 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt @@ -14,28 +14,10 @@ import com.android.build.gradle.api.LibraryVariant import com.android.build.gradle.internal.tasks.factory.dependsOn import com.callstack.react.brownfield.exceptions.TaskNotFound import com.callstack.react.brownfield.shared.BaseProject -import com.callstack.react.brownfield.shared.UnresolvedArtifactInfo -import com.callstack.react.brownfield.utils.AndroidArchiveLibrary -import org.gradle.api.provider.ListProperty -import java.io.File -class VariantProcessor(private val variant: LibraryVariant) : BaseProject() { - private val capitalizedVariantName = variant.name.replaceFirstChar(Char::titlecase) - private val variantHelper = VariantHelper(variant) - private val variantTaskProvider = VariantTaskProvider(variantHelper) - private val aarLibraries = mutableListOf() - private lateinit var aarLibrariesProperty: ListProperty - private val jarFiles = mutableListOf() - - private fun setup() { - variantHelper.project = project - variantTaskProvider.project = project - aarLibrariesProperty = project.objects.listProperty(AndroidArchiveLibrary::class.java) - VariantPackagesProperty.getVariantPackagesProperty().put(variant.name, aarLibrariesProperty) - } - - fun processVariant(artifacts: List) { - setup() +class VariantProcessor : BaseProject() { + fun processVariant(variant: LibraryVariant) { + val capitalizedVariantName = variant.name.replaceFirstChar(Char::titlecase) val preBuildTaskPath = "pre${capitalizedVariantName}Build" val prepareTask = project.tasks.named(preBuildTaskPath) @@ -46,10 +28,5 @@ class VariantProcessor(private val variant: LibraryVariant) : BaseProject() { if (capitalizedVariantName.contains("Release")) { prepareTask.dependsOn(":app:createBundle${capitalizedVariantName}JsAndAssets") } - - if (aarLibraries.isEmpty()) return - -// variantTaskProvider.processDataBinding(bundleTask, aarLibraries) -// variantTaskProvider.processDeepLinkTasks() } } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt index cdbe6688..fa634b34 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt @@ -1,81 +1,16 @@ package com.callstack.react.brownfield.processors -import com.android.build.gradle.internal.tasks.factory.registerTask -import com.callstack.react.brownfield.exceptions.TaskNotFound -import com.callstack.react.brownfield.plugin.ManifestMerger +import com.android.build.gradle.api.LibraryVariant 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.Utils import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.UnknownTaskException -import org.gradle.api.tasks.PathSensitivity import org.gradle.api.tasks.TaskProvider import java.io.File -class VariantTaskProvider(private val variantHelper: VariantHelper) : BaseProject() { - private val variant = variantHelper.getVariant() - private val capitalizedVariantName = variant.name.replaceFirstChar(Char::titlecase) - - fun classesMergeTask( - aarLibraries: Collection, - jarFiles: MutableList, - ): Task { - val mergeClassesTaskName = "mergeClasses$capitalizedVariantName" - val kotlinCompileTaskName = "compile${capitalizedVariantName}Kotlin" - - return project.tasks.create(mergeClassesTaskName, Task::class.java) { - it.outputs.upToDateWhen { false } - - it.dependsOn(variantHelper.getJavaCompileTask()) - - it.dependsOn(project.tasks.named(kotlinCompileTaskName)) - - it.inputs.files(variantHelper.getClassesJarFiles(aarLibraries)).withPathSensitivity(PathSensitivity.RELATIVE) - - if (variant.buildType.isMinifyEnabled) { - it.inputs.files(variantHelper.getLocalJarFiles(aarLibraries)).withPathSensitivity(PathSensitivity.RELATIVE) -// it.inputs.files(jarFiles).withPathSensitivity(PathSensitivity.RELATIVE) - } - -// val outputDir = DirectoryManager.getMergeClassDirectory(variant) -// it.outputs.dir(outputDir) -// -// it.doFirst { -// println("===== DO FIRST CLASSES MERGE") -// -// variantHelper.classesMergeTaskDoFirst( DirectoryManager.getMergeClassDirectory(variant)) -// } -// it.doLast { -// println("===== DO LAST CLASSES MERGE") -// variantHelper.classesMergeTaskDoLast( DirectoryManager.getMergeClassDirectory(variant), aarLibraries, jarFiles) -// } - } - } - - fun jarMergeTask( - syncLibTask: TaskProvider, - aarLibraries: Collection, - jarFiles: MutableList, - ): TaskProvider { - return project.tasks.register("mergeJars$capitalizedVariantName") { - it.dependsOn(variantHelper.getJavaCompileTask()) - it.mustRunAfter(syncLibTask) - - it.inputs.files(aarLibraries.map { aarLib -> aarLib.getLibsDir() }).withPathSensitivity( - PathSensitivity.RELATIVE, - ) - it.inputs.files(jarFiles).withPathSensitivity(PathSensitivity.RELATIVE) - val outputDir = variantHelper.getLibsDirFile() - it.outputs.dir(outputDir) - - it.doFirst { - MergeProcessor.mergeLibsIntoLibs(project, aarLibraries, jarFiles, outputDir) - } - } - } - +class VariantTaskProvider: BaseProject() { fun bundleTaskProvider( project: Project, variantName: String, @@ -83,56 +18,23 @@ class VariantTaskProvider(private val variantHelper: VariantHelper) : BaseProjec var bundleTaskPath = "bundle${variantName.replaceFirstChar(Char::titlecase)}" return try { project.tasks.named(bundleTaskPath) - } catch (ignored: UnknownTaskException) { + } catch (_: UnknownTaskException) { bundleTaskPath += "Aar" project.tasks.named(bundleTaskPath) } } - fun processManifestTask( - aarLibraries: Collection, - ) { - val processManifestTask = variantHelper.getProcessManifest() - val manifestOutput = - project.file( - "$buildDir/intermediates/merged_manifest/${variant.name}/process${capitalizedVariantName}Manifest/AndroidManifest.xml", - ) - - val inputManifests = aarLibraries.map { it.getManifestFile() } - - val manifestsMergeTask = - project.tasks.register( - "merge${capitalizedVariantName}Manifest", - ManifestMerger::class.java, - ) { - println("\n==== merge${capitalizedVariantName}Manifest Configured\n") - it.setGradleVersion(project.gradle.gradleVersion) - it.setGradlePluginVersion(Utils.getAGPVersion()) - it.setMainManifestFile(manifestOutput) - it.setSecondaryManifestFiles(inputManifests) - it.setOutputFile(manifestOutput) - - it.doLast { - println("\n==== merge${capitalizedVariantName}Manifest doLast ====\n") - } - } - - processManifestTask.inputs.files(inputManifests) - processManifestTask.doLast { - manifestsMergeTask.get().doTaskAction() - } - } - fun processDataBinding( bundleTask: TaskProvider, aarLibraries: Collection, + variant: LibraryVariant, ) { bundleTask.configure { task -> task.doLast { aarLibraries.forEach { val dataBindingFolder = it.getDataBindingFolder() if (dataBindingFolder.exists()) { - val filePath = getReBundleFilePath(dataBindingFolder.name) + val filePath = getReBundleFilePath(dataBindingFolder.name, variant) File(filePath).mkdirs() project.copy { copyTask -> copyTask.from(dataBindingFolder) @@ -142,7 +44,7 @@ class VariantTaskProvider(private val variantHelper: VariantHelper) : BaseProjec val dataBindingLogFolder = it.getDataBindingLogFolder() if (dataBindingLogFolder.exists()) { - val filePath = getReBundleFilePath(dataBindingLogFolder.name) + val filePath = getReBundleFilePath(dataBindingLogFolder.name, variant) File(filePath).mkdirs() project.copy { copyTask -> copyTask.from(dataBindingLogFolder) @@ -154,22 +56,5 @@ class VariantTaskProvider(private val variantHelper: VariantHelper) : BaseProjec } } - fun processDeepLinkTasks() { - val taskName = "extractDeepLinksForAar$capitalizedVariantName" - val extractDeepLinks = project.tasks.named(taskName) - - if (!extractDeepLinks.isPresent) { - throw TaskNotFound("Task $taskName not found") - } - - extractDeepLinks.configure { - println("\n==== extractDeepLinks Configured\n") - - it.doLast { - println("\n==== extractDeepLinks doLast ====\n") - } - } - } - - private fun getReBundleFilePath(folderName: String) = "${DirectoryManager.getReBundleDirectory(variant).path}/$folderName" + private fun getReBundleFilePath(folderName: String, variant: LibraryVariant) = "${DirectoryManager.getReBundleDirectory(variant).path}/$folderName" } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/AndroidArchiveLibrary.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/AndroidArchiveLibrary.kt index 3bac5d1a..7925781a 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/AndroidArchiveLibrary.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/AndroidArchiveLibrary.kt @@ -1,27 +1,20 @@ package com.callstack.react.brownfield.utils import com.android.build.gradle.LibraryExtension -import com.callstack.react.brownfield.shared.Logging import com.callstack.react.brownfield.shared.UnresolvedArtifactInfo import org.gradle.api.Project -import org.gradle.api.artifacts.ResolvedArtifact import java.io.File -import java.io.FileNotFoundException -import javax.xml.parsers.DocumentBuilderFactory class AndroidArchiveLibrary( private val project: Project, artifact: UnresolvedArtifactInfo, private val variantName: String, ) { - private var packageName: String? = null private val artifact: UnresolvedArtifactInfo = requireNotNull(artifact.takeIf { it.type == "aar" }) { "Only Aar is accepted as an artifact" } - private fun getArtifactName() = artifact.moduleName - fun getExplodedAarRootDir(): File { val explodedRootDir = File("${project.layout.buildDirectory.get()}/intermediates/exploded-aar") return File(explodedRootDir, "${artifact.moduleGroup}/${artifact.moduleName}/${artifact.moduleVersion}/$variantName") From f1b549748a6f7708726146f9a18ce0bc4e6e3a8f Mon Sep 17 00:00:00 2001 From: Hur Ali Date: Wed, 28 Jan 2026 21:02:25 +0500 Subject: [PATCH 08/12] refactor: cleanup --- .../react/brownfield/plugin/ManifestMerger.kt | 85 ------------------- .../plugin/ProjectConfigurations.kt | 6 -- .../brownfield/plugin/RNBrownfieldPlugin.kt | 1 - .../react/brownfield/plugin/RNSourceSets.kt | 1 - .../brownfield/processors/MergeProcessor.kt | 25 ------ .../processors/ProguardProcessor.kt | 3 - .../brownfield/processors/VariantHelper.kt | 76 ----------------- .../shared/ArtifactRegistrationTask.kt | 67 --------------- .../react/brownfield/shared/GeneralTask.kt | 11 --- .../brownfield/shared/ProcessArtifactTask.kt | 11 --- .../callstack/react/brownfield/utils/Utils.kt | 15 ---- 11 files changed, 301 deletions(-) delete mode 100644 gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/ManifestMerger.kt delete mode 100644 gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ArtifactRegistrationTask.kt delete mode 100644 gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/GeneralTask.kt diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/ManifestMerger.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/ManifestMerger.kt deleted file mode 100644 index 2ce64127..00000000 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/ManifestMerger.kt +++ /dev/null @@ -1,85 +0,0 @@ -package com.callstack.react.brownfield.plugin - -import com.android.build.gradle.internal.LoggerWrapper -import com.android.manifmerger.ManifestMerger2 -import com.android.manifmerger.ManifestProvider -import com.android.manifmerger.MergingReport -import com.android.utils.ILogger -import com.callstack.react.brownfield.shared.Logging -import org.apache.tools.ant.BuildException -import org.gradle.api.DefaultTask -import java.io.BufferedWriter -import java.io.File -import java.io.FileOutputStream -import java.io.OutputStreamWriter - -open class ManifestMerger : DefaultTask() { - private var mGradlePluginVersion: String? = null - private var mGradleVersion: String? = null - private var mMainManifestFile: File? = null - private var mSecondaryManifestFiles: List? = null - private var mOutputFile: File? = null - - fun setGradlePluginVersion(gradlePluginVersion: String) { - mGradlePluginVersion = gradlePluginVersion - } - - fun setGradleVersion(gradleVersion: String) { - mGradleVersion = gradleVersion - } - - fun setMainManifestFile(mainManifestFile: File) { - mMainManifestFile = mainManifestFile - } - - fun setSecondaryManifestFiles(sm: List) { - mSecondaryManifestFiles = sm - } - - fun setOutputFile(outputFile: File) { - mOutputFile = outputFile - } - - open fun doTaskAction() { - try { - doFullTaskAction() - } catch (e: IllegalStateException) { - Logging.info("Gradle Plugin Version: $mGradlePluginVersion") - Logging.info("Gradle Version: $mGradleVersion") - Logging.log(e.stackTraceToString()) - } - } - - private fun doFullTaskAction() { - val iLogger: ILogger = LoggerWrapper(logger) - val mergerInvoker = ManifestMerger2.newMerger(mMainManifestFile, iLogger, ManifestMerger2.MergeType.LIBRARY) - - val secondaryManifestFiles = mSecondaryManifestFiles - val manifestProviders = mutableListOf() - - val filteredSecondaryManifests = secondaryManifestFiles?.filter { it.exists() } - filteredSecondaryManifests?.forEach { file -> - manifestProviders.add( - object : ManifestProvider { - override fun getManifest(): File = file.absoluteFile - - override fun getName(): String = file.name - }, - ) - } - - mergerInvoker.addManifestProviders(manifestProviders) - val mergingReport: MergingReport = mergerInvoker.merge() - - if (mergingReport.result.isError) { - logger.error(mergingReport.reportString) - mergingReport.log(iLogger) - throw BuildException(mergingReport.reportString) - } - - BufferedWriter(OutputStreamWriter(FileOutputStream(mOutputFile!!), "UTF-8")).use { writer -> - writer.append(mergingReport.getMergedDocument(MergingReport.MergedManifestKind.MERGED)) - writer.flush() - } - } -} diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/ProjectConfigurations.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/ProjectConfigurations.kt index 28c869f5..8e59175a 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/ProjectConfigurations.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/ProjectConfigurations.kt @@ -1,18 +1,12 @@ package com.callstack.react.brownfield.plugin -import com.android.build.api.attributes.AgpVersionAttr -import com.android.build.api.attributes.BuildTypeAttr import com.android.build.api.variant.LibraryAndroidComponentsExtension import com.android.build.gradle.LibraryExtension -import com.android.build.gradle.internal.attributes.VariantAttr import com.callstack.react.brownfield.shared.Logging import org.gradle.api.Project import org.gradle.api.artifacts.Configuration import org.gradle.api.attributes.Attribute import org.gradle.api.attributes.AttributeContainer -import org.gradle.api.attributes.Usage -import org.gradle.api.attributes.java.TargetJvmEnvironment -import org.gradle.api.internal.artifacts.ArtifactAttributes class ProjectConfigurations(private val project: Project) { private val configurations: MutableCollection = mutableListOf() diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt index b8b7cbbf..c8179bbc 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt @@ -11,7 +11,6 @@ import com.callstack.react.brownfield.artifacts.ArtifactsResolver import com.callstack.react.brownfield.exceptions.TaskNotFound import com.callstack.react.brownfield.processors.JNILibsProcessor import com.callstack.react.brownfield.processors.ProguardProcessor -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 diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNSourceSets.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNSourceSets.kt index 0d08baf2..25b5b850 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNSourceSets.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNSourceSets.kt @@ -126,7 +126,6 @@ object RNSourceSets { val appProjectName = appProject.name project.tasks.register("copyAutolinkingSources", Copy::class.java) { - println("==== copyAutolink configured") val path = "generated/autolinking/src/main/java" it.dependsOn(":$appProjectName:generateAutolinkingPackageList") it.from("$appBuildDir/$path") diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/MergeProcessor.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/MergeProcessor.kt index 253c8f5a..394b3e8e 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/MergeProcessor.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/MergeProcessor.kt @@ -52,29 +52,4 @@ object MergeProcessor { private fun getFilteredAarLibs(androidLibraries: Collection): Collection { return androidLibraries.filter { it.getExplodedAarRootDir().exists() } } - - fun mergeLibsIntoLibs( - project: Project, - androidLibraries: Collection, - jarFiles: Collection, - folderOut: File, - ) { - val filteredLibs = getFilteredAarLibs(androidLibraries) - filteredLibs.forEach { aarLib -> - if (!aarLib.getLocalJars().isEmpty()) { - project.copy { - it.from(aarLib.getLocalJars()) - it.into(folderOut) - } - } - } - - val filteredJarFiles = jarFiles.filter { it.exists() } - filteredJarFiles.forEach { jarFile -> - project.copy { - it.from(jarFile) - it.into(folderOut) - } - } - } } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ProguardProcessor.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ProguardProcessor.kt index b7f4cc53..217e835f 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ProguardProcessor.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ProguardProcessor.kt @@ -10,13 +10,10 @@ package com.callstack.react.brownfield.processors -import com.android.build.gradle.api.LibraryVariant import com.callstack.react.brownfield.exceptions.TaskNotFound import com.callstack.react.brownfield.shared.BaseProject import com.callstack.react.brownfield.shared.Logging -import com.callstack.react.brownfield.utils.AndroidArchiveLibrary import com.callstack.react.brownfield.utils.Utils -import org.gradle.api.Task import org.gradle.api.file.RegularFileProperty import org.gradle.api.tasks.TaskProvider import java.io.File diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantHelper.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantHelper.kt index d2c0c59b..70168837 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantHelper.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantHelper.kt @@ -10,55 +10,23 @@ package com.callstack.react.brownfield.processors -import com.android.build.gradle.LibraryExtension import com.android.build.gradle.api.LibraryVariant -import com.android.build.gradle.tasks.ManifestProcessorTask -import com.callstack.react.brownfield.exceptions.TaskNotFound import com.callstack.react.brownfield.shared.BaseProject -import com.callstack.react.brownfield.shared.UnresolvedArtifactInfo import com.callstack.react.brownfield.utils.AndroidArchiveLibrary import com.callstack.react.brownfield.utils.DirectoryManager -import groovy.lang.MissingPropertyException -import org.gradle.api.Task -import org.gradle.api.artifacts.ResolvedArtifact import org.gradle.api.file.ConfigurableFileCollection -import org.gradle.api.tasks.compile.JavaCompile import java.io.File import java.nio.file.Files import java.nio.file.Path import java.nio.file.Paths class VariantHelper(private val variant: LibraryVariant) : BaseProject() { - private val capitalizedVariantName = variant.name.replaceFirstChar(Char::titlecase) - - fun getVariant(): LibraryVariant { - return variant - } - - fun getJavaCompileTask(): JavaCompile { - return variant.javaCompileProvider.get() - } - - fun getSyncLibJarsTaskPath(): String { - return "sync${variant.name.replaceFirstChar(Char::titlecase)}LibJars" - } - private fun getClassPathDirFiles(): ConfigurableFileCollection { return project.files( "$buildDir/intermediates/javac/${variant.name}/compile${variant.name.replaceFirstChar(Char::titlecase)}JavaWithJavac/classes", ) } - fun getLocalJarFiles(aarLibraries: Collection): Collection { - return aarLibraries.flatMap { - it.getLocalJars() - } - } - - fun getClassesJarFiles(aarLibraries: Collection): List { - return aarLibraries.map { it.getClassesJarFile() } - } - fun classesMergeTaskDoFirst(outputDir: File) { val pathsToDelete = mutableListOf() val javacDir = getClassPathDirFiles().first() @@ -93,48 +61,4 @@ class VariantHelper(private val variant: LibraryVariant) : BaseProject() { copyTask.include("*.kotlin_module") } } - - fun getLibsDirFile(): File { - return project.file( - "$buildDir/intermediates/aar_libs_directory/${variant.name}/sync${variant.name.replaceFirstChar(Char::titlecase)}LibJars/libs", - ) - } - - fun getProcessManifest(): ManifestProcessorTask { - return variant.outputs.first().processManifestProvider.get() - } - - fun processResources( - aarLibraries: Collection, - ) { - val taskPath = "generate${capitalizedVariantName}Resources" - val resourceGenTask = project.tasks.named(taskPath) - - if (!resourceGenTask.isPresent) { - throw TaskNotFound("Task $taskPath not found") - } - - aarLibraries.forEach { - variant.registerGeneratedResFolders( - project.files(it.getResDir()), - ) - } - } - - fun processAssets( - aarLibraries: Collection, - ) { - val assetsTask = variant.mergeAssetsProvider.get() - - val androidExtension = project.extensions.getByName("android") as LibraryExtension - assetsTask.doFirst { - val filteredSourceSets = androidExtension.sourceSets.filter { it.name == variant.name } - filteredSourceSets.forEach { sourceSet -> - val filteredAarLibs = aarLibraries.filter { it.getAssetsDir().exists() } - filteredAarLibs.forEach { - sourceSet.assets.srcDir(it.getAssetsDir()) - } - } - } - } } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ArtifactRegistrationTask.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ArtifactRegistrationTask.kt deleted file mode 100644 index 03019dc7..00000000 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ArtifactRegistrationTask.kt +++ /dev/null @@ -1,67 +0,0 @@ -package com.callstack.react.brownfield.shared - -import com.callstack.react.brownfield.artifacts.ArtifactsResolver -import org.gradle.api.DefaultTask -import org.gradle.api.artifacts.Configuration -import org.gradle.api.file.RegularFileProperty -import org.gradle.api.provider.ListProperty -import org.gradle.api.provider.Property -import org.gradle.api.tasks.InputFile -import org.gradle.api.tasks.InputFiles -import org.gradle.api.tasks.Internal -import org.gradle.api.tasks.OutputFile -import org.gradle.api.tasks.TaskAction -import java.io.File - -abstract class ArtifactRegistrationTask: DefaultTask() { - - @get:Internal - abstract val inputArtifacts: ListProperty - - @get:InputFile - abstract val inputFile: RegularFileProperty - - @TaskAction - fun run() { - println("=== ArtifactRegistrationTask ===") - val lines = inputFile.get().asFile.readLines() - - lines.forEach { line -> - println("==== Line $line") - val lineSplits = line.split(",") - println("=== splits -- $lineSplits") - val projectPath = lineSplits[0] - val taskName = lineSplits[1] - println("=== proj name $projectPath") - val task = project.rootProject.project(projectPath).tasks.findByName(taskName) - if (task != null) { - println("Executing $line") - task.actions.forEach { action -> - action.execute(task) - } - } else { - println("Task $line not found") - } - } - -// project.gradle.taskGraph.whenReady { graph -> -// lines.forEach { name -> -// val task = project.tasks.findByName(name) -// if (task != null) { -// if (!graph.hasTask(task)) { -// println("Enqueueing task: $name") -// task.actions.forEach { action -> action.execute(task) } -// } else { -// println("Task $name is already in the graph, skipping manual execution") -// } -// } else { -// println("Task $name not found") -// } -// } -// } - -// inputArtifacts.get().forEach { -// println("====== From artifact reg task ${it.moduleName} - ${it.moduleGroup} - ${it.file.absolutePath}") -// } - } -} \ No newline at end of file diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/GeneralTask.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/GeneralTask.kt deleted file mode 100644 index 20621ad8..00000000 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/GeneralTask.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.callstack.react.brownfield.shared - -import org.gradle.api.DefaultTask -import org.gradle.api.file.RegularFileProperty -import org.gradle.api.tasks.InputFile - -abstract class GeneralTask: DefaultTask() { - - @get:InputFile - abstract val inputTaskList: RegularFileProperty -} \ No newline at end of file diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ProcessArtifactTask.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ProcessArtifactTask.kt index 316b3c45..e3cc1f9e 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ProcessArtifactTask.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ProcessArtifactTask.kt @@ -4,9 +4,7 @@ import com.callstack.react.brownfield.artifacts.ArtifactsResolver import kotlinx.serialization.encodeToString import org.gradle.api.DefaultTask import org.gradle.api.file.RegularFileProperty -import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Property -import org.gradle.api.tasks.Input import org.gradle.api.tasks.Internal import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.TaskAction @@ -19,19 +17,12 @@ abstract class ProcessArtifactsTask: DefaultTask() { @get:OutputFile abstract val artifactOutput: RegularFileProperty - @get:Internal - abstract var artifactsList: ListProperty - - @TaskAction fun run() { println("=== ProcessArtifactsTask ===") val artifacts = artifactsResolver.get().processArtifacts() val metaList = mutableListOf() artifacts.forEach { -// if (it.bundleTaskName?.contains("Release") == true) { -// metaList.add("${it.moduleName},${it.bundleTaskName}") -// } metaList.add("${it.moduleName},${it.bundleTaskName}") } outputFile.get().asFile.writeText(metaList.joinToString("\n")) @@ -40,10 +31,8 @@ abstract class ProcessArtifactsTask: DefaultTask() { JsonInstance.json.encodeToString(it) } ) -// artifactOutput.get().asFile.writeText(artifacts.joinToString("\n") { it.toString() }) } @get:Internal abstract val artifactsResolver: Property - } \ No newline at end of file diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/Utils.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/Utils.kt index 26d2598c..7b4c78ea 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/Utils.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/Utils.kt @@ -3,21 +3,6 @@ package com.callstack.react.brownfield.utils import java.io.File object Utils { - fun getAGPVersion(): String { - return try { - extractAGPVersion("com.android.Version") - } catch (ignore: Throwable) { - extractAGPVersion("com.android.builder.model.Version") - } - } - - private fun extractAGPVersion(className: String): String { - val versionField = - Class.forName(className) - .getDeclaredField("ANDROID_GRADLE_PLUGIN_VERSION") - return versionField.get(null) as String - } - fun mergeFiles( inputFiles: Collection?, output: File, From 925e8eead0da9d183db24eb95aa14bb88bef9509 Mon Sep 17 00:00:00 2001 From: Hur Ali Date: Wed, 28 Jan 2026 21:02:36 +0500 Subject: [PATCH 09/12] refactor: cleanup --- .../brownfield/artifacts/ArtifactsResolver.kt | 34 ------------------- .../brownfield/artifacts/FlavorArtifact.kt | 12 ------- .../brownfield/plugin/RNBrownfieldPlugin.kt | 5 --- .../react/brownfield/shared/GradleProps.kt | 1 - .../brownfield/shared/ProcessArtifactTask.kt | 1 - 5 files changed, 53 deletions(-) diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/ArtifactsResolver.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/ArtifactsResolver.kt index 65de67eb..b53f66f2 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/ArtifactsResolver.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/ArtifactsResolver.kt @@ -10,12 +10,10 @@ package com.callstack.react.brownfield.artifacts -import com.android.build.api.variant.AndroidComponentsExtension import com.android.build.gradle.LibraryExtension import com.android.build.gradle.api.LibraryVariant import com.callstack.react.brownfield.plugin.ProjectConfigurations.Companion.CONFIG_NAME import com.callstack.react.brownfield.plugin.ProjectConfigurations.Companion.CONFIG_SUFFIX -import com.callstack.react.brownfield.processors.VariantHelper import com.callstack.react.brownfield.processors.VariantProcessor import com.callstack.react.brownfield.processors.VariantTaskProvider import com.callstack.react.brownfield.shared.BaseProject @@ -25,12 +23,10 @@ import com.callstack.react.brownfield.shared.UnresolvedArtifactInfo import com.callstack.react.brownfield.utils.Extension import com.callstack.react.brownfield.utils.Utils import org.gradle.api.Project -import org.gradle.api.artifacts.ArtifactCollection import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.component.ModuleComponentIdentifier import org.gradle.api.artifacts.component.ProjectComponentIdentifier import org.gradle.api.artifacts.result.ResolvedDependencyResult -import org.gradle.api.attributes.Attribute import org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency import org.gradle.internal.component.local.model.PublishArtifactLocalArtifactMetadata import kotlin.collections.mutableListOf @@ -42,11 +38,6 @@ class ArtifactsResolver( private val extension: Extension, ) : GradleProps() { - companion object { - const val ARTIFACT_TYPE_AAR = "aar" - const val ARTIFACT_TYPE_JAR = "jar" - } - fun processDefaultDependencies() { embedDefaultDependencies("implementation") } @@ -140,30 +131,11 @@ class ArtifactsResolver( configuration.name == variant.name + CONFIG_SUFFIX } - private fun resolveArtifacts(configuration: Configuration): ArtifactCollection { - println("\n==== Resolving Artifacts ${configuration.name} =======\n") - - // Prepare a view of the configuration that can resolve the correct variant - val componentArtifacts = configuration.incoming.artifactView { view -> - view.attributes { - // Do we always have to have AAR? or JAR in some cases? - it.attributes.attribute(Attribute.of("artifactType", String::class.java), "aar") -// it.attributes.attribute(Attribute.of("artifactType", String::class.java), "jar") - } - }.artifacts - - return componentArtifacts - } - private fun handleUnResolvedArtifacts( configuration: Configuration, variant: LibraryVariant, ): List { val unMatchedArtifacts = mutableListOf() -// val firstLevelIds = -// artifacts -// .map { it.id.componentIdentifier.displayName } -// .toSet() val firstLevelIds = setOf() val resolutionResult = configuration.incoming.resolutionResult @@ -184,7 +156,6 @@ class ArtifactsResolver( } is ProjectComponentIdentifier -> { val depProj = baseProject.project.project(id.projectPath) -// println("===----- project ${id.projectName} ${id.displayName} -- path ${baseProject.project.file(id.projectName).absolutePath}") if (id.displayName !in firstLevelIds) { unMatchedArtifacts.add(UnresolvedArtifactInfo( depProj.group.toString(), @@ -200,8 +171,6 @@ class ArtifactsResolver( } } - val variantHelper = VariantHelper(variant) - variantHelper.project = baseProject.project val variantTaskProvider = VariantTaskProvider() variantTaskProvider.project = baseProject.project val flavorArtifact = FlavorArtifact(variant, configuration) @@ -216,7 +185,6 @@ class ArtifactsResolver( val resolvedArtifact = flavorArtifact.createFlavorArtifact( - artifact, fileResolver, taskDependencyFactory, bundleProvider, @@ -233,8 +201,6 @@ class ArtifactsResolver( deps.map { it.path }.toSet(), bundleProvider?.name, )) - -// println("\n=== resolved artttt ${resolvedArtifact.file.absolutePath} -- ${deps.first().name}\n") } } } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/FlavorArtifact.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/FlavorArtifact.kt index c4a3c7e0..30d1ef97 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/FlavorArtifact.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/FlavorArtifact.kt @@ -11,19 +11,11 @@ package com.callstack.react.brownfield.artifacts import org.gradle.api.component.Artifact -import com.android.build.gradle.LibraryExtension import com.android.build.gradle.api.LibraryVariant -import com.android.build.gradle.internal.tasks.factory.dependsOn -import com.callstack.react.brownfield.processors.VariantTaskProvider import com.callstack.react.brownfield.shared.BaseProject -import com.callstack.react.brownfield.shared.UnresolvedArtifactInfo -import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.artifacts.Configuration -import org.gradle.api.artifacts.ResolvedArtifact import org.gradle.api.artifacts.result.ResolvedArtifactResult -import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier -import org.gradle.api.internal.artifacts.DefaultResolvedArtifact import org.gradle.api.internal.artifacts.dsl.LazyPublishArtifact import org.gradle.api.internal.artifacts.result.DefaultResolvedArtifactResult import org.gradle.api.internal.file.FileResolver @@ -34,13 +26,11 @@ import org.gradle.internal.Describables import org.gradle.internal.component.external.model.ImmutableCapabilities import org.gradle.internal.component.local.model.PublishArtifactLocalArtifactMetadata import org.gradle.internal.component.model.DefaultIvyArtifactName -import org.gradle.internal.model.CalculatedValueContainerFactory import java.io.File class FlavorArtifact(private val variant: LibraryVariant, private val configuration: Configuration) : BaseProject() { fun createFlavorArtifact( - unResolvedArtifact: UnresolvedArtifactInfo, fileResolver: FileResolver, taskDependencyFactory: TaskDependencyFactory, bundleTaskProvider: TaskProvider?, @@ -48,8 +38,6 @@ class FlavorArtifact(private val variant: LibraryVariant, val artifactFile = createArtifactFile(bundleTaskProvider?.get() as Task) val artifactName = DefaultIvyArtifactName(artifactFile.name, "aar", "") -// "${artifactProject?.path}:${bundleProvider?.name}" - return DefaultResolvedArtifactResult( PublishArtifactLocalArtifactMetadata( { artifactName.name }, diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt index c8179bbc..0b5e98cb 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt @@ -29,7 +29,6 @@ import org.gradle.api.Project import org.gradle.api.ProjectConfigurationException import org.gradle.api.internal.file.FileResolver import org.gradle.api.internal.tasks.TaskDependencyFactory -import org.gradle.internal.model.CalculatedValueContainerFactory import java.io.BufferedWriter import java.io.File import java.io.FileOutputStream @@ -39,7 +38,6 @@ import javax.inject.Inject class RNBrownfieldPlugin @Inject constructor( - private val calculatedValueContainerFactory: CalculatedValueContainerFactory, private val taskDependencyFactory: TaskDependencyFactory, private val fileResolver: FileResolver, ) : Plugin { @@ -54,8 +52,6 @@ constructor( verifyAndroidPluginApplied(project) initializers(project) - println("=== Applying $PROJECT_ID ===") - this.project = project // Configure projectConfigurations.configure() @@ -71,7 +67,6 @@ constructor( DirectoryManager.project = project artifactsResolver = ArtifactsResolver(projectConfigurations.getConfigurations(), baseProject, extension) - artifactsResolver.calculatedValueContainerFactory = calculatedValueContainerFactory artifactsResolver.taskDependencyFactory = taskDependencyFactory artifactsResolver.fileResolver = fileResolver diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/GradleProps.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/GradleProps.kt index 94f1aeb7..b1243a76 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/GradleProps.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/GradleProps.kt @@ -5,7 +5,6 @@ import org.gradle.api.internal.tasks.TaskDependencyFactory import org.gradle.internal.model.CalculatedValueContainerFactory open class GradleProps { - lateinit var calculatedValueContainerFactory: CalculatedValueContainerFactory lateinit var taskDependencyFactory: TaskDependencyFactory lateinit var fileResolver: FileResolver } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ProcessArtifactTask.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ProcessArtifactTask.kt index e3cc1f9e..56598649 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ProcessArtifactTask.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ProcessArtifactTask.kt @@ -19,7 +19,6 @@ abstract class ProcessArtifactsTask: DefaultTask() { @TaskAction fun run() { - println("=== ProcessArtifactsTask ===") val artifacts = artifactsResolver.get().processArtifacts() val metaList = mutableListOf() artifacts.forEach { From c8fa281e98dc1853fcd8f99457d4a0812b3b8b14 Mon Sep 17 00:00:00 2001 From: Hur Ali Date: Mon, 2 Feb 2026 22:00:02 +0500 Subject: [PATCH 10/12] fix: library namespace resolution --- .../brownfield/plugin/RClassTransformer.kt | 2 +- .../brownfield/plugin/RNBrownfieldPlugin.kt | 14 +++++----- .../processors/VariantPackagesProperty.kt | 10 +++++-- .../brownfield/utils/AndroidArchiveLibrary.kt | 28 +++++++++++++++++-- .../brownfield/utils/DirectoryManager.kt | 2 +- 5 files changed, 41 insertions(+), 15 deletions(-) diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RClassTransformer.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RClassTransformer.kt index e89647c3..2ad9bbd6 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RClassTransformer.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RClassTransformer.kt @@ -38,7 +38,7 @@ object RClassTransformer : BaseProject() { params.namespace.set(variant.namespace) params.libraryNamespaces.set( variantPackagesProperty.getting(variant.name) - .map { list -> list.map { it.getPackageName() }.toList() }, + .map { list -> list.toList()}, ) } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt index 0b5e98cb..d9161a20 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt @@ -50,9 +50,10 @@ constructor( override fun apply(project: Project) { verifyAndroidPluginApplied(project) - initializers(project) this.project = project + initializers() + // Configure projectConfigurations.configure() RNSourceSets.configure(project, extension) @@ -139,6 +140,9 @@ constructor( aarLibraries.add(archiveLibrary) } + val packageIDs = aarLibraries.map { it.getPackageName() } + VariantPackagesProperty.getVariantPackagesProperty().put(variant.name, packageIDs) + processManifestTask.doLast { // manifest-merger val buildDir = project.layout.buildDirectory.get() @@ -197,10 +201,6 @@ constructor( val bundleTask = variantTaskProvider.bundleTaskProvider(project, variant.name) variantTaskProvider.processDataBinding(bundleTask, aarLibraries, variant) } - - project.tasks.register("general", ExplodeAarTask::class.java) { task -> - task.inputArtifactListFile.set(processArtifactsTask.get().artifactOutput) - } } private fun readArtifacts(file: File): List { @@ -235,9 +235,9 @@ constructor( } } - private fun initializers(project: Project) { - this.extension = project.extensions.create(Extension.NAME, Extension::class.java) + private fun initializers() { RClassTransformer.project = project + this.extension = project.extensions.create(Extension.NAME, Extension::class.java) projectConfigurations = ProjectConfigurations(project) VariantPackagesProperty.setVariantPackagesProperty(project) } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantPackagesProperty.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantPackagesProperty.kt index bbe80fac..afe6e547 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantPackagesProperty.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantPackagesProperty.kt @@ -5,13 +5,17 @@ import org.gradle.api.Project import org.gradle.api.provider.MapProperty object VariantPackagesProperty { - private lateinit var properties: MapProperty> + private lateinit var properties: MapProperty> - fun getVariantPackagesProperty(): MapProperty> { + fun getVariantPackagesProperty(): MapProperty> { return properties } fun setVariantPackagesProperty(project: Project) { - properties = project.objects.mapProperty(String::class.java, List::class.java as Class>) + properties = + project.objects.mapProperty( + String::class.java, + List::class.java as Class> + ) } } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/AndroidArchiveLibrary.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/AndroidArchiveLibrary.kt index 7925781a..4da459ea 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/AndroidArchiveLibrary.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/AndroidArchiveLibrary.kt @@ -1,6 +1,5 @@ package com.callstack.react.brownfield.utils -import com.android.build.gradle.LibraryExtension import com.callstack.react.brownfield.shared.UnresolvedArtifactInfo import org.gradle.api.Project import java.io.File @@ -10,6 +9,7 @@ class AndroidArchiveLibrary( artifact: UnresolvedArtifactInfo, private val variantName: String, ) { + private var packageName: String? = null private val artifact: UnresolvedArtifactInfo = requireNotNull(artifact.takeIf { it.type == "aar" }) { "Only Aar is accepted as an artifact" @@ -22,8 +22,30 @@ class AndroidArchiveLibrary( @Synchronized fun getPackageName(): String { - val androidExtension = project.rootProject.project(":${artifact.moduleName}").extensions.getByType(LibraryExtension::class.java) - return androidExtension.namespace!! + if (packageName != null) return packageName!! + + packageName = getNameSpaceFromBuildGradle() + return packageName!! + } + + private fun getNameSpaceFromBuildGradle(): String { + val subProj = project.rootProject.project(":${artifact.moduleName}") + val buildFile = subProj.buildFile // points to build.gradle or build.gradle.kts + + if (!buildFile.exists()) { + error("build.gradle file does not exist for ${artifact.moduleName}") + } + + val text = buildFile.readText() + + // Regex to match: namespace = "com.example.rnscreens" + val regex = Regex("""namespace\s*=?\s*["']([^"']+)["']""") + val match = regex.find(text) + + val namespace = match?.groupValues?.get(1) + ?: error("No namespace found in ${buildFile.path}") + + return namespace } fun getManifestFile() = File(getExplodedAarRootDir(), "AndroidManifest.xml") diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/DirectoryManager.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/DirectoryManager.kt index bac333d5..aa40a0d2 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/DirectoryManager.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/DirectoryManager.kt @@ -18,7 +18,7 @@ import java.io.File object DirectoryManager : BaseProject() { fun getMergeClassDirectory(variant: LibraryVariant): File { - return File("$buildDir/intermediates/$INTERMEDIATES_TEMP_DIR/merge_classes/${variant.name}") + return project.file("$buildDir/intermediates/$INTERMEDIATES_TEMP_DIR/merge_classes/${variant.name}") } fun getKotlinMetaDirectory(variant: LibraryVariant): File { From 9cd0328646eb36072103f1711e19be44c6ef64cb Mon Sep 17 00:00:00 2001 From: Hur Ali Date: Tue, 3 Feb 2026 19:44:11 +0500 Subject: [PATCH 11/12] perf: optimize explodeAarTask --- .../brownfield/plugin/RNBrownfieldPlugin.kt | 55 ++++++-------- .../brownfield/processors/VariantHelper.kt | 29 +++---- .../processors/VariantTaskProvider.kt | 2 +- .../react/brownfield/shared/ExplodeAarTask.kt | 76 +++++++++++-------- .../brownfield/utils/DirectoryManager.kt | 23 ++---- 5 files changed, 83 insertions(+), 102 deletions(-) diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt index d9161a20..6479815d 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt @@ -80,39 +80,6 @@ constructor( it.artifactOutput.set(project.layout.buildDirectory.file("artifacts-list.jsonl")) } - /** - * Trigger the processVariants internal here to register the tasks - * - Can not do this because they require artifacts and we only get those in preBuild - * - let's try invoking those in preBuild configuration phase? - * - * - add explode tasks to explode.txt as part of processArtifacts - * - read that file to register task dependency in preBuild - * - basically what can be evaluated earlier in processArtifacts should be moved there and later read in preBuild - * - Also once this is done, invoke a function like processVariant directly in preBuild.configure phase to register - * all the tasks required. - * */ - - project.tasks.register("generateTPLAar", GenerateTPLAar::class.java) { task -> - task.inputTaskList.set(processArtifactsTask.get().outputFile) - - val file = task.inputTaskList.get().asFile - if (file.exists()) { - file.readLines().forEach { line -> - val lineSplits = line.split(",") - - val projectPath = lineSplits[0] - val taskName = lineSplits[1] - val artifactProject = project.rootProject.project(projectPath) - - artifactProject.tasks.findByName(taskName)?.let { task.dependsOn(it) } - } - } - } - - project.tasks.register("explodeAarTask", ExplodeAarTask::class.java) { task -> - task.inputArtifactListFile.set(processArtifactsTask.get().artifactOutput) - } - val jniLibsProcessor = JNILibsProcessor() jniLibsProcessor.project = project @@ -125,6 +92,28 @@ constructor( // process manifest & merger task project.extensions.getByType(LibraryExtension::class.java).libraryVariants.all { variant -> val capitalizedVariantName = variant.name.replaceFirstChar(Char::titlecase) + + project.tasks.register("explode${capitalizedVariantName}Aar", ExplodeAarTask::class.java) { task -> + task.inputArtifactListFile.set(processArtifactsTask.get().artifactOutput) + task.inputTaskList.set(processArtifactsTask.get().outputFile) + + task.variantName.set(variant.name) + task.minifyEnabled.set(variant.buildType.isMinifyEnabled) + + val file = task.inputTaskList.get().asFile + if (file.exists()) { + file.readLines().forEach { line -> + val lineSplits = line.split(",") + + val projectPath = lineSplits[0] + val taskName = lineSplits[1] + val artifactProject = project.rootProject.project(projectPath) + + artifactProject.tasks.findByName(taskName)?.let { task.dependsOn(it) } + } + } + } + val processManifestTask = variant.outputs.first().processManifestProvider.get() val artifacts = readArtifacts(processArtifactsTask.get().artifactOutput.get().asFile) diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantHelper.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantHelper.kt index 70168837..14338002 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantHelper.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantHelper.kt @@ -1,16 +1,5 @@ -@file:Suppress("DEPRECATION") - -/** - * Suppressing because of LibraryVariant. - * We can't use the new `com.android.build.gradle.api.LibraryVariant` - * as of now. - * - * We may want to re-visit this in future. - */ - package com.callstack.react.brownfield.processors -import com.android.build.gradle.api.LibraryVariant import com.callstack.react.brownfield.shared.BaseProject import com.callstack.react.brownfield.utils.AndroidArchiveLibrary import com.callstack.react.brownfield.utils.DirectoryManager @@ -20,16 +9,16 @@ import java.nio.file.Files import java.nio.file.Path import java.nio.file.Paths -class VariantHelper(private val variant: LibraryVariant) : BaseProject() { - private fun getClassPathDirFiles(): ConfigurableFileCollection { +class VariantHelper : BaseProject() { + private fun getClassPathDirFiles(variantName: String): ConfigurableFileCollection { return project.files( - "$buildDir/intermediates/javac/${variant.name}/compile${variant.name.replaceFirstChar(Char::titlecase)}JavaWithJavac/classes", + "$buildDir/intermediates/javac/$variantName/compile${variantName.replaceFirstChar(Char::titlecase)}JavaWithJavac/classes", ) } - fun classesMergeTaskDoFirst(outputDir: File) { + fun classesMergeTaskDoFirst(outputDir: File, variantName: String) { val pathsToDelete = mutableListOf() - val javacDir = getClassPathDirFiles().first() + val javacDir = getClassPathDirFiles(variantName).first() project.fileTree(outputDir).forEach { path -> pathsToDelete.add(Paths.get(outputDir.absolutePath).relativize(Paths.get(path.absolutePath))) } @@ -43,12 +32,14 @@ class VariantHelper(private val variant: LibraryVariant) : BaseProject() { outputDir: File, aarLibraries: Collection, jarFiles: MutableList, + variantName: String, + isMinifyEnabled: Boolean ) { MergeProcessor.mergeClassesJarIntoClasses(project, aarLibraries, outputDir) - if (variant.buildType.isMinifyEnabled) { + if (isMinifyEnabled) { MergeProcessor.mergeLibsIntoClasses(project, aarLibraries, jarFiles, outputDir) } - val javacDir = getClassPathDirFiles().first() + val javacDir = getClassPathDirFiles(variantName).first() project.copy { copyTask -> copyTask.from(outputDir) copyTask.into(javacDir) @@ -57,7 +48,7 @@ class VariantHelper(private val variant: LibraryVariant) : BaseProject() { project.copy { copyTask -> copyTask.from("${outputDir.absolutePath}/META-INF") - copyTask.into(DirectoryManager.getKotlinMetaDirectory(variant)) + copyTask.into(DirectoryManager.getKotlinMetaDirectory(variantName)) copyTask.include("*.kotlin_module") } } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt index fa634b34..757aae6e 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt @@ -56,5 +56,5 @@ class VariantTaskProvider: BaseProject() { } } - private fun getReBundleFilePath(folderName: String, variant: LibraryVariant) = "${DirectoryManager.getReBundleDirectory(variant).path}/$folderName" + private fun getReBundleFilePath(folderName: String, variant: LibraryVariant) = "${DirectoryManager.getReBundleDirectory(variant.name).path}/$folderName" } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ExplodeAarTask.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ExplodeAarTask.kt index 74f201d6..48b83c9b 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ExplodeAarTask.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ExplodeAarTask.kt @@ -6,6 +6,8 @@ import com.callstack.react.brownfield.utils.AndroidArchiveLibrary import com.callstack.react.brownfield.utils.DirectoryManager import org.gradle.api.DefaultTask import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input import org.gradle.api.tasks.InputFile import org.gradle.api.tasks.TaskAction import java.io.File @@ -15,47 +17,57 @@ abstract class ExplodeAarTask: DefaultTask() { @get:InputFile abstract val inputArtifactListFile: RegularFileProperty + @get:InputFile + abstract val inputTaskList: RegularFileProperty + + @get:Input + abstract val variantName: Property + + @get:Input + abstract val minifyEnabled: Property + @TaskAction fun run() { val file = inputArtifactListFile.get().asFile val artifacts = readArtifacts(file) + val resolvedVariantName = variantName.get() + + val variantHelper = VariantHelper() + variantHelper.project = project - project.extensions.getByType(LibraryExtension::class.java).libraryVariants.all { variant -> - val variantHelper = VariantHelper(variant) - variantHelper.project = project + // classes-merge + variantHelper.classesMergeTaskDoFirst( + DirectoryManager.getMergeClassDirectory( + resolvedVariantName + ), + resolvedVariantName + ) - // classes-merge - variantHelper.classesMergeTaskDoFirst( - DirectoryManager.getMergeClassDirectory( - variant + val aarLibraries = mutableListOf() + artifacts.forEach { art -> + val archiveLibrary = + AndroidArchiveLibrary( + this.project, + art, + resolvedVariantName, ) - ) - - val aarLibraries = mutableListOf() - artifacts.forEach { art -> - val archiveLibrary = - AndroidArchiveLibrary( - this.project, - art, - variant.name, - ) - - aarLibraries.add(archiveLibrary) - - // explode-aar - val zipFolder = archiveLibrary.getExplodedAarRootDir() - zipFolder.mkdirs() - - project.copy { - zipFolder.deleteRecursively() - it.from(project.zipTree(art.file)) - it.into(zipFolder) - } - } - // classes-merge - variantHelper.classesMergeTaskDoLast(DirectoryManager.getMergeClassDirectory(variant), aarLibraries, mutableListOf()) + aarLibraries.add(archiveLibrary) + + // explode-aar + val zipFolder = archiveLibrary.getExplodedAarRootDir() + zipFolder.mkdirs() + + project.copy { + zipFolder.deleteRecursively() + it.from(project.zipTree(art.file)) + it.into(zipFolder) + } } + + // classes-merge + val mergeClassesOutputDir = DirectoryManager.getMergeClassDirectory(resolvedVariantName) + variantHelper.classesMergeTaskDoLast(mergeClassesOutputDir, aarLibraries, mutableListOf(), resolvedVariantName, minifyEnabled.get()) } private fun readArtifacts(file: File): List { diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/DirectoryManager.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/DirectoryManager.kt index aa40a0d2..1f9c1e5b 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/DirectoryManager.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/DirectoryManager.kt @@ -1,31 +1,20 @@ -@file:Suppress("DEPRECATION") - -/** - * Suppressing because of LibraryVariant. - * We can't use the new `com.android.build.gradle.api.LibraryVariant` - * as of now. - * - * We may want to re-visit this in future. - */ - package com.callstack.react.brownfield.utils -import com.android.build.gradle.api.LibraryVariant import com.callstack.react.brownfield.shared.BaseProject import com.callstack.react.brownfield.shared.Constants.INTERMEDIATES_TEMP_DIR import com.callstack.react.brownfield.shared.Constants.RE_BUNDLE_FOLDER import java.io.File object DirectoryManager : BaseProject() { - fun getMergeClassDirectory(variant: LibraryVariant): File { - return project.file("$buildDir/intermediates/$INTERMEDIATES_TEMP_DIR/merge_classes/${variant.name}") + fun getMergeClassDirectory(variantName: String): File { + return project.file("$buildDir/intermediates/$INTERMEDIATES_TEMP_DIR/merge_classes/$variantName") } - fun getKotlinMetaDirectory(variant: LibraryVariant): File { - return project.file("$buildDir/tmp/kotlin-classes/${variant.name}/META-INF") + fun getKotlinMetaDirectory(variantName: String): File { + return project.file("$buildDir/tmp/kotlin-classes/$variantName/META-INF") } - fun getReBundleDirectory(variant: LibraryVariant): File { - return project.file("$buildDir/outputs/$RE_BUNDLE_FOLDER/${variant.name}") + fun getReBundleDirectory(variantName: String): File { + return project.file("$buildDir/outputs/$RE_BUNDLE_FOLDER/$variantName") } } From dbdde63ab1b844b946e2793c4ca3cd69facd829e Mon Sep 17 00:00:00 2001 From: Hur Ali Date: Tue, 3 Feb 2026 20:30:20 +0500 Subject: [PATCH 12/12] feat: improvements --- .../brownfield/artifacts/ArtifactsResolver.kt | 5 +-- .../brownfield/artifacts/FlavorArtifact.kt | 16 ++-------- .../brownfield/plugin/RNBrownfieldPlugin.kt | 32 +++++++++++-------- .../brownfield/processors/JNILibsProcessor.kt | 22 +++---------- .../processors/ProguardProcessor.kt | 26 ++++----------- .../brownfield/processors/VariantProcessor.kt | 15 ++------- .../processors/VariantTaskProvider.kt | 9 +++--- .../react/brownfield/shared/ExplodeAarTask.kt | 3 +- .../react/brownfield/shared/GenerateTPLAar.kt | 11 ------- 9 files changed, 43 insertions(+), 96 deletions(-) delete mode 100644 gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/GenerateTPLAar.kt diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/ArtifactsResolver.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/ArtifactsResolver.kt index b53f66f2..8f91e929 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/ArtifactsResolver.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/ArtifactsResolver.kt @@ -115,7 +115,7 @@ class ArtifactsResolver( if (artifacts.isNotEmpty()) { val processor = VariantProcessor() processor.project = baseProject.project - processor.processVariant(variant) + processor.processVariant(variant.name) } } @@ -173,7 +173,7 @@ class ArtifactsResolver( val variantTaskProvider = VariantTaskProvider() variantTaskProvider.project = baseProject.project - val flavorArtifact = FlavorArtifact(variant, configuration) + val flavorArtifact = FlavorArtifact(configuration) flavorArtifact.project = baseProject.project val bundleTaskProvider = BundleTaskProvider(variantTaskProvider) @@ -188,6 +188,7 @@ class ArtifactsResolver( fileResolver, taskDependencyFactory, bundleProvider, + variant.name ) when (val asd = resolvedArtifact.id) { diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/FlavorArtifact.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/FlavorArtifact.kt index 30d1ef97..ddf7c63a 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/FlavorArtifact.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/FlavorArtifact.kt @@ -1,17 +1,6 @@ -@file:Suppress("DEPRECATION") - -/** - * Suppressing because of LibraryVariant. - * We can't use the new `com.android.build.gradle.api.LibraryVariant` - * as of now. - * - * We may want to re-visit this in future. - */ - package com.callstack.react.brownfield.artifacts import org.gradle.api.component.Artifact -import com.android.build.gradle.api.LibraryVariant import com.callstack.react.brownfield.shared.BaseProject import org.gradle.api.Task import org.gradle.api.artifacts.Configuration @@ -28,12 +17,13 @@ import org.gradle.internal.component.local.model.PublishArtifactLocalArtifactMet import org.gradle.internal.component.model.DefaultIvyArtifactName import java.io.File -class FlavorArtifact(private val variant: LibraryVariant, +class FlavorArtifact( private val configuration: Configuration) : BaseProject() { fun createFlavorArtifact( fileResolver: FileResolver, taskDependencyFactory: TaskDependencyFactory, bundleTaskProvider: TaskProvider?, + variantName: String ): ResolvedArtifactResult { val artifactFile = createArtifactFile(bundleTaskProvider?.get() as Task) val artifactName = DefaultIvyArtifactName(artifactFile.name, "aar", "") @@ -45,7 +35,7 @@ class FlavorArtifact(private val variant: LibraryVariant, ), configuration.attributes, ImmutableCapabilities.EMPTY, - Describables.of(variant.name), + Describables.of(variantName), Artifact::class.java, artifactFile ) diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt index 6479815d..fd79b2c0 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt @@ -1,5 +1,6 @@ package com.callstack.react.brownfield.plugin +import com.android.build.api.variant.AndroidComponentsExtension import com.android.build.gradle.LibraryExtension import com.android.build.gradle.internal.LoggerWrapper import com.android.build.gradle.internal.coverage.JacocoReportTask.JacocoReportWorkerAction.Companion.logger @@ -16,7 +17,6 @@ import com.callstack.react.brownfield.processors.VariantTaskProvider import com.callstack.react.brownfield.shared.BaseProject import com.callstack.react.brownfield.shared.Constants.PROJECT_ID import com.callstack.react.brownfield.shared.ExplodeAarTask -import com.callstack.react.brownfield.shared.GenerateTPLAar import com.callstack.react.brownfield.shared.JsonInstance import com.callstack.react.brownfield.shared.ProcessArtifactsTask import com.callstack.react.brownfield.shared.UnresolvedArtifactInfo @@ -109,13 +109,13 @@ constructor( val taskName = lineSplits[1] val artifactProject = project.rootProject.project(projectPath) - artifactProject.tasks.findByName(taskName)?.let { task.dependsOn(it) } + if (taskName.contains(capitalizedVariantName)) { + artifactProject.tasks.findByName(taskName)?.let { task.dependsOn(it) } + } } } } - val processManifestTask = variant.outputs.first().processManifestProvider.get() - val artifacts = readArtifacts(processArtifactsTask.get().artifactOutput.get().asFile) val filteredArtifacts = artifacts.filter { it.bundleTaskName?.contains(capitalizedVariantName) == true } val aarLibraries = mutableListOf() @@ -129,9 +129,13 @@ constructor( aarLibraries.add(archiveLibrary) } + /** + * Flat IDs to be put into the variant property, required for RClass Transformer + */ val packageIDs = aarLibraries.map { it.getPackageName() } VariantPackagesProperty.getVariantPackagesProperty().put(variant.name, packageIDs) + val processManifestTask = variant.outputs.first().processManifestProvider.get() processManifestTask.doLast { // manifest-merger val buildDir = project.layout.buildDirectory.get() @@ -159,11 +163,9 @@ constructor( throw TaskNotFound("Task $taskPath not found") } - aarLibraries.forEach { - variant.registerGeneratedResFolders( - project.files(it.getResDir()), - ) - } + variant.registerGeneratedResFolders( + project.files(aarLibraries.map { it.getResDir() }), + ) /** ======= GENERATE ASSETS ========= */ val assetsTask = variant.mergeAssetsProvider.get() @@ -174,21 +176,23 @@ constructor( filteredSourceSets.forEach { sourceSet -> val filteredAarLibs = aarLibraries.filter { it.getAssetsDir().exists() } - filteredAarLibs.forEach { - sourceSet.assets.srcDir(it.getAssetsDir()) + if (!filteredAarLibs.isEmpty()) { + sourceSet.assets.srcDirs(filteredAarLibs.map { it.getAssetsDir() }) } } } - jniLibsProcessor.processJniLibs(aarLibraries, variant) - val proguardRules = aarLibraries.map { it.getProguardRules() } + /** ===== jniLibsProcessor ===== */ + jniLibsProcessor.processJniLibs(aarLibraries, variant.name) + /** ===== proguardProcessor ===== */ + val proguardRules = aarLibraries.map { it.getProguardRules() } proguardProcessor.processConsumerFiles(proguardRules, capitalizedVariantName) proguardProcessor.processGeneratedFiles(proguardRules, capitalizedVariantName) /** ===== processDataBinding ===== */ val bundleTask = variantTaskProvider.bundleTaskProvider(project, variant.name) - variantTaskProvider.processDataBinding(bundleTask, aarLibraries, variant) + variantTaskProvider.processDataBinding(bundleTask, aarLibraries, variant.name) } } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/JNILibsProcessor.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/JNILibsProcessor.kt index 5ea6e4d3..2b404dfa 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/JNILibsProcessor.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/JNILibsProcessor.kt @@ -1,17 +1,6 @@ -@file:Suppress("DEPRECATION") - -/** - * Suppressing because of LibraryVariant. - * We can't use the new `com.android.build.gradle.api.LibraryVariant` - * as of now. - * - * We may want to re-visit this in future. - */ - package com.callstack.react.brownfield.processors import com.android.build.gradle.LibraryExtension -import com.android.build.gradle.api.LibraryVariant import com.callstack.react.brownfield.exceptions.TaskNotFound import com.callstack.react.brownfield.shared.BaseProject import com.callstack.react.brownfield.shared.Logging @@ -24,9 +13,9 @@ import java.io.File class JNILibsProcessor : BaseProject() { fun processJniLibs( aarLibraries: Collection, - variant: LibraryVariant, + variantName: String, ) { - val capitalizedVariantName = variant.name.replaceFirstChar(Char::titlecase) + val capitalizedVariantName = variantName.replaceFirstChar(Char::titlecase) val taskName = "merge${capitalizedVariantName}JniLibFolders" val mergeJniLibsTask = project.tasks.named(taskName) @@ -35,7 +24,7 @@ class JNILibsProcessor : BaseProject() { } val androidExtension = project.extensions.getByName("android") as LibraryExtension - val copyTask = copySoLibsTask(variant) + val copyTask = copySoLibsTask(variantName) mergeJniLibsTask.configure { it.dependsOn(copyTask) @@ -50,7 +39,7 @@ class JNILibsProcessor : BaseProject() { val jniDir = archiveLibrary.getJniDir() processNestedLibs(jniDir.listFiles(), existingJNILibs) if (jniDir.exists()) { - val filteredSourceSets = androidExtension.sourceSets.filter { sourceSet -> sourceSet.name == variant.name } + val filteredSourceSets = androidExtension.sourceSets.filter { sourceSet -> sourceSet.name == variantName } filteredSourceSets.forEach { sourceSet -> sourceSet.jniLibs.srcDir(jniDir) } } } @@ -58,8 +47,7 @@ class JNILibsProcessor : BaseProject() { } } - private fun copySoLibsTask(variant: LibraryVariant): TaskProvider { - val variantName = variant.name + private fun copySoLibsTask(variantName: String): TaskProvider { val capitalizedVariant = variantName.replaceFirstChar(Char::titlecase) val projectExt = project.extensions.getByType(Extension::class.java) diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ProguardProcessor.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ProguardProcessor.kt index 217e835f..d89119ad 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ProguardProcessor.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ProguardProcessor.kt @@ -1,13 +1,3 @@ -@file:Suppress("DEPRECATION") - -/** - * Suppressing because of LibraryVariant. - * We can't use the new `com.android.build.gradle.api.LibraryVariant` - * as of now. - * - * We may want to re-visit this in future. - */ - package com.callstack.react.brownfield.processors import com.callstack.react.brownfield.exceptions.TaskNotFound @@ -30,11 +20,9 @@ class ProguardProcessor : BaseProject() { throw TaskNotFound("Task $mergeTaskName not found") } - mergeFileTask.configure { task -> - task.doLast { - val outputFile = it.outputs.files.singleFile - doLast(proguardRules, outputFile) - } + mergeFileTask.get().doLast { + val outputFile = it.outputs.files.singleFile + doLast(proguardRules, outputFile) } } @@ -46,11 +34,9 @@ class ProguardProcessor : BaseProject() { val mergeName = "merge${capitalizedVariantName}GeneratedProguardFiles" mergeGenerateProguardTask = project.tasks.named(mergeName) - mergeGenerateProguardTask.configure { task -> - task.doLast { - val outputFile = it.outputs.files.singleFile - doLast(proguardRules, outputFile) - } + mergeGenerateProguardTask.get().doLast { + val outputFile = it.outputs.files.singleFile + doLast(proguardRules, outputFile) } } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt index 8b380d01..3b56163b 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantProcessor.kt @@ -1,23 +1,12 @@ -@file:Suppress("DEPRECATION") - -/** - * Suppressing because of LibraryVariant. - * We can't use the new `com.android.build.gradle.api.LibraryVariant` - * as of now. - * - * We may want to re-visit this in future. - */ - package com.callstack.react.brownfield.processors -import com.android.build.gradle.api.LibraryVariant import com.android.build.gradle.internal.tasks.factory.dependsOn import com.callstack.react.brownfield.exceptions.TaskNotFound import com.callstack.react.brownfield.shared.BaseProject class VariantProcessor : BaseProject() { - fun processVariant(variant: LibraryVariant) { - val capitalizedVariantName = variant.name.replaceFirstChar(Char::titlecase) + fun processVariant(variantName: String) { + val capitalizedVariantName = variantName.replaceFirstChar(Char::titlecase) val preBuildTaskPath = "pre${capitalizedVariantName}Build" val prepareTask = project.tasks.named(preBuildTaskPath) diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt index 757aae6e..2665b293 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt @@ -1,6 +1,5 @@ package com.callstack.react.brownfield.processors -import com.android.build.gradle.api.LibraryVariant import com.callstack.react.brownfield.shared.BaseProject import com.callstack.react.brownfield.utils.AndroidArchiveLibrary import com.callstack.react.brownfield.utils.DirectoryManager @@ -27,14 +26,14 @@ class VariantTaskProvider: BaseProject() { fun processDataBinding( bundleTask: TaskProvider, aarLibraries: Collection, - variant: LibraryVariant, + variantName: String, ) { bundleTask.configure { task -> task.doLast { aarLibraries.forEach { val dataBindingFolder = it.getDataBindingFolder() if (dataBindingFolder.exists()) { - val filePath = getReBundleFilePath(dataBindingFolder.name, variant) + val filePath = getReBundleFilePath(dataBindingFolder.name, variantName) File(filePath).mkdirs() project.copy { copyTask -> copyTask.from(dataBindingFolder) @@ -44,7 +43,7 @@ class VariantTaskProvider: BaseProject() { val dataBindingLogFolder = it.getDataBindingLogFolder() if (dataBindingLogFolder.exists()) { - val filePath = getReBundleFilePath(dataBindingLogFolder.name, variant) + val filePath = getReBundleFilePath(dataBindingLogFolder.name, variantName) File(filePath).mkdirs() project.copy { copyTask -> copyTask.from(dataBindingLogFolder) @@ -56,5 +55,5 @@ class VariantTaskProvider: BaseProject() { } } - private fun getReBundleFilePath(folderName: String, variant: LibraryVariant) = "${DirectoryManager.getReBundleDirectory(variant.name).path}/$folderName" + private fun getReBundleFilePath(folderName: String, variantName: String) = "${DirectoryManager.getReBundleDirectory(variantName).path}/$folderName" } diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ExplodeAarTask.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ExplodeAarTask.kt index 48b83c9b..f34163cf 100644 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ExplodeAarTask.kt +++ b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ExplodeAarTask.kt @@ -44,7 +44,8 @@ abstract class ExplodeAarTask: DefaultTask() { ) val aarLibraries = mutableListOf() - artifacts.forEach { art -> + val filteredArtifacts = artifacts.filter { it.bundleTaskName?.lowercase()?.contains(resolvedVariantName) == true } + filteredArtifacts.forEach { art -> val archiveLibrary = AndroidArchiveLibrary( this.project, diff --git a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/GenerateTPLAar.kt b/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/GenerateTPLAar.kt deleted file mode 100644 index 3242bfc1..00000000 --- a/gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/GenerateTPLAar.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.callstack.react.brownfield.shared - -import org.gradle.api.DefaultTask -import org.gradle.api.file.RegularFileProperty -import org.gradle.api.tasks.InputFile - -abstract class GenerateTPLAar: DefaultTask() { - - @get:InputFile - abstract val inputTaskList: RegularFileProperty -} \ No newline at end of file