Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update vendor plugin to use non-deprecated api #5179

Merged
merged 8 commits into from
Jul 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
281 changes: 100 additions & 181 deletions buildSrc/src/main/java/com/google/firebase/gradle/plugins/VendorPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@

package com.google.firebase.gradle.plugins

import com.android.build.api.transform.Format
import com.android.build.api.transform.QualifiedContent
import com.android.build.api.transform.Transform
import com.android.build.api.transform.TransformInvocation
import com.android.build.gradle.LibraryExtension
import com.android.build.api.artifact.ScopedArtifact
import com.android.build.api.variant.LibraryAndroidComponentsExtension
import com.android.build.api.variant.ScopedArtifacts
import com.android.build.gradle.LibraryPlugin
import java.io.BufferedInputStream
import java.io.BufferedOutputStream
Expand All @@ -28,42 +26,43 @@ import java.io.FileOutputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipFile
import java.util.zip.ZipOutputStream
import javax.inject.Inject
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.logging.Logger
import org.gradle.api.file.Directory
import org.gradle.api.file.RegularFile
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.Classpath
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.create

abstract class VendorExtension {
/** Controls dead code elimination, enabled if true. */
abstract val optimize: Property<Boolean>

init {
optimize.convention(true)
}
}
import org.gradle.kotlin.dsl.getByType
import org.gradle.process.ExecOperations

class VendorPlugin : Plugin<Project> {
override fun apply(project: Project) {
val vendorConfig = project.extensions.create<VendorExtension>("vendor")
project.plugins.all {
when (this) {
is LibraryPlugin -> configureAndroid(project, vendorConfig)
is LibraryPlugin -> configureAndroid(project)
}
}
}

fun configureAndroid(project: Project, vendorConfig: VendorExtension) {
fun configureAndroid(project: Project) {
project.apply(plugin = "LicenseResolverPlugin")

val vendor = project.configurations.create("vendor")
project.configurations.all {
when (name) {
"compileOnly",
"releaseCompileOnly",
"debugImplementation",
"testImplementation",
"androidTestImplementation" -> extendsFrom(vendor)
}
Expand All @@ -72,174 +71,63 @@ class VendorPlugin : Plugin<Project> {
val jarJar = project.configurations.create("firebaseJarJarArtifact")
project.dependencies.add("firebaseJarJarArtifact", "org.pantsbuild:jarjar:1.7.2")

val android = project.extensions.getByType(LibraryExtension::class.java)

android.registerTransform(
VendorTransform(
android,
vendor,
JarJarTransformer(
parentPackageProvider = {
android.libraryVariants.find { it.name == "release" }!!.applicationId
},
jarJarProvider = { jarJar.resolve() },
project = project,
logger = project.logger,
optimize = vendorConfig.optimize
),
logger = project.logger
)
)
}
}
val androidComponents = project.extensions.getByType<LibraryAndroidComponentsExtension>()

interface JarTransformer {
fun transform(
inputJar: File,
outputJar: File,
ownPackages: Set<String>,
packagesToVendor: Set<String>
)
}

class JarJarTransformer(
private val parentPackageProvider: () -> String,
private val jarJarProvider: () -> Collection<File>,
private val project: Project,
private val logger: Logger,
private val optimize: Provider<Boolean>
) : JarTransformer {
override fun transform(
inputJar: File,
outputJar: File,
ownPackages: Set<String>,
packagesToVendor: Set<String>
) {
val parentPackage = parentPackageProvider()
val rulesFile = File.createTempFile(parentPackage, ".jarjar")
rulesFile.printWriter().use {
if (optimize.get()) {
for (packageName in ownPackages) {
it.println("keep $packageName.**")
androidComponents.onVariants(androidComponents.selector().withBuildType("release")) { variant ->
val vendorTask =
project.tasks.register("${variant.name}VendorTransform", VendorTask::class.java) {
vendorDependencies.set(vendor)
packageName.set(variant.namespace)
this.jarJar.set(jarJar)
}
}
for (externalPackageName in packagesToVendor) {
it.println("rule $externalPackageName.** $parentPackage.@0")
}
variant.artifacts
.forScope(ScopedArtifacts.Scope.PROJECT)
.use(vendorTask)
.toTransform(
ScopedArtifact.CLASSES,
VendorTask::inputJars,
VendorTask::inputDirs,
VendorTask::outputJar
)
}
logger.info("The following JarJar configuration will be used:\n ${rulesFile.readText()}")

project
.javaexec {
main = "org.pantsbuild.jarjar.Main"
classpath = project.files(jarJarProvider())
args =
listOf("process", rulesFile.absolutePath, inputJar.absolutePath, outputJar.absolutePath)
systemProperties = mapOf("verbose" to "true", "misplacedClassStrategy" to "FATAL")
}
.assertNormalExitValue()
}
}

class VendorTransform(
private val android: LibraryExtension,
private val configuration: Configuration,
private val jarTransformer: JarTransformer,
private val logger: Logger
) : Transform() {
override fun getName() = "firebaseVendorTransform"
abstract class VendorTask @Inject constructor(private val execOperations: ExecOperations) :
DefaultTask() {
@get:[InputFiles Classpath]
abstract val vendorDependencies: Property<Configuration>

override fun getInputTypes(): MutableSet<QualifiedContent.ContentType> {
return mutableSetOf(QualifiedContent.DefaultContentType.CLASSES)
}
@get:[InputFiles Classpath]
abstract val jarJar: Property<Configuration>

override fun isIncremental() = false
@get:Input abstract val packageName: Property<String>

override fun getScopes(): MutableSet<in QualifiedContent.Scope> {
return mutableSetOf(QualifiedContent.Scope.PROJECT)
}
@get:InputFiles abstract val inputJars: ListProperty<RegularFile>

override fun getReferencedScopes(): MutableSet<in QualifiedContent.Scope> {
return mutableSetOf(QualifiedContent.Scope.PROJECT)
}
@get:InputFiles abstract val inputDirs: ListProperty<Directory>

override fun transform(transformInvocation: TransformInvocation) {
if (configuration.resolve().isEmpty()) {
logger.warn(
"Nothing to vendor. " +
"If you don't need vendor functionality please disable 'firebase-vendor' plugin. " +
"Otherwise use the 'vendor' configuration to add dependencies you want vendored in."
)
for (input in transformInvocation.inputs) {
for (directoryInput in input.directoryInputs) {
val directoryOutput =
transformInvocation.outputProvider.getContentLocation(
directoryInput.name,
setOf(QualifiedContent.DefaultContentType.CLASSES),
mutableSetOf(QualifiedContent.Scope.PROJECT),
Format.DIRECTORY
)
directoryInput.file.copyRecursively(directoryOutput, overwrite = true)
}
for (jarInput in input.jarInputs) {
val jarOutput =
transformInvocation.outputProvider.getContentLocation(
jarInput.name,
setOf(QualifiedContent.DefaultContentType.CLASSES),
mutableSetOf(QualifiedContent.Scope.PROJECT),
Format.JAR
)
@get:OutputFile abstract val outputJar: RegularFileProperty

jarInput.file.copyTo(jarOutput, overwrite = true)
}
}
return
}

val contentLocation =
transformInvocation.outputProvider.getContentLocation(
"sourceAndVendoredLibraries",
setOf(QualifiedContent.DefaultContentType.CLASSES),
mutableSetOf(QualifiedContent.Scope.PROJECT),
Format.DIRECTORY
)
contentLocation.deleteRecursively()
contentLocation.mkdirs()
val tmpDir = File(contentLocation, "tmp")
tmpDir.mkdirs()
try {
val fatJar = process(tmpDir, transformInvocation)
unzipJar(fatJar, contentLocation)
} finally {
tmpDir.deleteRecursively()
}
}

private fun isTest(transformInvocation: TransformInvocation): Boolean {
return android.testVariants.find { it.name == transformInvocation.context.variantName } != null
}
@TaskAction
fun taskAction() {
val workDir = File.createTempFile("vendorTmp", null)
workDir.mkdirs()
workDir.deleteRecursively()

private fun process(workDir: File, transformInvocation: TransformInvocation): File {
transformInvocation.context.variantName
val unzippedDir = File(workDir, "unzipped")
val unzippedExcludedDir = File(workDir, "unzipped-excluded")
unzippedDir.mkdirs()
unzippedExcludedDir.mkdirs()

val externalCodeDir = if (isTest(transformInvocation)) unzippedExcludedDir else unzippedDir
val externalCodeDir = unzippedDir

for (input in transformInvocation.inputs) {
for (directoryInput in input.directoryInputs) {
directoryInput.file.copyRecursively(unzippedDir)
}
for (jarInput in input.jarInputs) {
unzipJar(jarInput.file, unzippedDir)
}
for (directory in inputDirs.get()) {
directory.asFile.copyRecursively(unzippedDir)
}
for (jar in inputJars.get()) {
unzipJar(jar.asFile, unzippedDir)
}

val ownPackageNames = inferPackages(unzippedDir)

for (jar in configuration.resolve()) {
for (jar in vendorDependencies.get()) {
unzipJar(jar, externalCodeDir)
}
val externalPackageNames = inferPackages(externalCodeDir) subtract ownPackageNames
Expand All @@ -250,26 +138,57 @@ class VendorTransform(
throw GradleException(
"Vendoring java or javax packages is not supported. " +
"Please exclude one of the direct or transitive dependencies: \n" +
configuration.resolvedConfiguration.resolvedArtifacts.joinToString(separator = "\n")
vendorDependencies
.get()
.resolvedConfiguration
.resolvedArtifacts
.joinToString(separator = "\n")
)
}

val jar = File(workDir, "intermediate.jar")
zipAll(unzippedDir, jar)
val outputJar = File(workDir, "output.jar")

jarTransformer.transform(jar, outputJar, ownPackageNames, externalPackageNames)
return outputJar
transform(jar, ownPackageNames, externalPackageNames)
}

private fun inferPackages(dir: File): Set<String> {
return dir
.walk()
.filter { it.name.endsWith(".class") }
.map { it.parentFile.toRelativeString(dir).replace('/', '.') }
.toSet()
fun transform(inputJar: File, ownPackages: Set<String>, packagesToVendor: Set<String>) {
val parentPackage = packageName.get()
val rulesFile = File.createTempFile(parentPackage, ".jarjar")
rulesFile.printWriter().use {
for (packageName in ownPackages) {
it.println("keep $packageName.**")
}
for (externalPackageName in packagesToVendor) {
it.println("rule $externalPackageName.** $parentPackage.@0")
}
}
logger.info("The following JarJar configuration will be used:\n ${rulesFile.readText()}")

execOperations
.javaexec {
mainClass.set("org.pantsbuild.jarjar.Main")
classpath = project.files(jarJar.get())
args =
listOf(
"process",
rulesFile.absolutePath,
inputJar.absolutePath,
outputJar.asFile.get().absolutePath
)
systemProperties = mapOf("verbose" to "true", "misplacedClassStrategy" to "FATAL")
}
.assertNormalExitValue()
}
}

fun inferPackages(dir: File): Set<String> {
return dir
.walk()
.filter { it.name.endsWith(".class") }
.map { it.parentFile.toRelativeString(dir).replace('/', '.') }
.toSet()
}

fun unzipJar(jar: File, directory: File) {
ZipFile(jar).use { zip ->
zip
Expand Down
3 changes: 1 addition & 2 deletions firebase-inappmessaging-display/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Unreleased

* [unchanged] Updated internal Dagger dependency.

# 20.3.2
* [fixed] Fixed nullpointer crash when using experiments
Expand Down Expand Up @@ -289,4 +289,3 @@ additional updates.

# 17.0.0
* [feature] The initial public beta release of the Firebase In-App Messaging Display SDK for Android is now available. To learn more, see the [Firebase In-App Messaging documentation](/docs/in-app-messaging).

Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,13 @@ dependencies {
implementation 'com.github.bumptech.glide:glide:4.11.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'

vendor ('com.google.dagger:dagger:2.27') {
vendor (libs.dagger.dagger) {
exclude group: "javax.inject", module: "javax.inject"
}
annotationProcessor libs.dagger.compiler

implementation 'javax.inject:javax.inject:1'

annotationProcessor "com.google.dagger:dagger-compiler:2.27"
annotationProcessor 'com.google.auto.value:auto-value:1.6.5'
annotationProcessor 'com.ryanharter.auto.value:auto-value-parcel:0.2.6'

Expand Down
Loading