Minimizing¶
Shadow can automatically remove all JARs and classes of dependencies that are not used by the project, thereby minimizing the resulting shadowed JAR.
tasks.shadowJar {
minimize()
}
tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
minimize()
}
A dependency can be excluded from the minimization process, thereby forcing its inclusion the shadow JAR.
This is useful when the dependency analyzer cannot find the usage of a class programmatically, for example if the class
is loaded dynamically via Class.forName(String). Each of the group, name and version fields separated by : of
a dependency is interpreted as a regular expression.
tasks.shadowJar {
minimize {
exclude(dependency("org.scala-lang:.*:.*"))
}
}
tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
minimize {
exclude(dependency('org.scala-lang:.*:.*'))
}
}
Dependencies scoped as
apiwill be automatically excluded from minimization and used as “entry points” on minimization.
Similar to ShadowJar.dependencies, projects can also be excluded.
tasks.shadowJar {
minimize {
exclude(project(":api"))
}
}
tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
minimize {
exclude(project(":api"))
}
}
When excluding a
project, all dependencies of the excludedprojectare automatically excluded from minimization as well.
Minimizing with R8¶
Shadow can also run R8 over the final shadowed JAR. This is useful when you want
whole-program shrinking instead of the default dependency analyzer. R8 runs after Shadow has merged, transformed, and
relocated the JAR, so service descriptors in META-INF/services are used to keep service providers.
The default R8 configuration only shrinks unused code. It disables name minification and optimization.
repositories {
google()
}
tasks.shadowJar {
minimize {
r8 {
// Optional extra configuration
keepRules.add("-keep class com.example.ReflectiveApi { *; }")
keepRuleFiles.from(layout.projectDirectory.file("r8-rules.pro"))
}
}
}
repositories {
google()
}
tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
minimize {
r8 {
// Optional extra configuration
keepRules.add('-keep class com.example.ReflectiveApi { *; }')
keepRuleFiles.from(layout.projectDirectory.file('r8-rules.pro'))
}
}
}
Shadow resolves R8 from the shadowR8 configuration. The default dependency is com.android.tools:r8, which is
published by Google Maven rather than Maven Central. Add google() to your repositories or override the dependency:
dependencies {
shadowR8("com.android.tools:r8:9.1.31")
}
dependencies {
shadowR8 'com.android.tools:r8:9.1.31'
}
Advanced R8 command line arguments can be added with args. Replacing the default args value removes Shadow’s
default command line arguments, so prefer the helper functions for common obfuscation and optimization toggles. These
helpers are independent and can be used together.
For example, to downgrade R8 warnings to info:
repositories {
google()
}
tasks.shadowJar {
minimize {
r8 {
args.addAll(listOf("--map-diagnostics", "warning", "info"))
}
}
}
repositories {
google()
}
tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
minimize {
r8 {
args.addAll(['--map-diagnostics', 'warning', 'info'])
}
}
}
To enable name obfuscation:
repositories {
google()
}
tasks.shadowJar {
minimize {
r8 {
enableObfuscation()
}
}
}
repositories {
google()
}
tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
minimize {
r8 {
enableObfuscation()
}
}
}
To enable optimization:
repositories {
google()
}
tasks.shadowJar {
minimize {
r8 {
enableOptimization()
}
}
}
repositories {
google()
}
tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
minimize {
r8 {
enableOptimization()
}
}
}
To enable both:
repositories {
google()
}
tasks.shadowJar {
minimize {
r8 {
enableObfuscation()
enableOptimization()
}
}
}
repositories {
google()
}
tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
minimize {
r8 {
enableObfuscation()
enableOptimization()
}
}
}