Skip to content
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

Shadow configuration does not work as documented #722

Open
vchekan opened this issue Nov 3, 2021 · 0 comments
Open

Shadow configuration does not work as documented #722

vchekan opened this issue Nov 3, 2021 · 0 comments

Comments

@vchekan
Copy link

vchekan commented Nov 3, 2021

Please check the User Guide before submitting "how do I do 'x'?" questions!

Shadow Version

7.0.0

Gradle Version

7.2

Expected Behavior

When a dependency is declared with shadow configuration, it should be accessible at runtime.

Actual Behavior

When dependency is included with shadow configuration it is not accessible at runtime.

Gradle Build Script(s)

shadow(libs.bundles.spark.batch.compileonly)

Content of Shadow JAR (jar tf <jar file> - post link to GIST if too long)

Jar file is generated correctly, i.e. without dependency declared in shadow configuration.

Explanation

There is fairly typical situation when we need to develop a "plugin" artifact, for example Storm or Spark application. When deploying, the artifact should NOT include "provided" libraries, such as "org.apache.spark:spark-core" but in order to be able to debug application locally, it must be included in runtimeClasspath configuration.

According to the documentation,

There may be situations where the desire is to not bundle select dependencies into the shadowed JAR file but they are still required for runtime execution. n these scenarios, Shadow creates a shadow configuration...

So it sounds like exact solution to the problem described. Yet observation shows that dependency declared with shadow will be excluded from jar (correct), but will not be included into runtime classpath, in contradiction to what documentation says.

Looking at the implementation confirms the observation: shadow configuration is declared as contributing to compileClasspath, which makes it analogs to compileOnly configuration. And it does not provide dependencies to runtimeClasspath configuration. So, the code will compile but will fail to run when debugging locally.

Shadow's configuration is initialized from runtimeClasspath which makes it fundamentally impossible to have different dependencies set for runtime and jar artifact.
image

I have solved this problem with making shadow contributing dependencies to runtimeClasspath and introducing another configuration, uberJar which captures runtimeOnly and implementation configurations.

configurations.runtimeClasspath {
    extendsFrom(configurations.shadow.get())
}

configurations {
    // alternative "runtimeClasspath" configuration to provide to shadowJar configuration
    create("uberJar") {
        extendsFrom(configurations.runtimeOnly.get(), configurations.implementation.get())
        isCanBeResolved = true
        isCanBeConsumed = false
    }
}

tasks.shadowJar {
    configurations = listOf(project.configurations.named("uberJar").get())
}

Which can be demonstrated with diagram
image

So documentation makes incorrect statement about what shadow configuration does and either code should be fixed, or documentation should be corrected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants