Gr8 is Gradle + R8.

Related tags

Gradle plugin gr8
Overview

Gr8

Gr8 is Gradle + R8.

Gr8 makes it easy to shadow, shrink, and minimize your jars.

Motivation

Gradle has a very powerful plugin system. Unfortunately, Gradle handling of classpath/Classloaders for plugins has some serious limitations. For an example:

By shadowing and relocating the plugin dependencies, it is possible to ship a plugin and all its dependencies without having to worry about what Gradle is going to put on the classpath.

As a nice bonus, it makes plugins standalone so consumers of your plugin don't need to declare additional repositories. The gr8 plugin for an example, uses R8 from the Google repo although it makes it available directly from the preconfigured Gradle plugin portal.

Usage

To make a shadowed Gradle plugin:

plugins {
  id("org.jetbrains.kotlin.jvm").version("$kotlinVersion")
  id("java-gradle-plugin")
  id("com.gradleup.gr8").version("$gr8Version")
}

// Configuration dependencies that will be shadowed
val shadeConfiguration = configurations.create("shade")

dependencies {
  // Using a redistributed version of Gradle instead of `gradleApi` provides more flexibility
  // See https://github.com/gradle/gradle/issues/1835
  compileOnly("dev.gradleplugins:gradle-api:7.1.1")

  // Also set kotlin.stdlib.default.dependency=false in gradle.properties to avoid the 
  // plugin to add it to the "api" configuration
  add("shade", "org.jetbrains.kotlin:kotlin-stdlib")
  add("shade", "com.squareup.okhttp3:okhttp:4.9.0")
}

gr8 {
  val shadowedJar = create("gr8") {
    proguardFile("rules.pro")
    configuration("shade")
  }
  // Replace the regular jar with the shadowed one in the publication
  replaceOutgoingJar(shadowedJar)

  // Make the shadowed dependencies available during compilation/tests
  configurations.named("compileOnly").configure {
    extendsFrom(shadeConfiguration)
  }
  configurations.named("testImplementation").configure {
    extendsFrom(shadeConfiguration)
  }
}

Then customize your proguard rules. The below is the bare minimum. If you're using reflection, you might need more rules

# The Gradle API jar isn't added to the classpath, ignore the missing symbols
-ignorewarnings
# Allow to make some classes public so that we can repackage them without breaking package-private members
-allowaccessmodification

# Keep kotlin metadata so that the Kotlin compiler knows about top level functions and other things
-keep class kotlin.Metadata { *; }

# We need to keep type arguments (Signature) for Gradle to be able to instantiate abstract models like `Property`
-keepattributes Signature,Exceptions,*Annotation*,InnerClasses,PermittedSubclasses,EnclosingMethod,Deprecated,SourceFile,LineNumberTable

# Keep your public API so that it's callable from scripts
-keep class com.example.** { *; }

-repackageclasses com.example.relocated

FAQ

Could I use the Shadow plugin instead?

The Gradle Shadow Plugin has been helping plugin authors for years and is a very stable solution. Unfortunately, it doesn't allow very granular configuration and might relocate constant strings that shouldn't be. In practice, any plugin that tries to read the "kotlin" extension is subject to having its behaviour changed:

project.extensions.getByName("kotlin")
}

will be transformed to:

project.extensions.getByName("com.relocated.kotlin")

For plugins that generate source code and contain a lot of package names, this might be even more unpredictable and require weird workarounds.

By using R8 and proguard rules, Gr8 makes relocation more predictable and configurable.

Could I use the Gradle Worker API instead?

Yes, the Gradle Worker API ensures proper plugin isolation. It only works for task actions and requires some setup so shadowing/relocating is a more universal solution.

Are there any drawbacks?

Yes. Because every plugin now relocates its own version of kotlin-stdlib, okio and other dependendancies, it means more work for the Classloaders and more Metaspace being used. There's a risk that builds will use more memory although it hasn't been a big issue so far.

You might also like...
A Gradle Plugin to determine which modules were affected by a set of files in a commit.
A Gradle Plugin to determine which modules were affected by a set of files in a commit.

A Gradle Plugin to determine which modules were affected by a set of files in a commit. One use case for this plugin is for developers who would like to only run tests in modules which have changed in a given commit.

EasyVersion is a Gradle plugin that manage your app or library version.

EasyVersion EasyVersion is a Gradle plugin that manage your app or library version. Before Downloading Create easy_version.json in your root project d

A Gradle plugin to help analyse the dependency between modules and run tasks only on modules impacted by specific set of changes.
A Gradle plugin to help analyse the dependency between modules and run tasks only on modules impacted by specific set of changes.

Change Tracker Plugin A Gradle plugin to help analyse the dependency between modules and run tasks only on modules impacted by specific set of changes

Android Gradle Plugin -- Auto Check big image and compress image in building.

McImage I will continue to update, please rest assured to use 中文文档 Android优雅的打包时自动化获取全部res资源 McImage is a Non-invasive plugin for compress all res in

Kotlin Gradle plugins for conveniently setting up Kotlin projects (JVM/MPP), publishing, Dokka, etc

Arrow Gradle config Add basic config to a Kotlin Multiplatform project In an Arrow KMP project, just add to the plugin block: plugins { kotlin("mu

Gradle plugin that generates a Swift Package Manager manifest and an XCFramework to distribute a Kotlin Multiplatform library for Apple platforms.

Multiplatform Swift Package This is a Gradle plugin for Kotlin Multiplatform projects that generates an XCFramework for your native Apple targets and

A Gradle plugin helps to proxy all the BuildConfig fields in the Android project.
A Gradle plugin helps to proxy all the BuildConfig fields in the Android project.

Readme A Gradle plugin helps to proxy all the BuildConfig fields in the Android project. Background In android BuildConfig, We might have different co

Gradle Plugin for publishing artifacts to Sonatype and Nexus

Introduction Due to Sonatype's strict validation rules, the publishing requirement must be satisfied by every artifact which wants to be published to

Gradle-i18n-plugin is meant for generating a JSON file with internationalized texts, based on a Google Sheet.
Gradle-i18n-plugin is meant for generating a JSON file with internationalized texts, based on a Google Sheet.

Gradle-i18n-plugin Gradle-i18n-plugin is meant for generating a JSON file with internationalized texts, based on a Google Sheet. The plugin assumes th

Comments
  • Add latest version to README

    Add latest version to README

    The readme has no link to the Plugin Portal page or an explicit version, which makes the $latestVersion in the usage section fairly useless. This automatically updating badge makes it easier for users to find the right version.

    opened by msfjarvis 1
  • Use R8 main

    Use R8 main

    Use R8 main as of todays ed91d27f5094710e9cee0f6a5d12a20f40ee315e. This has support for relocating without obfuscating (https://r8.googlesource.com/r8/+/81ae5c8b3ef02120cea8ac15bfc0f71aac66f72f)

    Also:

    • indent everything with 2 spaces
    • convert convention plugins to regular plugins
    opened by martinbonnin 0
  • Relocate without shrinkning

    Relocate without shrinkning

    Hi,

    I want to relocate AWS SDK for https://github.com/burrunan/gradle-s3-build-cache, and it looks like proguard is either "relocate+obfuscate" or "just keep old package names".

    What I want is to just relocate packages under com.github.burrunan.s3cache.relocated package, and I don't want all the classes to be renamed as a.class so the stacktraces are understandable.

    Do you know if there's a proguard configuration for that?

    It looks like -keep would keep the original names (which would defeat the purpose of shading as it would conflict with other dependencies), however, -flattenpackagehierarchy and -repackageclasses obfuscate the names.

    opened by vlsi 4
  • Applying to multi module project

    Applying to multi module project

    I'm trying to use this plugin for https://github.com/littlerobots/version-catalog-update-plugin. That project has a plugin module and a separate module containing some logic around the version catalogs.

    Following the README I've setup the plugin like this:

    def shadeConfiguration = configurations.create("shade")
    
    gr8 {
        def shadowedJar = create("gr8") {
            proguardFile("rules.pro")
            configuration("shade")
        }
        // Replace the regular jar with the shadowed one in the publication
        replaceOutgoingJar(shadowedJar)
    
        // Make the shadowed dependencies available during compilation/tests
        configurations.named("compileOnly").configure {
            extendsFrom(shadeConfiguration)
        }
        configurations.named("testImplementation").configure {
            extendsFrom(shadeConfiguration)
        }
    }
    
    repositories {
        gradlePluginPortal()
    }
    
    dependencies {
        shade project(":catalog")
        compileOnly("dev.gradleplugins:gradle-api:7.3.2")
        shade "org.jetbrains.kotlin:kotlin-stdlib:1.4"
        shade "com.fasterxml.jackson.dataformat:jackson-dataformat-toml:2.13.0"
        shade "com.squareup.moshi:moshi:1.12.0"
        shade "com.squareup.moshi:moshi-kotlin:1.12.0"
        testImplementation 'junit:junit:4.13.2'
        testImplementation 'com.github.ben-manes:gradle-versions-plugin:0.40.0'
        testImplementation(gradleTestKit())
        compileOnly 'com.github.ben-manes:gradle-versions-plugin:0.40.0'
    }
    

    It seems that I have to add the catalog module to the shade configuration too, otherwise none of the classes from that module appear to be added to the plugin jar. But this introduces an issue where I can no longer run my tests; classes from that project are not found in testKit tests, even when testImplementation is extending the shade config.

    I'm also not sure if I really need to redeclare the dependencies that that module uses here in the shade config. It also seems that not all of the kotlin classes are relocated in the gr8 jar so that also seems to point to more configuration / user errors 😄

    Can you point me in the right direction?

    opened by hvisser 22
Releases(0.7)
Owner
null
Gradle plugin to ease Kotlin IR plugin development and usage in multimodule gradle projects

Gradle plugin to ease Kotlin IR plugin development and usage in multimodule gradle projects. Former: kotlin-ir-plugin-adapter-gradle

null 2 Mar 8, 2022
A Gradle plugin that generates plugin.yml for Bukkit/BungeeCord/Nukkit plugins based on the Gradle project

plugin-yml is a simple Gradle plugin that generates the plugin.yml plugin description file for Bukkit plugins, bungee.yml for Bungee plugins or nukkit.yml for Nukkit plugins based on the Gradle project. Various properties are set automatically (e.g. project name, version or description) and additional properties can be added using a simple DSL.

Plexus 0 Apr 10, 2022
Gradle Plugin to enable auto-completion and symbol resolution for all Kotlin/Native platforms.

CompleteKotlin Gradle Plugin to enable auto-completion and symbol resolution for all Kotlin/Native platforms. What this plugin provides This zero-conf

Louis CAD 235 Jan 3, 2023
A Gradle plugin that improves the experience when developing Android apps, especially system tools, that use hidden APIs.

A Gradle plugin that improves the experience when developing Android apps, especially system tools, that use hidden APIs.

Rikka apps 124 Dec 31, 2022
Grazel is a Gradle plugin to automate generation of valid Bazel files for a given Android/Kotlin/Java project.

Grazel Grazel stands for Gradle to Bazel. It is a Gradle plugin that enables you to migrate Android projects to Bazel build system in an incremental a

Grab 228 Jan 2, 2023
Gradle Plugin for Continuous Integration of AppSweep App Testing.

This Gradle plugin can be used to continuously integrate app scanning using AppSweep into your Android app build process

Guardsquare 28 Nov 13, 2022
Gradle plugin which validates the licenses of your dependency graph match what you expect

Gradle plugin which validates the licenses of your dependency graph match what you expect

Cash App 502 Dec 31, 2022
Artifactory is a gradle plugin to assist in developing Minecraft mods that can target different modloaders.

Artifactory Artifactory is a gradle plugin to assist in developing Minecraft mods that can target different modloaders. Currently, Fabric and Forge ar

Zach Kozar 3 Dec 29, 2021
Gradle Plugin that allows you to decompile bytecode compiled with Jetpack Compose Compiler Plugin into Java and check it

decomposer Gradle Plugin that allows you to decompile bytecode compiled with Jetpack Compose Compiler Plugin into Java and check it How to use Run bui

Takahiro Menju 56 Nov 18, 2022
Graphfity is a Gradle Plugin which creates a dependency node diagram graph about your internal modules dependencies, specially useful if you are developing a multi-module application

Graphfity creates a dependency nodes diagram graph about your internal modules dependencies, specially useful if you are developing a multi-module app

Iván Carrasco 27 Dec 20, 2022