Slackbot
09/26/2023, 5:20 PMVampire
09/26/2023, 5:34 PMRubydesic
09/26/2023, 5:42 PMval configureStripProguard: Task by tasks.register("configureStripProguard") {
dependsOn(getRuntimeClasses)
notCompatibleWithConfigurationCache("configures another task")
doLast {
// Configure the stripProguard task to copy from the proguard jar and exclude the runtime classes: see below
stripProguard.apply {
from(zipTree(proguardJarFile)) {
exclude(getRuntimeClasses.get().classes)
}
}
}
}
Rubydesic
09/26/2023, 5:43 PMRubydesic
09/26/2023, 5:44 PM/**
* A task which returns a list of the paths of every class in every JAR in the given set of files
*/
abstract class GetClassesInClasspath : DefaultTask() {
@get:InputFiles
@get:CompileClasspath
abstract val inputFiles: ConfigurableFileCollection
@Internal
lateinit var classes: Set<String>
@TaskAction
fun writeClasses() {
classes = inputFiles
.flatMap { jar ->
JarFile(jar).entries().asSequence()
.map { it.name }
.filter { it.endsWith(".class") && it != "module-info.class" }
}
.toSortedSet()
}
}
/**
* Get the list of all the class files on the runtime classpath (aka, libraries that are *not* shaded)
*/
val getRuntimeClasses: TaskProvider<GetClassesInClasspath> = tasks.register<GetClassesInClasspath>("getRuntimeClasses") {
inputFiles.from(configurations.runtimeClasspath)
}
Vampire
09/26/2023, 6:20 PMGetClassesInClasspath
is not really idiomatic.
You should not set a task property that you then read in another task.
If you need to transport information like that, you should probably use a shared build service.
And also it might easily break, as a classpath can also contain directories, not only jar files.
And a classpath might even contain non-existent entries in the Java world. (not fully sure if this could happen within Gradle right now)
Actually, anytime you need to do a dependsOn
manually (except with a lifecycle task on the left-hand side) you have a code smell and most probably do something in a non-optimal way.
Without having tried, I guess you should do the filename gathering in a shared build service that you then use in the exclude spec.
And the exclude spec can be a closure / lambda so that it is not evaluated at configuration time immediately, but only when needed.
Not fully your use-case, but this for example is CC-safe:
tasks.jar {
val runtimeClasspath: FileCollection = configurations.runtimeClasspath.get()
exclude { runtimeClasspath.files.contains(it.file) }
}
Rubydesic
09/26/2023, 6:34 PMGetClassesInClasspath
is a little fragile but it works for my purposes, unless you have a convenient other suggestion. But it's not too important.
To make your bottom suggestion work, I need to modify it a bit, but calling this method for every single file in the jar is pretty ridiculous. I will look into a shared build service.
fun classes() = configurations.runtimeClasspath.get()
.flatMap { jar ->
JarFile(jar).entries().asSequence()
.map { it.name }
.filter { it.endsWith(".class") && it != "module-info.class" }
}
.toSortedSet()
from(zipTree(proguardJarFile)) {
exclude { classes().contains(it.name) }
}
Rubydesic
09/26/2023, 6:36 PMVampire
09/26/2023, 6:36 PMbut calling this method for every single file in the jar is pretty ridiculousExactly, that's why I not suggested to do it like that, just to give you a general idea about CC-safety. 😉 You could maybe use a
val classes by lazy { ... }
then it will only be calculated once, but I'm not sure right now whether that will be CC-safe.Rubydesic
09/26/2023, 6:37 PMRubydesic
09/26/2023, 7:01 PMVampire
09/26/2023, 7:02 PMVampire
09/26/2023, 7:03 PMRubydesic
09/26/2023, 7:06 PMRubydesic
09/26/2023, 7:07 PMFileSystemOperations#jar
method that we could call insteadRubydesic
09/26/2023, 7:40 PMRubydesic
09/26/2023, 7:41 PMVampire
09/27/2023, 6:58 AM