Shadow Gradle Plugin

repository·main·Indexed 26 days ago

https://github.com/gradleup/shadow

A Gradle plugin used to create fat or uber JARs by bundling all dependencies into a single archive. It provides support for package relocation to avoid classpath conflicts, JAR shrinking via R8, and integration with the Gradle application plugin to create standalone distributions (Zip and Tar) with start scripts. It also supports integration with the Android Fused Library Plugin.

Tokens
19.1K
Snippets
76
Records
113
Agent score
88%

What's inside gradleup-shadow

  1. Understand ResourceTransformer processing order

    main

    Shadow uses the ResourceTransformer interface to customize JAR generation. A transformer is invoked for each entry before it is written to the final output JAR.

    Processing Order Guarantee:

    1. Project files first: Files within your project are processed before any dependency files.
    2. Dependency files second: Files from runtime dependencies or added via ShadowJar.from are processed after project files.

    This order ensures you can preserve project-specific values when merging data from dependencies.

  2. Default ShadowJar behavior and configuration

    main

    When the java, org.jetbrains.kotlin.jvm, or groovy plugins are applied, Shadow automatically configures the following:

    • Adds a ShadowJar task.
    • Adds a shadow configuration, variant, and component to the project.
    • Configures ShadowJar to include all sources from the main sourceSet.
    • Configures ShadowJar to bundle all dependencies from the runtimeClasspath configuration.
    • Sets the ShadowJar task classifier to 'all'.
    • Generates a Manifest that inherits standard Jar configuration and adds a Class-Path attribute containing all dependencies from the shadow configuration.
    • Automatically excludes signature and index files: META-INF/INDEX.LIST, META-INF/*.SF, META-INF/*.DSA, META-INF/*.RSA, META-INF/versions/**/module-info.class, and module-info.class.
    • Registers the shadow component for use with maven-publish.
  3. Configure package relocation for Gradle plugins

    main
    If you are developing a Gradle plugin and want to automatically configure package relocation to avoid classpath conflicts, use the ConfigureShadowRelocation task. Note that the legacy plugin ID com.github.johnrengelman.plugin-shadow has been removed; you must now declare your own ConfigureShadowRelocation task to achieve this functionality.
  4. Configure the Shadow JAR manifest

    main

    The shadowJar task inherits the manifest from the standard jar task by default. You can define attributes in the jar task, or merge manifests from other Jar tasks using manifest.from.

    // Inheriting from the standard jar task
    tasks.jar {
      manifest {
        attributes["Main-Class"] = "my.Main"
      }
    }
    
    // Merging manifest from another Jar task
    val testJar = tasks.register<Jar>("testJar") {
      manifest {
        attributes["Description"] = "This is an application JAR"
      }
    }
    
    tasks.shadowJar {
      manifest.from(testJar.get().manifest)
    }
  5. Bundle and relocate dependencies for libraries

    main
    Library authors can use Shadow to bundle dependencies and use relocation to avoid classpath conflicts. By relocating package names for dependencies, you ensure that your library's dependencies do not conflict with the same dependencies used by downstream applications, preventing binary incompatibility issues.
  6. Migrate to the new Shadow plugin ID

    main

    The Shadow plugin has transitioned from the old ID com.github.johnrengelman.shadow to the new ID com.gradleup.shadow. To ensure you receive the latest bug fixes and improvements, you should switch to the new plugin ID and update to the latest version.

    Note that version 8.0.0+ still supports the old ID, but versions 8.3.0+ and above use the new com.gradleup.shadow ID.

  7. Depend on a Shadow JAR from another project

    main

    In a multi-project build, if one project applies the Shadow plugin and another project needs to use the resulting shadowed JAR, you must explicitly depend on the shadow configuration of that project using Gradle's dependency mechanism.

    // Kotlin
    dependencies {
      implementation(project(path = ":api", configuration = "shadow"))
    }
    // Groovy
    dependencies {
      implementation project(path: ':api', configuration: 'shadow')
    }
  8. Publish custom ShadowJar task outputs

    main

    You can publish the output of a custom ShadowJar task by passing the task instance to the MavenPublication.artifact() method within your publishing block. This is useful when you want to create a specific shadowed JAR (e.g., for tests) that is distinct from the main project artifact.

    plugins {
      java
      `maven-publish`
      id("com.gradleup.shadow")
    }
    
    val testShadowJar = tasks.register<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>("testShadowJar") {
      description = "Create a combined JAR of project and test dependencies"
      archiveClassifier = "tests"
      from(sourceSets.test.map { it.output })
      configurations = project.configurations.testRuntimeClasspath.map { listOf(it) }
    }
    
    dependencies {
      testImplementation("junit:junit:3.8.2")
    }
    
    publishing {
      publications {
        create<MavenPublication>("shadow") {
          artifact(testShadowJar)
        }
      }
      repositories {
        maven("https://repo.myorg.com")
      }
    }
  9. Relocate project resources only

    main

    To relocate only the resources of the project while excluding all dependencies from the relocation process, set the configurations property to an empty list.

    tasks.shadowJar {
      // Empty configurations list will exclude all dependencies.
      configurations = emptyList()
      relocate("com.example", "shadow.com.example")
    }
  10. Configure Kotlin standard library shadowing

    main

    By default, Kotlin plugins add the standard library (stdlib) via implementation, and Shadow will automatically bundle it into shadowed JARs.

    If you want to prevent the standard library from being bundled, add this property to your gradle.properties:

    kotlin.stdlib.default.dependency=false

    If you disable the default dependency but still need the standard library for compilation, add it as compileOnly to avoid shadowing it:

    dependencies {
      compileOnly("org.jetbrains.kotlin:kotlin-stdlib")
    }
  11. Publish Shadowed Gradle Plugins

    main

    If you are developing a Gradle plugin using Shadow and the com.gradle.plugin-publish plugin, Shadow automatically configures the ShadowJar task output as the consumable artifact. To ensure the plugin is published correctly, you must set the archiveClassifier of the shadowJar task to an empty string.

    plugins {
      id("com.gradle.plugin-publish") version "latest"
      id("com.gradleup.shadow")
    }
    
    tasks.shadowJar {
      archiveClassifier = ""
    }