Skip to content

Commit

Permalink
Support configuration-cache feature
Browse files Browse the repository at this point in the history
  • Loading branch information
5peak2me committed Jan 24, 2025
1 parent d8debac commit f36fb1b
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 84 deletions.
8 changes: 7 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,11 @@ org.gradle.jvmargs=-Xmx4608m -Dfile.encoding=UTF-8

kotlin.code.style=official
kotlin.mpp.stability.nowarn=true

android.useAndroidX=true
android.experimental.legacyTransform.forceNonIncremental=true
android.experimental.legacyTransform.forceNonIncremental=true

org.gradle.configuration-cache=true
org.gradle.configuration-cache.max-problems=5
org.gradle.configuration-cache.parallel=true
org.gradle.configuration-cache.problems=warn
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,30 @@

package com.spotify.ruler.common.dependency

import java.io.Serializable
import kotlinx.serialization.Serializable as KSerializable

/** Single entry of a dependency. */
sealed class DependencyEntry {
@KSerializable
sealed class DependencyEntry: Serializable {
abstract val name: String
abstract val component: String

/** Default dependency entry. If an entry has no special type, it is considered to be a default entry. */
@KSerializable
data class Default(
override val name: String,
override val component: String,
) : DependencyEntry()

/** Class file dependency entry. */
@KSerializable
data class Class(
override val name: String,
override val component: String,
) : DependencyEntry()

companion object {
private const val serialVersionUID = 1L
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import com.android.build.api.variant.ApplicationVariant
import com.spotify.ruler.common.models.AppInfo
import com.spotify.ruler.common.models.DeviceSpec
import com.spotify.ruler.common.veritication.VerificationConfig
import com.spotify.ruler.plugin.dependency.EntryParser
import org.codehaus.groovy.runtime.StringGroovyMethods
import org.gradle.api.Plugin
import org.gradle.api.Project
Expand All @@ -47,6 +48,13 @@ class RulerPlugin : Plugin<Project> {
RulerTask::class.java
) { task ->
task.group = name

val resolve = EntryParser().parse(variant.runtimeConfiguration)
resolve.forEach(task.dependencies::add)

task.projectPath.set(project.path)
task.sdkDirectory.set(androidComponents.sdkComponents.sdkDirectory)

task.appInfo.set(getAppInfo(project, variant))
task.deviceSpec.set(getDeviceSpec(rulerExtension))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,51 @@

package com.spotify.ruler.plugin

import com.android.build.gradle.BaseExtension
import com.spotify.ruler.common.BaseRulerTask
import com.spotify.ruler.common.apk.ApkCreator
import com.spotify.ruler.common.dependency.DependencyComponent
import com.spotify.ruler.common.dependency.DependencyEntry
import com.spotify.ruler.common.dependency.DependencySanitizer
import com.spotify.ruler.common.models.AppInfo
import com.spotify.ruler.common.models.DeviceSpec
import com.spotify.ruler.common.models.RulerConfig
import com.spotify.ruler.common.sanitizer.ClassNameSanitizer
import com.spotify.ruler.common.veritication.VerificationConfig
import com.spotify.ruler.plugin.dependency.EntryParser
import org.gradle.api.DefaultTask
import org.gradle.api.file.DirectoryProperty
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.CacheableTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputDirectory
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.PathSensitive
import org.gradle.api.tasks.PathSensitivity
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.TaskAction
import org.gradle.workers.WorkAction
import org.gradle.workers.WorkParameters
import org.gradle.workers.WorkerExecutor
import java.io.File
import javax.inject.Inject

abstract class RulerTask : DefaultTask(), BaseRulerTask {
@CacheableTask
abstract class RulerTask : DefaultTask() {

@get:Input
abstract val dependencies: ListProperty<List<DependencyEntry>>

@get:Input
abstract val projectPath: Property<String>

@get:InputDirectory
@get:PathSensitive(PathSensitivity.RELATIVE)
abstract val sdkDirectory: DirectoryProperty

@get:Input
abstract val appInfo: Property<AppInfo>
Expand All @@ -50,18 +69,22 @@ abstract class RulerTask : DefaultTask(), BaseRulerTask {
abstract val deviceSpec: Property<DeviceSpec>

@get:InputFile
@get:PathSensitive(PathSensitivity.NONE)
abstract val bundleFile: RegularFileProperty

@get:Optional
@get:InputFile
@get:PathSensitive(PathSensitivity.RELATIVE)
abstract val mappingFile: RegularFileProperty

@get:Optional
@get:InputFile
@get:PathSensitive(PathSensitivity.RELATIVE)
abstract val resourceMappingFile: RegularFileProperty

@get:Optional
@get:InputFile
@get:PathSensitive(PathSensitivity.RELATIVE)
abstract val ownershipFile: RegularFileProperty

@get:Input
Expand All @@ -72,10 +95,12 @@ abstract class RulerTask : DefaultTask(), BaseRulerTask {

@get:Optional
@get:InputFiles
@get:PathSensitive(PathSensitivity.RELATIVE)
abstract val unstrippedNativeFiles: ListProperty<RegularFile>

@get:Optional
@get:InputFile
@get:PathSensitive(PathSensitivity.RELATIVE)
abstract val staticDependenciesFile: RegularFileProperty

@get:Input
Expand All @@ -87,61 +112,103 @@ abstract class RulerTask : DefaultTask(), BaseRulerTask {
@get:OutputDirectory
abstract val reportDir: DirectoryProperty

@get:Inject
abstract val workerExecutor: WorkerExecutor

@TaskAction
fun analyze() {
run()
workerExecutor.noIsolation().submit(RulerTaskAction::class.java) {
it.dependencies.set(dependencies)
it.projectPath.set(projectPath)
it.sdkDirectory.set(sdkDirectory)
it.appInfo.set(appInfo)
it.deviceSpec.set(deviceSpec)
it.bundleFile.set(bundleFile)
it.mappingFile.set(mappingFile)
it.resourceMappingFile.set(resourceMappingFile)
it.ownershipFile.set(ownershipFile)
it.defaultOwner.set(defaultOwner)
it.omitFileBreakdown.set(omitFileBreakdown)
it.unstrippedNativeFiles.set(unstrippedNativeFiles)
it.staticDependenciesFile.set(staticDependenciesFile)
it.verificationConfig.set(verificationConfig)
it.workingDir.set(workingDir)
it.reportDir.set(reportDir)
}
}

private val config by lazy {
RulerConfig(
projectPath = project.path,
apkFilesMap = createApkFile(),
reportDir = reportDir.asFile.get(),
ownershipFile = ownershipFile.asFile.orNull,
staticDependenciesFile = staticDependenciesFile.asFile.orNull,
appInfo = appInfo.get(),
deviceSpec = deviceSpec.get(),
defaultOwner = defaultOwner.get(),
omitFileBreakdown = omitFileBreakdown.get(),
additionalEntries = emptyList(),
ignoredFiles = emptyList(),
verificationConfig = verificationConfig.get()
)
abstract class Params : WorkParameters {
abstract val dependencies: ListProperty<List<DependencyEntry>>
abstract val projectPath: Property<String>
abstract val sdkDirectory: DirectoryProperty
abstract val appInfo: Property<AppInfo>
abstract val deviceSpec: Property<DeviceSpec>
abstract val bundleFile: RegularFileProperty
abstract val mappingFile: RegularFileProperty
abstract val resourceMappingFile: RegularFileProperty
abstract val ownershipFile: RegularFileProperty
abstract val defaultOwner: Property<String>
abstract val omitFileBreakdown: Property<Boolean>
abstract val unstrippedNativeFiles: ListProperty<RegularFile>
abstract val staticDependenciesFile: RegularFileProperty
abstract val verificationConfig: Property<VerificationConfig>
abstract val workingDir: DirectoryProperty
abstract val reportDir: DirectoryProperty
}

override fun rulerConfig(): RulerConfig = config
abstract class RulerTaskAction : WorkAction<Params>, BaseRulerTask {

override fun provideDependencies(): Map<String, List<DependencyComponent>> {
val dependencyParser = EntryParser()
val entries = dependencyParser.parse(project, rulerConfig().appInfo)
override fun execute() {
run()
}

val classNameSanitizer = ClassNameSanitizer(provideMappingFile())
val dependencySanitizer = DependencySanitizer(classNameSanitizer)
return dependencySanitizer.sanitize(entries)
}
private val config by lazy {
RulerConfig(
projectPath = parameters.projectPath.get(),
apkFilesMap = createApkFile(),
reportDir = parameters.reportDir.asFile.get(),
ownershipFile = parameters.ownershipFile.asFile.orNull,
staticDependenciesFile = parameters.staticDependenciesFile.asFile.orNull,
appInfo = parameters.appInfo.get(),
deviceSpec = parameters.deviceSpec.get(),
defaultOwner = parameters.defaultOwner.get(),
omitFileBreakdown = parameters.omitFileBreakdown.get(),
additionalEntries = emptyList(),
ignoredFiles = emptyList(),
verificationConfig = parameters.verificationConfig.get(),
)
}

override fun print(content: String) = project.logger.lifecycle(content)
override fun provideMappingFile(): File? = mappingFile.asFile.orNull
override fun provideResourceMappingFile(): File? = resourceMappingFile.asFile.orNull
override fun provideUnstrippedLibraryFiles(): List<File> = unstrippedNativeFiles.get().map {
it.asFile
}
override fun rulerConfig(): RulerConfig = config

override fun provideBloatyPath() = null
override fun provideDependencies(): Map<String, List<DependencyComponent>> {
val classNameSanitizer = ClassNameSanitizer(provideMappingFile())
val dependencySanitizer = DependencySanitizer(classNameSanitizer)
return dependencySanitizer.sanitize(parameters.dependencies.get().flatMap { it })
}

private fun createApkFile(): Map<String, List<File>> {
val android = project.extensions.findByName("android") as BaseExtension?
val apkCreator = ApkCreator(android?.sdkDirectory)
override fun print(content: String) = println(content) // Use println directly?
override fun provideMappingFile(): File? = parameters.mappingFile.asFile.orNull
override fun provideResourceMappingFile(): File? = parameters.resourceMappingFile.asFile.orNull
override fun provideUnstrippedLibraryFiles(): List<File> = parameters.unstrippedNativeFiles.get().map {
it.asFile
}

val apkFile = bundleFile.asFile.get()
return if (apkFile.extension == "apk") {
mapOf(ApkCreator.BASE_FEATURE_NAME to listOf(apkFile))
} else {
apkCreator.createSplitApks(
apkFile,
deviceSpec.get(),
workingDir.asFile.get()
)
override fun provideBloatyPath() = null

private fun createApkFile(): Map<String, List<File>> {
val apkCreator = ApkCreator(parameters.sdkDirectory.asFile.get())

val apkFile = parameters.bundleFile.asFile.get()
return if (apkFile.extension == "apk") {
mapOf(ApkCreator.BASE_FEATURE_NAME to listOf(apkFile))
} else {
apkCreator.createSplitApks(
apkFile,
parameters.deviceSpec.get(),
parameters.workingDir.asFile.get(),
)
}
}
}
}
Loading

0 comments on commit f36fb1b

Please sign in to comment.