Skip to content
25 changes: 25 additions & 0 deletions api/shadow.api
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,28 @@ public abstract interface class com/github/jengelman/gradle/plugins/shadow/tasks
public abstract fun inheritFrom ([Ljava/lang/Object;Lorg/gradle/api/Action;)V
}

public abstract interface class com/github/jengelman/gradle/plugins/shadow/tasks/MinimizeSpec : com/github/jengelman/gradle/plugins/shadow/tasks/DependencyFilter {
public abstract fun getTool ()Lorg/gradle/api/provider/Property;
public abstract fun r8 (Lgroovy/lang/Closure;)V
public abstract fun r8 (Lorg/gradle/api/Action;)V
}

public final class com/github/jengelman/gradle/plugins/shadow/tasks/MinimizeTool : java/lang/Enum {
public static final field DEPENDENCY_ANALYZER Lcom/github/jengelman/gradle/plugins/shadow/tasks/MinimizeTool;
public static final field R8 Lcom/github/jengelman/gradle/plugins/shadow/tasks/MinimizeTool;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public static fun valueOf (Ljava/lang/String;)Lcom/github/jengelman/gradle/plugins/shadow/tasks/MinimizeTool;
public static fun values ()[Lcom/github/jengelman/gradle/plugins/shadow/tasks/MinimizeTool;
}

public abstract interface class com/github/jengelman/gradle/plugins/shadow/tasks/R8Spec {
public abstract fun enableObfuscation ()V
public abstract fun enableOptimization ()V
public abstract fun getArgs ()Lorg/gradle/api/provider/ListProperty;
public abstract fun getKeepRuleFiles ()Lorg/gradle/api/file/ConfigurableFileCollection;
public abstract fun getKeepRules ()Lorg/gradle/api/provider/ListProperty;
}

public class com/github/jengelman/gradle/plugins/shadow/tasks/ShadowCopyAction : org/gradle/api/internal/file/copy/CopyAction {
public static final field CONSTANT_TIME_FOR_ZIP_ENTRIES J
public static final field Companion Lcom/github/jengelman/gradle/plugins/shadow/tasks/ShadowCopyAction$Companion;
Expand Down Expand Up @@ -232,13 +254,16 @@ public abstract class com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar
public fun getEnableAutoRelocation ()Lorg/gradle/api/provider/Property;
public fun getEnableKotlinModuleRemapping ()Lorg/gradle/api/provider/Property;
public fun getExcludes ()Ljava/util/Set;
protected abstract fun getExecOperations ()Lorg/gradle/process/ExecOperations;
public fun getFailOnDuplicateEntries ()Lorg/gradle/api/provider/Property;
public fun getIncludedDependencies ()Lorg/gradle/api/file/ConfigurableFileCollection;
public fun getIncludes ()Ljava/util/Set;
public fun getMainClass ()Lorg/gradle/api/provider/Property;
public fun getManifest ()Lcom/github/jengelman/gradle/plugins/shadow/tasks/InheritManifest;
public synthetic fun getManifest ()Lorg/gradle/api/java/archives/Manifest;
public fun getMinimizeJar ()Lorg/gradle/api/provider/Property;
public fun getMinimizeSpec ()Lcom/github/jengelman/gradle/plugins/shadow/tasks/MinimizeSpec;
public fun getR8Classpath ()Lorg/gradle/api/file/ConfigurableFileCollection;
public fun getRelocationPrefix ()Lorg/gradle/api/provider/Property;
public fun getRelocators ()Lorg/gradle/api/provider/SetProperty;
public fun getSourceSetsClassesDirs ()Lorg/gradle/api/file/ConfigurableFileCollection;
Expand Down
1 change: 1 addition & 0 deletions docs/changes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

- Check `DuplicatesStrategy` for merging transformers. ([#2026](https://github.com/GradleUp/shadow/pull/2026))
This will log warnings when an incompatible `DuplicatesStrategy` (e.g., `EXCLUDE`) is applied in Gradle configuration for built-in `ResourceTransformer`s.
- Add R8 as an opt-in `minimize { r8 { ... } }` tool for shrinking the final shadowed JAR.

### Changed

Expand Down
203 changes: 203 additions & 0 deletions docs/configuration/minimizing/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,209 @@ Similar to [`ShadowJar.dependencies`][ShadowJar.dependencies], projects can also
> When excluding a `project`, all dependencies of the excluded `project` are automatically excluded from
> minimization as well.

## Minimizing with R8

Shadow can also run [R8](https://r8.googlesource.com/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.

=== "Kotlin"

```kotlin
repositories {
google()
}

tasks.shadowJar {
minimize {
r8 {
// Optional extra configuration
keepRules.add("-keep class com.example.ReflectiveApi { *; }")
keepRuleFiles.from(layout.projectDirectory.file("r8-rules.pro"))
}
}
}
```

=== "Groovy"

```groovy
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:

=== "Kotlin"

```kotlin
dependencies {
shadowR8("com.android.tools:r8:9.1.31")
}
```

=== "Groovy"

```groovy
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:

=== "Kotlin"

```kotlin
repositories {
google()
}

tasks.shadowJar {
minimize {
r8 {
args.addAll(listOf("--map-diagnostics", "warning", "info"))
}
}
}
```

=== "Groovy"

```groovy
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:

=== "Kotlin"

```kotlin
repositories {
google()
}

tasks.shadowJar {
minimize {
r8 {
enableObfuscation()
}
}
}
```

=== "Groovy"

```groovy
repositories {
google()
}

tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
minimize {
r8 {
enableObfuscation()
}
}
}
```

To enable optimization:

=== "Kotlin"

```kotlin
repositories {
google()
}

tasks.shadowJar {
minimize {
r8 {
enableOptimization()
}
}
}
```

=== "Groovy"

```groovy
repositories {
google()
}

tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
minimize {
r8 {
enableOptimization()
}
}
}
```

To enable both:

=== "Kotlin"

```kotlin
repositories {
google()
}

tasks.shadowJar {
minimize {
r8 {
enableObfuscation()
enableOptimization()
}
}
}
```

=== "Groovy"

```groovy
repositories {
google()
}

tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
minimize {
r8 {
enableObfuscation()
enableOptimization()
}
}
}
```

[ShadowJar.dependencies]: ../../api/shadow/com.github.jengelman.gradle.plugins.shadow.tasks/-shadow-jar/dependencies.html
Loading