Document package relocation using R8 - #2173
Conversation
7ecb238 to
3f77569
Compare
There was a problem hiding this comment.
Pull request overview
This PR adds user-facing documentation and functional test coverage for using R8 repackaging (-repackageclasses) as an alternative approach to package relocation, and centralizes shared functional-test helpers for R8 setup.
Changes:
- Document “Relocating with R8”, including configuration examples and a comparison with Shadow’s built-in
relocate. - Add functional tests covering R8 repackaging behavior and its interaction with service-file merging.
- Refactor duplicated
writeR8Repository()helper intoBasePluginTestand add a bytecode helper for generating minimal.classentries.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt | Adds a functional test for mergeServiceFiles + R8 repackaging. |
| src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt | Adds a functional test asserting output structure when using R8 repackaging. |
| src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/MinimizeTest.kt | Removes duplicated writeR8Repository() helper (moved to base). |
| src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/CachingTest.kt | Removes duplicated writeR8Repository() helper (moved to base). |
| src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/BasePluginTest.kt | Centralizes writeR8Repository() and adds createEmptyClassBytes() for tests. |
| docs/configuration/relocation/README.md | Adds documentation section for using R8 repackaging for relocation and compares approaches. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| assertThat(outputShadowedJar).useAll { | ||
| containsOnly( | ||
| "bar/", | ||
| "bar/BarDriver.class", | ||
| "com/", | ||
| "com/example/", | ||
| "com/example/Driver.class", | ||
| "foo/", | ||
| "foo/FooDriver.class", | ||
| "META-INF/services/", | ||
| "META-INF/services/com.example.Driver", | ||
| *manifestEntries, | ||
| ) | ||
| getContent("META-INF/services/com.example.Driver") | ||
| .isEqualTo( | ||
| """ | ||
| |foo.FooDriver | ||
| |bar.BarDriver | ||
| |""" | ||
| .trimMargin() | ||
| ) | ||
| } |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.
Suppressed comments (2)
src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt:131
- The test name suggests R8 relocation is being validated, but the assertions only check non-repackaged class paths and the original service descriptor names/content. Given Shadow generates
-keep class ...rules forMETA-INF/services/**entries (which keeps names), this test is really validating that service files are still merged/kept when R8 is enabled, not that relocation happens. Renaming the test to reflect its actual expectation would avoid confusion and false assumptions about relocation behavior.
@Test
fun serviceResourceTransformerWithR8Relocation() {
val one = buildJarOne {
docs/configuration/relocation/README.md:258
- This section documents R8 repackaging, but it doesn’t mention that Shadow’s R8 integration generates
-keep class ...rules for service interfaces/providers listed inMETA-INF/services/**(seeserviceProguardRulesinR8Minimizer.kt). Those keep rules preserve class names, which can prevent-repackageclassesfrom relocating service types unless users also adapt the service descriptor resources. Adding a short note here would set correct expectations for ServiceLoader-based dependencies.
R8 performs whole-program analysis during its minimization pass to safely relocate classes while respecting Java
access visibility constraints (such as package-private and `protected` members). Repackaging works with
`-repackageclasses` alone. Adding [-allowaccessmodification][allowaccessmodification] is optional, but allows R8 to
relocate additional classes by widening package-private or protected access restrictions to `public`. For more details
on R8 rules, see the [Global options for additional optimization][android-r8-global-options] and ProGuard manual for
[-repackageclasses][repackageclasses] and [-allowaccessmodification][allowaccessmodification].
a1b0855 to
9ecfe03
Compare
Refs: - https://developer.android.com/topic/performance/app-optimization/global-options#global-options - https://www.guardsquare.com/manual/configuration/usage#repackageclasses - https://www.guardsquare.com/manual/configuration/usage#allowaccessmodification - https://www.guardsquare.com/manual/configuration/usage#keeppackagenames
9ecfe03 to
bf71eba
Compare
Refs: