Skip to content

Support skipping string constant remapping #1401

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Jul 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
7ab3258
Add `isSkipStringLiteral` for `Relocator`
Goooler Apr 16, 2025
d159668
Check `mapLiterals` in `RelocatorRemapper`
Goooler Apr 16, 2025
efccd57
Make isSkipStringLiteral configurable
Goooler Apr 16, 2025
233e9e0
Test `canDisableRelocateStringConstants`
Goooler Apr 16, 2025
f3ae60f
Merge remote-tracking branch 'origin/main' into g/22050416/fix-issue-232
Goooler Apr 17, 2025
de55c7b
Fix `canDisableRelocateStringConstants`
Goooler Apr 17, 2025
3388470
Dump API
Goooler Apr 17, 2025
9116b7f
Merge remote-tracking branch 'origin/main' into g/22050416/fix-issue-232
Goooler Apr 23, 2025
4dc3d9b
Update changelog
Goooler Apr 23, 2025
ceba4c5
Merge remote-tracking branch 'origin/main' into g/22050416/fix-issue-232
Goooler Apr 30, 2025
0d462ac
Update changelog
Goooler Apr 30, 2025
81796bf
Merge remote-tracking branch 'origin/main' into g/22050416/fix-issue-232
Goooler Jul 14, 2025
79e6247
Apply suggestion from @Copilot
Goooler Jul 14, 2025
dacfba8
Merge branch 'main' into g/22050416/fix-issue-232
Goooler Jul 23, 2025
78e9fba
Cleanups
Goooler Jul 23, 2025
5530f3e
Mark `skipStringLiteral` as `Input`
Goooler Jul 23, 2025
87a5b3d
Rename `skipStringLiteral` to `skipStringConstants`
Goooler Jul 23, 2025
7953783
Update doc
Goooler Jul 23, 2025
d5060b1
Update src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/int…
Goooler Jul 23, 2025
95ea038
Update docs/configuration/relocation/README.md
Goooler Jul 23, 2025
1b09b15
Revert "Update src/main/kotlin/com/github/jengelman/gradle/plugins/sh…
Goooler Jul 23, 2025
72368ad
Update changelog
Goooler Jul 23, 2025
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
6 changes: 5 additions & 1 deletion api/shadow.api
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ public abstract interface class com/github/jengelman/gradle/plugins/shadow/reloc
public abstract fun applyToSourceContent (Ljava/lang/String;)Ljava/lang/String;
public abstract fun canRelocateClass (Ljava/lang/String;)Z
public abstract fun canRelocatePath (Ljava/lang/String;)Z
public fun getSkipStringConstants ()Z
public abstract fun relocateClass (Lcom/github/jengelman/gradle/plugins/shadow/relocation/RelocateClassContext;)Ljava/lang/String;
public abstract fun relocatePath (Lcom/github/jengelman/gradle/plugins/shadow/relocation/RelocatePathContext;)Ljava/lang/String;
}
Expand All @@ -127,18 +128,21 @@ public class com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocat
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Ljava/util/List;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Ljava/util/List;Z)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Ljava/util/List;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Ljava/util/List;ZZ)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Ljava/util/List;ZZILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun applyToSourceContent (Ljava/lang/String;)Ljava/lang/String;
public fun canRelocateClass (Ljava/lang/String;)Z
public fun canRelocatePath (Ljava/lang/String;)Z
public fun equals (Ljava/lang/Object;)Z
public fun exclude (Ljava/lang/String;)V
public final fun getExcludes ()Ljava/util/Set;
public final fun getIncludes ()Ljava/util/Set;
public fun getSkipStringConstants ()Z
public fun hashCode ()I
public fun include (Ljava/lang/String;)V
public fun relocateClass (Lcom/github/jengelman/gradle/plugins/shadow/relocation/RelocateClassContext;)Ljava/lang/String;
public fun relocatePath (Lcom/github/jengelman/gradle/plugins/shadow/relocation/RelocatePathContext;)Ljava/lang/String;
public fun setSkipStringConstants (Z)V
}

public abstract interface class com/github/jengelman/gradle/plugins/shadow/tasks/DependencyFilter : java/io/Serializable {
Expand Down
1 change: 1 addition & 0 deletions docs/changes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

**Added**

- Support skipping string constant remapping. ([#1401](https://github.com/GradleUp/shadow/pull/1401))
- Let `assemble` depend on `shadowJar`. ([#1524](https://github.com/GradleUp/shadow/pull/1524))
- Fail build when inputting AAR files or using Shadow with AGP. ([#1530](https://github.com/GradleUp/shadow/pull/1530))

Expand Down
57 changes: 57 additions & 0 deletions docs/configuration/relocation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,63 @@ expression in `%regex[]` before passing it to `include`/`exclude`.
}
```

## Skipping Relocation for String Constants

If there is a class like:

```java
package foo;

public class Bar {
public static void main(String[] args) {
System.out.println("foo.Bar");
}
}
```

in your project, and you configure the relocation like:

=== "Kotlin"

```kotlin
tasks.shadowJar {
relocate("foo", "my.foo")
}
```

=== "Groovy"

```groovy
tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
relocate 'foo', 'my.foo'
}
```

the string constant `"foo.Bar"` will be relocated to `"my.foo.Bar"` by default. This may not be what you want, you can
skip relocating string constants in the classes like:

=== "Kotlin"

```kotlin
tasks.shadowJar {
relocate("foo", "my.foo") {
// Optionally, defaults to `false`.
skipStringConstants = true
}
}
```

=== "Groovy"

```groovy
tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
relocate('foo', 'my.foo') {
// Optionally, defaults to `false`.
skipStringConstants = true
}
}
```

## Automatically Relocating Dependencies

Shadow is shipped with a task that can be used to automatically configure all packages from all dependencies to be
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -585,16 +585,7 @@ class RelocationTest : BasePluginTest() {

@Test
fun relocateStringConstantsByDefault() {
writeClass {
"""
package my;
public class Main {
public static void main(String[] args) {
System.out.println("junit.framework.Test");
}
}
""".trimIndent()
}
writeClassWithStringRef()
projectScriptPath.appendText(
"""
$shadowJar {
Expand All @@ -614,6 +605,46 @@ class RelocationTest : BasePluginTest() {
)
}

@Issue(
"https://github.com/GradleUp/shadow/issues/232",
)
@ParameterizedTest
@ValueSource(booleans = [false, true])
fun canDisableRelocateStringConstants(skipStringConstants: Boolean) {
writeClassWithStringRef()
projectScriptPath.appendText(
"""
$shadowJar {
manifest {
attributes '$mainClassAttributeKey': 'my.Main'
}
relocate('junit', 'foo.junit') {
skipStringConstants = $skipStringConstants
}
}
""".trimIndent(),
)

run(shadowJarTask)
val result = runProcess("java", "-jar", outputShadowJar.use { it.toString() })

val expected = if (skipStringConstants) "junit.framework.Test" else "foo.junit.framework.Test"
assertThat(result).contains(expected)
}

private fun writeClassWithStringRef() {
writeClass {
"""
package my;
public class Main {
public static void main(String[] args) {
System.out.println("junit.framework.Test");
}
}
""".trimIndent()
}
}

private companion object {
@JvmStatic
fun prefixProvider() = listOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,20 @@ internal class RelocatorRemapper(

override fun mapValue(value: Any): Any {
return if (value is String) {
map(value)
mapName(value, mapLiterals = true)
} else {
super.mapValue(value)
}
}

override fun map(name: String): String {
override fun map(internalName: String): String = mapName(internalName)

fun mapPath(path: String): String {
val dotIndex = path.indexOf('.')
return if (dotIndex == -1) path else map(path.take(dotIndex))
}

private fun mapName(name: String, mapLiterals: Boolean = false): String {
var newName = name
var prefix = ""
var suffix = ""
Expand All @@ -38,7 +45,9 @@ internal class RelocatorRemapper(
}

for (relocator in relocators) {
if (relocator.canRelocateClass(newName)) {
if (mapLiterals && relocator.skipStringConstants) {
return name
} else if (relocator.canRelocateClass(newName)) {
return prefix + relocator.relocateClass(newName) + suffix
} else if (relocator.canRelocatePath(newName)) {
return prefix + relocator.relocatePath(newName) + suffix
Expand All @@ -47,8 +56,4 @@ internal class RelocatorRemapper(

return name
}

fun mapPath(path: String): String {
return map(path.substringBefore('.'))
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.github.jengelman.gradle.plugins.shadow.relocation

import com.github.jengelman.gradle.plugins.shadow.transformers.CacheableTransformer
import org.gradle.api.tasks.Input

/**
* Modified from [org.apache.maven.plugins.shade.relocation.Relocator.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/relocation/Relocator.java).
Expand All @@ -19,6 +20,14 @@ public interface Relocator {

public fun applyToSourceContent(sourceContent: String): String

/**
* Indicates whether this relocator should skip relocating string constants.
*
* Defaults to `false`.
*/
@get:Input
public val skipStringConstants: Boolean get() = false

public companion object {
public val ROLE: String = Relocator::class.java.name
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public open class SimpleRelocator @JvmOverloads constructor(
includes: List<String>? = null,
excludes: List<String>? = null,
private val rawString: Boolean = false,
@get:Input override var skipStringConstants: Boolean = false,
) : Relocator {
private val pattern: String
private val pathPattern: String
Expand Down Expand Up @@ -137,6 +138,7 @@ public open class SimpleRelocator @JvmOverloads constructor(
if (this === other) return true
if (other !is SimpleRelocator) return false
return rawString == other.rawString &&
skipStringConstants == other.skipStringConstants &&
pattern == other.pattern &&
pathPattern == other.pathPattern &&
shadedPattern == other.shadedPattern &&
Expand All @@ -149,6 +151,7 @@ public open class SimpleRelocator @JvmOverloads constructor(

override fun hashCode(): Int {
var result = rawString.hashCode()
result = 31 * result + skipStringConstants.hashCode()
result = 31 * result + pattern.hashCode()
result = 31 * result + pathPattern.hashCode()
result = 31 * result + shadedPattern.hashCode()
Expand Down