GradleUp / shadow

Gradle plugin to create fat/uber JARs, apply file transforms, and relocate packages for applications and libraries. Gradle version of Maven's Shade plugin.
https://www.gradleup.com/shadow/
Apache License 2.0
3.76k stars 395 forks source link

The plugin changes constants with values similar to package names #232

Open sergeykad opened 8 years ago

sergeykad commented 8 years ago

Shadow Version 1.2.3

Gradle Version 2.14

Expected Behavior: There will be an option to control this behavior, preferably using filters

Actual Behavior: All constants are changed

For example Before Shadow: public static final String AttributePrefix = "org.mypackage"; After Shadow public static final String AttributePrefix = "shadow.mypackage";

johnrengelman commented 8 years ago

Yeah, the relocation code is ported from Maven Shade which exhibits this same problem: https://issues.apache.org/jira/browse/MSHADE-156 https://issues.apache.org/jira/browse/MSHADE-153

I'll have to think about how best to tackle this. Those tickets have been open for 3 years and they haven't come up with a better solution.

So, this might take a while for me to get something I'm happy with.

sergeykad commented 8 years ago

I see. Will not ability to exclude classes from this constants substitution solve the issue? Maybe it is not a perfect solution, but it should work in vast majority of cases.

pietrobraione commented 5 years ago

Are there updates on this issue? Is there any workaround for it?

eli-darkly commented 4 years ago

I'm having a similar issue, but it's worse because the strings in question are very clearly NOT package names - they just happen to start with something that could be a package name.

The package is "redis" (the root package of the Jedis client - it's nonstandard, but unfortunately that's what they chose) and the string is a Redis URL string, "redis://localhost:6379". When I shade the Jedis dependency using a prefix of "xxx.shaded", my string becomes "xxx/shaded/redis://localhost:6379". Surely it ought to be possible to know that that wasn't a class/package path, given the double slash.

johnrengelman commented 4 years ago

I see two ways of addressing this that I would be happy to accept PRs for. 1) change the relocation code to do an explicit match of the String against the JVM spec for package names. We’d have to be careful about perf here, perhaps we can only eval against the pattern when the value we are looking to replace is a String (an not a class declaration or package statement) 2) extend the relocation classes to also accept a set of exclude patterns which can be used to skip certain matches. (This could actually be how the first option is implemented with the default set configured to have patterns that match the JVM spec)

eli-darkly commented 4 years ago

I think 2 sounds good— someone's inevitably going to have some strings in their code that will look like valid class names but aren't (the original reporter of this issue had some).

martinbonnin commented 3 years ago

That would be super helpful. We're doing a Gradle plugin that generates code so it contains a lot of Strings that look exactly like package names... Because well, they actually are package names! And renaming them will break at runtime. For our use cases, I would actually prefer to have a set of include patterns than excludes since there is very little use of reflection.

Ultimately, something like GraalVM native image reflection support would be nice albeit considerably more work

mahmoudyusuf94 commented 3 years ago

I am facing a similar problem: in my build.gradle I have the following:

relocate 'io.netty','thirdparty.io.netty'

I found string literals affected by this shading which caused some runtime errors with the netty dependency.

The following string literal is defined in the original dependency: String staticLibName = "netty_tcnative"

In the shaded jar, this string literal is changed to: String staticLibName = "thirdparty.netty_tcnative";

Is there any way I can prevent this behavior of changing the string literals?

eli-darkly commented 3 years ago

Based on previous responses, it sounds like a workaround won't be implemented until someone contributes a PR.

martinbonnin commented 1 year ago

@johnrengelman can you give more details where that was fixed?

EliteMasterEric commented 1 year ago

I am still experiencing this bug with my project, which uses Gradle 7.5.1 and Shadow 7.1.2.

capitaorev commented 6 months ago

Hi folks,

Joining the party late :)

I'm having a similar/same issue trying to relocate google-cloud-logging with a config like this:

plugins {
    id 'com.github.johnrengelman.shadow' version '7.1.2'
}

dependencies {
    implementation("com.google.cloud:google-cloud-logging:${googleCloudLoggingVersion}")
}

def shadedPrefix = 'com.mycompany.common.internal.shade.gcloud'
shadowJar {
    relocate 'com', "${shadedPrefix}.com"
    relocate 'io', "${shadedPrefix}.io"
    relocate 'javax.annotation', "${shadedPrefix}.javax.annotation"
    relocate 'org', "${shadedPrefix}.org"

    archiveClassifier.set('')
    mergeServiceFiles()
}

With this I ended up having strings like /computeMetadata/v1/instance/service-accounts/default/token being renamed to /com/mycompany/common/internal/shade/gcloud/computeMetadata/v1/instance/service-accounts/default/token, which breaks GCE authentication.

I believe this is the exact same problem (maybe more like this), so just adding more info for future reference.

weijiii commented 1 month ago

Having a similar issue here

public static final String ITEMS_KEY = "items";

is interpreted as

public static final String ITEMS_KEY = "xxx.shaded.items";

I am curious though when is this going to be triggered; I tried excluding the package containing this static field but it did not work

relocate ('xxx', 'xxx.shaded') {
  exclude 'xxx.yyy'
}