Skip to content
Closed
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
2 changes: 2 additions & 0 deletions api/shadow.api
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ public abstract interface class com/github/jengelman/gradle/plugins/shadow/tasks
public abstract fun getConfigurationFile ()Lorg/gradle/api/file/RegularFileProperty;
public fun getKeepRuleFiles ()Lorg/gradle/api/file/ConfigurableFileCollection;
public fun getKeepRules ()Lorg/gradle/api/provider/ListProperty;
public abstract fun getMaxHeapSize ()Lorg/gradle/api/provider/Property;
public abstract fun getProguardRuleFiles ()Lorg/gradle/api/file/ConfigurableFileCollection;
public abstract fun getProguardRules ()Lorg/gradle/api/provider/ListProperty;
}
Expand Down Expand Up @@ -279,6 +280,7 @@ public abstract class com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar
public fun getSourceSetsClassesDirs ()Lorg/gradle/api/file/ConfigurableFileCollection;
public fun getToMinimize ()Lorg/gradle/api/file/ConfigurableFileCollection;
public fun getTransformers ()Lorg/gradle/api/provider/SetProperty;
protected abstract fun getWorkerExecutor ()Lorg/gradle/workers/WorkerExecutor;
public fun mergeGroovyExtensionModules ()V
public final fun mergeServiceFiles ()V
public fun mergeServiceFiles (Ljava/lang/String;)V
Expand Down
2 changes: 2 additions & 0 deletions docs/changes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
### Added

- Allow configuring the final R8 configuration file with `R8Spec.configurationFile`. ([#2133](https://github.com/GradleUp/shadow/pull/2133))
- Allow configuring the R8 worker maximum heap size with `R8Spec.maxHeapSize`. ([#2172](https://github.com/GradleUp/shadow/pull/2172))

### Changed

- Bump min Gradle requirement to 9.4.0. ([#2114](https://github.com/GradleUp/shadow/pull/2114))
- Remove runtime dependencies on Commons Codec and Commons IO by using JDK APIs. ([#2136](https://github.com/GradleUp/shadow/pull/2136))
- **POTENTIALLY BREAKING:** Remove `Serializable` from `DependencyFilter`. ([#2144](https://github.com/GradleUp/shadow/pull/2144))
- Bump default R8 from `9.1.31` to `9.2.23`. ([#2157](https://github.com/GradleUp/shadow/pull/2157))
- Use Gradle Worker API for R8 minimization. ([#2172](https://github.com/GradleUp/shadow/pull/2172))
- Allow repackaging Service file classes with R8. ([#2174](https://github.com/GradleUp/shadow/pull/2174))

### Deprecated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,49 @@ class MinimizeTest : BasePluginTest() {
assertThat(result.output).contains("R8 launcher JDK ${JavaVersion.current().majorVersion}")
}

@Test
fun minimizeWithR8UsesGradleDaemonMaxHeapSize() {
writeR8Repository()
writeR8ClientAndServerModules(
serverShadowBlock =
"""
|minimize {
| r8 {}
|}
"""
.trimMargin()
)
path("gradle.properties").writeText("org.gradle.jvmargs=-Xmx768m")

val result = runWithSuccess(serverShadowJarPath, infoArgument)

val workerCommand =
result.output.lineSequence().single { "Starting process 'Gradle Worker Daemon" in it }
assertThat(workerCommand).contains("-Xmx${768L * 1024 * 1024}")
}

@Test
fun minimizeWithR8CanConfigureMaxHeapSize() {
writeR8Repository()
writeR8ClientAndServerModules(
serverShadowBlock =
"""
|minimize {
| r8 {
| maxHeapSize.set("640m")
| }
|}
"""
.trimMargin()
)

val result = runWithSuccess(serverShadowJarPath, infoArgument)

val workerCommand =
result.output.lineSequence().single { "Starting process 'Gradle Worker Daemon" in it }
assertThat(workerCommand).contains("-Xmx640m")
}

private fun writeApiLibAndImplModules() {
settingsScript.appendText(
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ constructor(

@get:Input val optimizationEnabled: Property<Boolean> = objectFactory.property(false)

override val maxHeapSize: Property<String> =
objectFactory.property(Runtime.getRuntime().maxMemory().toString())

override val args: ListProperty<String> = objectFactory.listProperty(defaultArgs)

override val proguardRules: ListProperty<String> = objectFactory.listProperty()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ import org.apache.tools.zip.ZipOutputStream
import org.gradle.api.GradleException
import org.gradle.api.file.FileCollection
import org.gradle.api.logging.Logger
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Provider
import org.gradle.jvm.toolchain.JavaLauncher
import org.gradle.process.ExecOperations
import org.gradle.workers.WorkAction
import org.gradle.workers.WorkParameters
import org.gradle.workers.WorkerExecutor

/**
* Runs R8 as a final-archive shrinker.
Expand All @@ -36,7 +39,7 @@ import org.gradle.process.ExecOperations
internal fun minimizeWithR8(
inputJar: File,
temporaryDir: File,
execOperations: ExecOperations,
workerExecutor: WorkerExecutor,
logger: Logger,
r8Classpath: FileCollection,
r8Spec: DefaultR8Spec,
Expand Down Expand Up @@ -95,14 +98,15 @@ internal fun minimizeWithR8(
}

logger.info("Running R8 to minimize {}.", inputJar)
execOperations.javaexec {
it.classpath = r8Classpath
it.mainClass.set(R8_MAIN_CLASS)
val workQueue = workerExecutor.processIsolation {
it.classpath.from(r8Classpath)
it.forkOptions.maxHeapSize = r8Spec.maxHeapSize.get()
if (launcher != null) {
it.executable = launcher.executablePath.asFile.absolutePath
it.forkOptions.executable = launcher.executablePath.asFile.absolutePath
}
it.args(arguments)
}
workQueue.submit(R8WorkAction::class.java) { it.r8Args.set(arguments) }
workQueue.await()

normalizeJar(
inputJar = r8Output,
Expand Down Expand Up @@ -339,6 +343,19 @@ internal fun normalizeJar(
}
}

internal abstract class R8WorkAction : WorkAction<R8WorkAction.Parameters> {
override fun execute() {
val args = parameters.r8Args.get().toTypedArray()
val r8Class = Class.forName(R8_MAIN_CLASS, true, javaClass.classLoader)
val mainMethod = r8Class.getMethod("main", Array<String>::class.java)
mainMethod(null, args)
Comment thread
Goooler marked this conversation as resolved.
}

interface Parameters : WorkParameters {
val r8Args: ListProperty<String>
}
}

private const val R8_MAIN_CLASS = "com.android.tools.r8.R8"
private const val SERVICES_PATH = "META-INF/services/"
// Keep only ordinary dot-separated Java type names in generated rules. This filters out blank
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,26 @@ import com.github.jengelman.gradle.plugins.shadow.ShadowDsl
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.PathSensitive
import org.gradle.api.tasks.PathSensitivity

/** Minimal R8 configuration for [ShadowJar.minimize]. */
@ShadowDsl
public interface R8Spec {
/**
* The maximum heap size for the R8 worker process.
*
* Defaults to the effective maximum heap size of the Gradle daemon. The value uses JVM memory
* notation, such as `2g` or `512m`.
*/
@get:Internal // Doesn't affect the output.
public val maxHeapSize: Property<String>

/**
* Additional R8 command line arguments.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ import org.gradle.api.tasks.options.Option
import org.gradle.jvm.toolchain.JavaLauncher
import org.gradle.language.base.plugins.LifecycleBasePlugin
import org.gradle.process.ExecOperations
import org.gradle.workers.WorkerExecutor

@ShadowDsl
@CacheableTask
Expand Down Expand Up @@ -330,10 +331,14 @@ public abstract class ShadowJar : Jar() {
*/
override fun getDuplicatesStrategy(): DuplicatesStrategy = super.getDuplicatesStrategy()

@get:Inject protected abstract val execOperations: ExecOperations
@Deprecated("Replace the logic with `workerExecutor`. This will be removed in Shadow 10.")
@get:Inject
protected abstract val execOperations: ExecOperations

@get:Inject protected abstract val archiveOperations: ArchiveOperations

@get:Inject protected abstract val workerExecutor: WorkerExecutor

/** Enable minimization and execute the [action] with the [MinimizeSpec] for minimize. */
@JvmOverloads
public open fun minimize(action: Action<in MinimizeSpec> = Action {}) {
Expand Down Expand Up @@ -703,7 +708,7 @@ public abstract class ShadowJar : Jar() {
minimizeWithR8(
inputJar = archiveFile.get().asFile,
temporaryDir = temporaryDir,
execOperations = execOperations,
workerExecutor = workerExecutor,
logger = logger,
r8Classpath = r8Classpath,
r8Spec = defaultMinimizeSpec.r8Spec,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class MinimizeSpecsTest {
assertThat(args.get()).containsExactly(DefaultR8Spec.NO_MINIFICATION_ARG)
assertThat(obfuscationEnabled.get()).isFalse()
assertThat(optimizationEnabled.get()).isFalse()
assertThat(maxHeapSize.get()).isEqualTo(Runtime.getRuntime().maxMemory().toString())
assertThat(proguardRules.get()).isEmpty()
assertThat(proguardRuleFiles.files).isEmpty()
assertThat(configurationFile.get().asFile)
Expand Down