├── .github └── workflows │ ├── build-pull-request.yaml │ ├── publish-pages.yaml │ ├── publish-release.yaml │ └── publish-snapshot.yaml ├── .gitignore ├── .idea └── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── build-logic ├── build.gradle.kts └── settings.gradle.kts ├── build.gradle.kts ├── gr8-plugin-common ├── api │ └── gr8-plugin-common.api ├── build.gradle.kts └── src │ └── main │ └── kotlin │ └── com │ └── gradleup │ └── gr8 │ ├── DownloadR8Task.kt │ ├── FilterTransform.kt │ ├── Gr8Configurator.kt │ ├── Gr8Extension.kt │ └── Gr8Task.kt ├── gr8-plugin-external ├── api │ └── gr8-plugin-external.api ├── build.gradle.kts └── src │ └── main │ └── kotlin │ └── com │ └── gradleup │ └── gr8 │ └── Gr8Plugin.kt ├── gr8-plugin ├── api │ └── gr8-plugin.api ├── build.gradle.kts ├── rules.pro └── src │ └── main │ └── kotlin │ └── com │ └── gradleup │ └── gr8 │ └── Gr8Plugin.kt ├── gradle.properties ├── gradle ├── libs.versions.toml ├── repositories.gradle.kts └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── librarian.root.properties ├── settings.gradle.kts └── test-plugin ├── README.md ├── build.gradle.kts ├── fixtures └── test-project │ ├── build.gradle.kts │ ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle.kts ├── gradle.properties ├── gradle └── wrapper ├── gradlew ├── gradlew.bat ├── rules.pro ├── settings.gradle.kts └── src ├── main ├── kotlin │ └── com │ │ └── gradleup │ │ └── test │ │ └── TestPlugin.kt └── resources │ └── META-INF │ └── gradle-plugins │ └── com.gradleup.test.properties └── test └── kotlin └── MainTests.kt /.github/workflows/build-pull-request.yaml: -------------------------------------------------------------------------------- 1 | name: Build pull request 2 | 3 | on: pull_request 4 | 5 | jobs: 6 | build-pull-request: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 11 | - uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda #v3.4.2 12 | - run: | 13 | ./gradlew build && ./gradlew -p test-plugin build 14 | -------------------------------------------------------------------------------- /.github/workflows/publish-pages.yaml: -------------------------------------------------------------------------------- 1 | name: Publish documentation 2 | 3 | on: 4 | push: 5 | branches: ["main"] 6 | workflow_dispatch: 7 | 8 | jobs: 9 | build-docs: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 13 | with: 14 | fetch-depth: 0 15 | 16 | - uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda #v3.4.2 17 | - run: | 18 | export JAVA_HOME=$JAVA_HOME_21_X64 # Remove when ubuntu-latest updates to Java 21 19 | ./gradlew librarianStaticContent 20 | 21 | - uses: JamesIves/github-pages-deploy-action@94f3c658273cf92fb48ef99e5fbc02bd2dc642b2 #v4.6.3 22 | with: 23 | branch: gh-pages # The branch the action should deploy to. 24 | folder: build/static # The folder the action should deploy. 25 | -------------------------------------------------------------------------------- /.github/workflows/publish-release.yaml: -------------------------------------------------------------------------------- 1 | name: Publish release 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | tags: 7 | - '*' 8 | 9 | jobs: 10 | publish-release: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 15 | with: 16 | # See https://github.com/cli/cli/issues/9558 17 | ref: ${{ github.ref }} 18 | - uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda #v3.4.2 19 | - run: | 20 | ./gradlew librarianPublishToMavenCentral 21 | gh release create $GITHUB_REF_NAME --title $GITHUB_REF_NAME --verify-tag --notes-from-tag 22 | env: 23 | LIBRARIAN_SONATYPE_USERNAME: ${{ secrets.OSSRH_USER }} 24 | LIBRARIAN_SONATYPE_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} 25 | LIBRARIAN_SIGNING_PRIVATE_KEY: ${{ secrets.GPG_KEY }} 26 | LIBRARIAN_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.GPG_KEY_PASSWORD }} 27 | GH_TOKEN: ${{ github.token }} -------------------------------------------------------------------------------- /.github/workflows/publish-snapshot.yaml: -------------------------------------------------------------------------------- 1 | name: Publish snapshot 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | jobs: 7 | publish-snapshot: 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 12 | - uses: gradle/actions/setup-gradle@dbbdc275be76ac10734476cc723d82dfe7ec6eda #v3.4.2 13 | - run: | 14 | ./gradlew librarianPublishToSnapshots 15 | LIBRARIAN_VERSION_SHA1=$GITHUB_SHA ./gradlew librarianPublishToGcs 16 | env: 17 | LIBRARIAN_SONATYPE_USERNAME: ${{ secrets.OSSRH_USER }} 18 | LIBRARIAN_SONATYPE_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} 19 | LIBRARIAN_SIGNING_PRIVATE_KEY: ${{ secrets.GPG_KEY }} 20 | LIBRARIAN_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.GPG_KEY_PASSWORD }} 21 | LIBRARIAN_GOOGLE_SERVICES_JSON: ${{ secrets.GOOGLE_SERVICES_JSON }} 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Idea 2 | **/.idea/* 3 | !**/.idea/codeStyles 4 | !**/.idea/icon.png 5 | !**/.idea/runConfigurations 6 | !**/.idea/scopes 7 | *.iml 8 | 9 | .gradle 10 | build 11 | .DS_Store 12 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Next version (unreleased) 2 | 3 | # Version 0.11.1 4 | _2024-11-25_ 5 | 6 | # Version 0.11.0 7 | _2024-11-25_ 8 | 9 | 10 | ## Configurable R8 version 11 | 12 | Gr8 0.11.0 uses R8 8.5.35 by default. 13 | 14 | You can now override this version. 15 | 16 | Using the `https://storage.googleapis.com/r8-releases/raw` repository ([doc](https://r8.googlesource.com/r8)): 17 | 18 | ```kotlin 19 | repositories { 20 | maven("https://storage.googleapis.com/r8-releases/raw") 21 | } 22 | 23 | gr8 { 24 | create("default") { 25 | r8Version("8.8.19") 26 | //... 27 | } 28 | } 29 | ``` 30 | 31 | Gr8 can also download a R8 jar from a git sha1: 32 | 33 | ```kotlin 34 | gr8 { 35 | create("default") { 36 | r8Version("887704078a06fc0090e7772c921a30602bf1a49f") 37 | //... 38 | } 39 | } 40 | ``` 41 | 42 | ## [BREAKING] Artifact transform 43 | 44 | Gr8 now uses an [artifact transform](https://docs.gradle.org/current/userguide/artifact_transforms.html) to filter the input jars: 45 | 46 | ```kotlin 47 | gr8 { 48 | registerFilterTransform(listOf(".*/impldep/META-INF/versions/.*")) 49 | } 50 | ``` 51 | 52 | As a consequence, `Gr8Configurator.configuration(String)` and `Gr8Configurator.classPathConfiguration(String)` are removed and replaced by equivalent APIs accepting files: 53 | 54 | ```kotlin 55 | gr8 { 56 | create("default") { 57 | // Replace 58 | configuration("shadowedDependencies") 59 | // With 60 | addProgramJarsFrom(configurations.getByName("shadowedDependencies")) 61 | 62 | // Replace 63 | stripGradleApi(true) 64 | classPathConfiguration("compileOnlyDependenciesForGr8") 65 | 66 | // With 67 | val compileOnlyDependenciesForGr8 = configurations.create("compileOnlyDependenciesForGr8") { 68 | attributes { 69 | attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, FilterTransform.artifactType) 70 | attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_API)) 71 | } 72 | } 73 | registerFilterTransform(listOf(".*/impldep/META-INF/versions/.*")) 74 | addClassPathJarsFrom(compileOnlyDependenciesForGr8) 75 | } 76 | } 77 | ``` 78 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Releasing 2 | 3 | The plugin is released to MavenCentral and the GradlePluginPortal. To release: 4 | 5 | * Bump the version in PublishingPlugin 6 | * Create a tag 7 | * Push the tag 8 | * Wait for GitHub Actions to build and publish the artifacts 9 | * Go to https://oss.sonatype.org/#stagingRepositories -> close and release the repo 10 | * Profit 🍹 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 GradleUp authors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gr8 [![Maven Central](https://img.shields.io/maven-central/v/com.gradleup/gr8-plugin?style=flat-square)](https://central.sonatype.com/namespace/com.gradleup) 2 | 3 | Gr8 is [Gradle](https://gradle.org/) + [R8](https://r8.googlesource.com/r8). 4 | 5 | Gr8 makes it easy to shadow, shrink, and minimize your jars. 6 | 7 | ## Motivation 8 | 9 | Gradle has a [very powerful plugin system](https://r8.googlesource.com/r8). Unfortunately, [Gradle handling of classpath/Classloaders](https://dev.to/autonomousapps/build-compile-run-a-crash-course-in-classpaths-f4g) for plugins has some serious limitations. For an example: 10 | 11 | * Gradle always [forces its bundled version of the Kotlin stdlib in the classpath](https://github.com/gradle/gradle/issues/16345). This makes it impossible to use Kotlin 1.5 APIs with Gradle 7.1 for an example because Gradle 7.1 uses Kotlin 1.4 (See [compatibility matrix](https://docs.gradle.org/current/userguide/compatibility.html) for other versions). 12 | * [`buildSrc` dependencies leak in the classpath](https://github.com/gradle/gradle/issues/8301). This causes [very weird bugs](https://github.com/apollographql/apollo-android/issues/2939) during execution because a conflicting dependency might be forced in the classpath. This happens especially with popular libraries such as `okio` or `antlr` that are likely to be used with conflicting versions by different plugins in your build. 13 | 14 | By shadowing (embedding and relocating) the plugin dependencies, it is possible to ship a plugin and all its dependencies without having to worry about what other dependencies are on the classpath, including the Kotlin stdlib. 15 | 16 | To learn more, read the ["Use latest Kotlin in your Gradle plugins"](https://mbonnin.net/2021-11-12_use-latest-kotlin-in-your-gradle-plugins/) blog post. 17 | 18 | Gr8 is mostly focused at Gradle plugins but you can use it to relocate/shrink any library/binary. See [Shrinking a Kotlin binary by 99.2%](https://jakewharton.com/shrinking-a-kotlin-binary/ ) for a good illustration. 19 | 20 | ## Usage 21 | 22 | ```kotlin 23 | plugins { 24 | id("org.jetbrains.kotlin.jvm").version("$latestKotlinVersion") 25 | id("com.gradleup.gr8").version("$gr8Version") 26 | } 27 | 28 | dependencies { 29 | implementation("com.squareup.okhttp3:okhttp:4.9.0") 30 | // More dependencies here 31 | } 32 | 33 | /** 34 | * Create a separate configuration to resolve compileOnly dependencies. 35 | * You can skip this if you have no compileOnly dependencies. 36 | */ 37 | val compileOnlyDependencies: Configuration = configurations.create("compileOnlyDependencies") 38 | compileOnlyDependencies.extendsFrom(configurations.getByName("compileOnly")) 39 | 40 | gr8 { 41 | val shadowedJar = create("gr8") { 42 | // program jars are included in the final shadowed jar 43 | addProgramJarsFrom(configurations.getByName("runtimeClasspath")) 44 | addProgramJarsFrom(tasks.getByName("jar")) 45 | // classpath jars are only used by R8 for analysis but are not included in the 46 | // final shadowed jar. 47 | addClassPathJarsFrom(compileOnlyDependencies) 48 | proguardFile("rules.pro") 49 | 50 | // Use a version from https://storage.googleapis.com/r8-releases/raw 51 | // Requires a maven("https://storage.googleapis.com/r8-releases/raw") repository 52 | r8Version("8.8.19") 53 | // Or use a commit 54 | // The jar is downloaded on demand 55 | r8Version("887704078a06fc0090e7772c921a30602bf1a49f") 56 | // Or leave it to the default version 57 | } 58 | } 59 | ``` 60 | 61 | Then customize your proguard rules. The below is a non-exhaustive example. If you're using reflection, you might need more rules 62 | 63 | ``` 64 | # Keep your public API so that it's callable from scripts 65 | -keep class com.example.** { *; } 66 | 67 | # Repackage other classes 68 | -repackageclasses com.example.relocated 69 | 70 | # Allows more aggressive repackaging 71 | -allowaccessmodification 72 | 73 | # We need to keep type arguments for Gradle to be able to instantiate abstract models like `Property` 74 | -keepattributes Signature,Exceptions,*Annotation*,InnerClasses,PermittedSubclasses,EnclosingMethod,Deprecated,SourceFile,LineNumberTable 75 | ``` 76 | 77 | ## Using Gr8 for Gradle plugins 78 | 79 | Using Gr8 to shadow dependencies in Gradle plugin is a typical use case but requires extra care because: 80 | 81 | * The `java-gradle-plugin` automatically adds `api(gradleApi())` to your dependencies but `gradleApi()` shouldn't be shadowed. 82 | * `gradleApi()` is a [multi-release jar](https://docs.oracle.com/javase/10/docs/specs/jar/jar.html#multi-release-jar-files) file that [R8 doesn't support](https://issuetracker.google.com/u/1/issues/380805015). 83 | * Since the plugins are published, the shadowed dependencies must not be exposed in the .pom/.module files. 84 | 85 | To work around this, you can use, `removeGradleApiFromApi()`, `registerTransform()` and custom configurations: 86 | 87 | ```kotlin 88 | val shadowedDependencies = configurations.create("shadowedDependencies") 89 | 90 | val compileOnlyDependencies: Configuration = configurations.create("compileOnlyDependencies") { 91 | attributes { 92 | attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_API)) 93 | 94 | // this attribute is needed to filter out some classes, see https://issuetracker.google.com/u/1/issues/380805015 95 | attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, FilterTransform.artifactType) 96 | } 97 | } 98 | compileOnlyDependencies.extendsFrom(configurations.getByName("compileOnly")) 99 | 100 | dependencies { 101 | add(shadowedDependencies.name, "com.squareup.okhttp3:okhttp:4.9.0") 102 | add("compileOnly", gradleApi()) 103 | // More dependencies here 104 | } 105 | 106 | if (shadow) { 107 | gr8 { 108 | val shadowedJar = create("default") { 109 | addProgramJarsFrom(shadowedDependencies) 110 | addProgramJarsFrom(tasks.getByName("jar")) 111 | // classpath jars are only used by R8 for analysis but are not included in the 112 | // final shadowed jar. 113 | addClassPathJarsFrom(compileOnlyDependencies) 114 | 115 | proguardFile("rules.pro") 116 | 117 | // for more information about the different options, refer to their matching R8 documentation 118 | // at https://r8.googlesource.com/r8#running-r8 119 | 120 | // See https://issuetracker.google.com/u/1/issues/380805015 for why this is required 121 | registerFilterTransform(listOf(".*/impldep/META-INF/versions/.*")) 122 | } 123 | 124 | removeGradleApiFromApi() 125 | 126 | // Optional: replace the regular jar with the shadowed one in the publication 127 | replaceOutgoingJar(shadowedJar) 128 | 129 | // Or if you prefer the shadowed jar to be a separate variant in the default publication 130 | // The variant will have `org.gradle.dependency.bundling = shadowed` 131 | addShadowedVariant(shadowedJar) 132 | 133 | // Allow to compile the module without exposing the shadowedDependencies downstream 134 | configurations.getByName("compileOnly").extendsFrom(shadowedDependencies) 135 | configurations.getByName("testImplementation").extendsFrom(shadowedDependencies) 136 | } 137 | } else { 138 | configurations.getByName("implementation").extendsFrom(shadowedDependencies) 139 | } 140 | ``` 141 | 142 | ## Kotlin interop 143 | 144 | By default, R8 removes `kotlin.Metadata` from the shadowed jar. This means the Kotlin compiler only sees plain Java classes and symbols and Kotlin-only features such as parameters default values, extension function, etc... are lost. 145 | 146 | If you want to keep them, you need to keep `kotlin.Metadata` and `kotlin.Unit`: 147 | 148 | ``` 149 | # Keep kotlin metadata so that the Kotlin compiler knows about top level functions 150 | -keep class kotlin.Metadata { *; } 151 | # Keep Unit as it's in the signature of public methods: 152 | -keep class kotlin.Unit { *; } 153 | ``` 154 | 155 | > [!NOTE] 156 | > Stripping kotlin.Metadata acts as a compile-time verification that your API is usable in Groovy as it is in Kotlin and might be beneficial. 157 | 158 | ## Java runtime version 159 | 160 | You can specify the version of the java runtime to use with `systemClassesToolchain`: 161 | 162 | ```kotlin 163 | gr8 { 164 | val shadowedJar = create("gr8") { 165 | proguardFile("rules.pro") 166 | addProgramJarsFrom(configurations.getByName("runtimeClasspath")) 167 | systemClassesToolchain { 168 | languageVersion.set(JavaLanguageVersion.of(11)) 169 | } 170 | } 171 | } 172 | ``` 173 | 174 | ## FAQ 175 | 176 | **Could I use the Shadow plugin instead?** 177 | 178 | The [Gradle Shadow Plugin](https://imperceptiblethoughts.com/shadow/) has been [helping plugin authors](https://www.alecstrong.com/posts/shading/) 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](https://github.com/johnrengelman/shadow/issues/232). In practice, any plugin that tries to read the `"kotlin"` extension is subject to having its behaviour changed: 179 | 180 | ```kotlin 181 | project.extensions.getByName("kotlin") 182 | ``` 183 | 184 | will be transformed to: 185 | 186 | ```kotlin 187 | project.extensions.getByName("com.relocated.kotlin") 188 | ``` 189 | 190 | For plugins that generate source code and contain a lot of package names, this might be even more unpredictable and require weird [workarounds](https://github.com/apollographql/apollo-android/blob/f72c3afd17655591aca90a6a118dbb7be9c50920/apollo-compiler/src/main/kotlin/com/apollographql/apollo/compiler/codegen/kotlin/OkioJavaTypeName.kt#L19). 191 | 192 | By using `R8` and [proguard rules](https://www.guardsquare.com/manual/configuration/usage), `Gr8` makes relocation more predictable and configurable. 193 | 194 | **Could I use the Gradle Worker API instead?** 195 | 196 | The [Gradle Worker API](https://docs.gradle.org/current/userguide/worker_api.html) has a [classLoaderIsolation mode](https://docs.gradle.org/current/kotlin-dsl/gradle/org.gradle.workers/-worker-executor/class-loader-isolation.html) that can be used to achieve a similar result with some limitations: 197 | * `gradle-api` and `kotlin-stdlib` are still in the worker classpath meaning you need to make sure your Kotlin version is compatible. 198 | * [classLoaderIsolation leaks memory](https://github.com/gradle/gradle/issues/18313) 199 | * Workers require serializing parameters and writing more boilerplate code. 200 | 201 | **Are there any drawbacks?** 202 | 203 | Yes. Because every plugin now relocates its own version of `kotlin-stdlib`, `okio` and other dependencies, 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. 204 | 205 | -------------------------------------------------------------------------------- /build-logic/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("java") 3 | } 4 | 5 | group = "build-logic" 6 | 7 | dependencies { 8 | implementation(libs.vespene) 9 | implementation(libs.kgp) 10 | implementation(libs.gradle.publish) 11 | implementation(libs.gr8.published) 12 | implementation(libs.librarian) 13 | } 14 | -------------------------------------------------------------------------------- /build-logic/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | dependencyResolutionManagement { 2 | this.versionCatalogs { 3 | this.create("libs") { 4 | from(files("../gradle/libs.versions.toml")) 5 | } 6 | } 7 | } 8 | 9 | apply(from = "../gradle/repositories.gradle.kts") 10 | -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | import com.gradleup.librarian.gradle.Librarian 2 | 3 | buildscript { 4 | dependencies { 5 | classpath("build-logic:build-logic") 6 | } 7 | 8 | repositories { 9 | mavenCentral() 10 | gradlePluginPortal() 11 | google() 12 | maven("https://storage.googleapis.com/gradleup/m2") 13 | } 14 | } 15 | 16 | Librarian.root(project) -------------------------------------------------------------------------------- /gr8-plugin-common/api/gr8-plugin-common.api: -------------------------------------------------------------------------------- 1 | public abstract class com/gradleup/gr8/DownloadR8Task : org/gradle/api/DefaultTask { 2 | public fun ()V 3 | public abstract fun getOutputFile ()Lorg/gradle/api/file/RegularFileProperty; 4 | public abstract fun getSha1 ()Lorg/gradle/api/provider/Property; 5 | public final fun taskAction ()V 6 | } 7 | 8 | public abstract class com/gradleup/gr8/FilterTransform : org/gradle/api/artifacts/transform/TransformAction { 9 | public static final field Companion Lcom/gradleup/gr8/FilterTransform$Companion; 10 | public static final field artifactType Ljava/lang/String; 11 | public fun ()V 12 | public abstract fun getInputArtifact ()Lorg/gradle/api/provider/Provider; 13 | public fun transform (Lorg/gradle/api/artifacts/transform/TransformOutputs;)V 14 | } 15 | 16 | public final class com/gradleup/gr8/FilterTransform$Companion { 17 | } 18 | 19 | public abstract interface class com/gradleup/gr8/FilterTransform$Parameters : org/gradle/api/artifacts/transform/TransformParameters { 20 | public abstract fun getExcludes ()Ljava/util/List; 21 | public abstract fun setExcludes (Ljava/util/List;)V 22 | } 23 | 24 | public class com/gradleup/gr8/Gr8Configurator { 25 | public fun (Ljava/lang/String;Lorg/gradle/api/Project;Lorg/gradle/jvm/toolchain/JavaToolchainService;)V 26 | public final fun addClassPathJarsFrom (Ljava/lang/Object;)V 27 | public final fun addProgramJarsFrom (Ljava/lang/Object;)V 28 | public final fun classPathConfiguration (Ljava/lang/String;)V 29 | public final fun configuration (Ljava/lang/String;)V 30 | public final fun exclude (Ljava/lang/String;)V 31 | public final fun getDefaultR8Version ()Ljava/lang/String; 32 | public final fun proguardFile (Ljava/lang/Object;)V 33 | public final fun r8Version (Ljava/lang/String;)V 34 | public final fun systemClassesToolchain (Lorg/gradle/api/Action;)V 35 | public final fun systemClassesToolchain (Lorg/gradle/jvm/toolchain/JavaCompiler;)V 36 | } 37 | 38 | public abstract class com/gradleup/gr8/Gr8Extension { 39 | public fun (Lorg/gradle/api/Project;)V 40 | public final fun addShadowedVariant (Ljava/lang/Object;)V 41 | public final fun create (Ljava/lang/String;Lorg/gradle/api/Action;)Lorg/gradle/api/provider/Provider; 42 | public static synthetic fun create$default (Lcom/gradleup/gr8/Gr8Extension;Ljava/lang/String;Lorg/gradle/api/Action;ILjava/lang/Object;)Lorg/gradle/api/provider/Provider; 43 | protected abstract fun getJavaToolchainService ()Lorg/gradle/jvm/toolchain/JavaToolchainService; 44 | public final fun registerFilterTransform (Ljava/util/List;)V 45 | public final fun registerFilterTransform (Ljava/util/List;Ljava/lang/String;)V 46 | public final fun removeGradleApiFromApi ()V 47 | public final fun replaceOutgoingJar (Ljava/lang/Object;)V 48 | } 49 | 50 | public abstract class com/gradleup/gr8/Gr8Task : org/gradle/api/tasks/JavaExec { 51 | public fun ()V 52 | public fun exec ()V 53 | } 54 | 55 | -------------------------------------------------------------------------------- /gr8-plugin-common/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import com.gradleup.librarian.gradle.Librarian 2 | 3 | plugins { 4 | id("org.jetbrains.kotlin.jvm") 5 | } 6 | 7 | dependencies { 8 | compileOnly(libs.gradle.api) 9 | } 10 | 11 | Librarian.module(project) 12 | 13 | -------------------------------------------------------------------------------- /gr8-plugin-common/src/main/kotlin/com/gradleup/gr8/DownloadR8Task.kt: -------------------------------------------------------------------------------- 1 | package com.gradleup.gr8 2 | 3 | import org.gradle.api.DefaultTask 4 | import org.gradle.api.file.RegularFileProperty 5 | import org.gradle.api.provider.Property 6 | import org.gradle.api.tasks.CacheableTask 7 | import org.gradle.api.tasks.Input 8 | import org.gradle.api.tasks.OutputFile 9 | import org.gradle.api.tasks.TaskAction 10 | import java.net.URI 11 | 12 | @CacheableTask // We want to keep the downloaded jar in local build cache if any 13 | abstract class DownloadR8Task : DefaultTask() { 14 | @get:Input 15 | abstract val sha1: Property 16 | 17 | @get:OutputFile 18 | abstract val outputFile: RegularFileProperty 19 | 20 | @TaskAction 21 | fun taskAction() { 22 | if (outputFile.get().asFile.exists()) { 23 | return 24 | } 25 | val url = "https://storage.googleapis.com/r8-releases/raw/main/${sha1.get()}/r8.jar" 26 | 27 | URI(url).toURL().openStream().buffered().use { inputStream -> 28 | outputFile.get().asFile.outputStream().use { outputStream -> 29 | inputStream.copyTo(outputStream) 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /gr8-plugin-common/src/main/kotlin/com/gradleup/gr8/FilterTransform.kt: -------------------------------------------------------------------------------- 1 | package com.gradleup.gr8 2 | 3 | import org.gradle.api.artifacts.transform.InputArtifact 4 | import org.gradle.api.artifacts.transform.TransformAction 5 | import org.gradle.api.artifacts.transform.TransformOutputs 6 | import org.gradle.api.artifacts.transform.TransformParameters 7 | import org.gradle.api.attributes.Attribute 8 | import org.gradle.api.file.FileSystemLocation 9 | import org.gradle.api.provider.Provider 10 | import org.gradle.api.tasks.Input 11 | import org.gradle.api.tasks.PathSensitive 12 | import org.gradle.api.tasks.PathSensitivity 13 | import java.util.zip.ZipEntry 14 | import java.util.zip.ZipInputStream 15 | import java.util.zip.ZipOutputStream 16 | 17 | abstract class FilterTransform: TransformAction { 18 | @get:PathSensitive(PathSensitivity.NAME_ONLY) 19 | @get:InputArtifact 20 | abstract val inputArtifact: Provider 21 | 22 | override fun transform(outputs: TransformOutputs) { 23 | val file = inputArtifact.get().asFile 24 | val regexes = parameters.excludes.map { Regex(it) } 25 | ZipInputStream(file.inputStream()).use { inputStream -> 26 | ZipOutputStream(outputs.file("${file.nameWithoutExtension}-filtered.${file.extension}").outputStream()).use { outputStream -> 27 | var entry: ZipEntry? = inputStream.nextEntry 28 | while (entry != null) { 29 | if (regexes.none { it.matches(entry!!.name) }) { 30 | outputStream.putNextEntry(entry) 31 | inputStream.copyTo(outputStream) 32 | } 33 | entry = inputStream.nextEntry 34 | } 35 | } 36 | } 37 | } 38 | 39 | interface Parameters : TransformParameters { 40 | /** 41 | * A list of Regex patterns 42 | */ 43 | @get:Input 44 | var excludes: List 45 | } 46 | 47 | companion object { 48 | @JvmField 49 | val artifactType = "filtered-jar" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /gr8-plugin-common/src/main/kotlin/com/gradleup/gr8/Gr8Configurator.kt: -------------------------------------------------------------------------------- 1 | package com.gradleup.gr8 2 | 3 | import org.gradle.api.Action 4 | import org.gradle.api.Project 5 | import org.gradle.api.plugins.JavaPluginExtension 6 | import org.gradle.api.provider.ListProperty 7 | import org.gradle.api.provider.Property 8 | import org.gradle.api.tasks.TaskProvider 9 | import org.gradle.jvm.toolchain.JavaCompiler 10 | import org.gradle.jvm.toolchain.JavaToolchainService 11 | import org.gradle.jvm.toolchain.JavaToolchainSpec 12 | 13 | open class Gr8Configurator( 14 | private val name: String, 15 | private val project: Project, 16 | private val javaToolchainService: JavaToolchainService, 17 | ) { 18 | private val programJars = project.objects.fileCollection() 19 | 20 | private val excludes: ListProperty = project.objects.listProperty(String::class.java) 21 | private val classPathExcludes: ListProperty = project.objects.listProperty(String::class.java) 22 | private val javaCompiler: Property = project.objects.property(JavaCompiler::class.java) 23 | private val proguardFiles = project.objects.fileCollection() 24 | private var classPathJars = project.objects.fileCollection() 25 | 26 | val defaultR8Version = "8.7.18" 27 | 28 | private var r8Version_: String = defaultR8Version 29 | 30 | private val buildDir = project.layout.buildDirectory.dir("gr8/$name").get().asFile 31 | 32 | init { 33 | val javaExtension = project.extensions.findByType(JavaPluginExtension::class.java) 34 | if (javaExtension != null) { 35 | javaCompiler.convention(javaToolchainService.compilerFor(javaExtension.toolchain)) 36 | } 37 | excludes.convention(null as List?) 38 | classPathExcludes.convention(null as List?) 39 | } 40 | 41 | fun r8Version(r8Version: String) { 42 | r8Version_ = r8Version 43 | } 44 | 45 | /** 46 | * The configuration to shadow in the resulting output jar. 47 | */ 48 | @Deprecated("use addProgramJarsFrom(configurations.getByName(\"name\") instead", replaceWith = ReplaceWith("addProgramJarsFrom(configurations.getByName(\"name\")"), level = DeprecationLevel.ERROR) 49 | fun configuration(name: String): Unit = TODO() 50 | 51 | /** 52 | * The jar file to include in the resulting output jar. 53 | * 54 | * Default: the jar produced by the "jar" task 55 | * 56 | * @param file a file that will be evaluated like [Project.file]. If this file is created by another task, use a provider 57 | * so that the dependency between the task can be set up 58 | */ 59 | fun addProgramJarsFrom(file: Any) { 60 | programJars.from(file) 61 | } 62 | 63 | /** 64 | * Adds additional jars on the classpath (but not in the output jar). 65 | */ 66 | @Deprecated("use addClassPathJarsFrom(configurations.getByName(\"name\") instead", replaceWith = ReplaceWith("addClassPathJarsFrom(configurations.getByName(\"name\")"), level = DeprecationLevel.ERROR) 67 | fun classPathConfiguration(name: String): Unit = TODO() 68 | 69 | /** 70 | * Adds additional jars on the classpath (but not in the output jar). 71 | * 72 | * @param files files to add, evaluated as in [Project.file]. 73 | */ 74 | fun addClassPathJarsFrom(files: Any) { 75 | classPathJars.from(files) 76 | } 77 | 78 | /** 79 | * Adds the given file as a proguard-like configuration file 80 | * 81 | * @param file a file that will be evaluated like [Project.file] 82 | */ 83 | fun proguardFile(file: Any) { 84 | proguardFiles.from(file) 85 | } 86 | 87 | @Deprecated("exclude is not supported anymore, use addProgramJarsFrom(fileCollection) and filter your fileCollection. See also FilterTransform") 88 | fun exclude(exclude: String) { 89 | this.excludes.add(exclude) 90 | } 91 | 92 | /** 93 | * The java compiler toolchain to use for discovering system classes when running R8 94 | * 95 | * The system classes from this Java toolchain will be passed to R8 when invoking it, enabling you 96 | * to target any version of Java toolchain while building on newer JDKs. Defaults to the toolchain used to compile. 97 | * 98 | * Usage: 99 | * 100 | * ``` 101 | * systemClassesToolchain(javaToolchains.compilerFor { 102 | * languageVersion.set(JavaLanguageVersion.of(11)) 103 | * }) 104 | * ``` 105 | */ 106 | fun systemClassesToolchain(compiler: JavaCompiler) { 107 | this.javaCompiler.set(compiler) 108 | } 109 | 110 | /** 111 | * The java compiler toolchain to use for discovering system classes when running R8, defaults to the Java extension 112 | * toolchain (also used for compiling your classes) 113 | * 114 | * The system classes from this Java toolchain will be passed to R8 when invoking it, enabling you 115 | * to target any version of Java toolchain while building on newer JDKs. Defaults to the toolchain used to compile. 116 | * 117 | * Usage: 118 | * 119 | * ``` 120 | * systemClassesToolchain { 121 | * languageVersion.set(JavaLanguageVersion.of(11)) 122 | * } 123 | * ``` 124 | */ 125 | fun systemClassesToolchain(spec: Action) { 126 | this.javaCompiler.set(javaToolchainService.compilerFor(spec)) 127 | } 128 | 129 | internal fun registerTasks(): TaskProvider { 130 | val upperCaseName = name.replaceFirstChar { it.uppercase() } 131 | 132 | val gr8Configuration = project.configurations.create("gr8$upperCaseName") { 133 | it.isCanBeResolved = true 134 | } 135 | gr8Configuration.dependencies.add(project.dependencies.create("com.android.tools:r8:$defaultR8Version")) 136 | 137 | val downloadR8 = project.tasks.register("gr8${upperCaseName}Download", DownloadR8Task::class.java) { 138 | it.sha1.set(r8Version_) 139 | it.outputFile.set(buildDir.resolve("r8/$r8Version_.jar")) 140 | } 141 | 142 | val r8TaskProvider = project.tasks.register("gr8${upperCaseName}ShadowedJar", Gr8Task::class.java) { task -> 143 | if (r8Version_.contains('.')) { 144 | task.classpath(gr8Configuration) 145 | } else { 146 | task.classpath(downloadR8) 147 | } 148 | 149 | task.mainClass.set("com.android.tools.r8.R8") 150 | 151 | task.programFiles.from(programJars) 152 | task.mapping.set(buildDir.resolve("mapping.txt")) 153 | task.classPathFiles.from(classPathJars) 154 | task.proguardConfigurationFiles.from(proguardFiles) 155 | 156 | task.outputJar.set(buildDir.resolve("${project.name}-${project.version}-shadowed.jar")) 157 | 158 | task.javaCompiler.set(javaCompiler) 159 | } 160 | 161 | return r8TaskProvider 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /gr8-plugin-common/src/main/kotlin/com/gradleup/gr8/Gr8Extension.kt: -------------------------------------------------------------------------------- 1 | package com.gradleup.gr8 2 | 3 | import org.gradle.api.Action 4 | import org.gradle.api.Project 5 | import org.gradle.api.artifacts.FileCollectionDependency 6 | import org.gradle.api.artifacts.type.ArtifactTypeDefinition 7 | import org.gradle.api.attributes.Bundling 8 | import org.gradle.api.attributes.Category 9 | import org.gradle.api.attributes.LibraryElements 10 | import org.gradle.api.attributes.Usage 11 | import org.gradle.api.component.AdhocComponentWithVariants 12 | import org.gradle.api.file.RegularFile 13 | import org.gradle.api.provider.Provider 14 | import org.gradle.jvm.toolchain.JavaToolchainService 15 | import javax.inject.Inject 16 | 17 | abstract class Gr8Extension( 18 | private val project: Project, 19 | ) { 20 | 21 | private val configurators = mutableSetOf() 22 | 23 | @get:Inject 24 | protected abstract val javaToolchainService: JavaToolchainService 25 | 26 | /** 27 | * @return a provider that returns the new fat-minimized jar 28 | */ 29 | fun create(name: String, action: Action = Action {}): Provider { 30 | check(configurators.contains(name).not()) { 31 | "Gr8: $name is already created" 32 | } 33 | 34 | val configurator = Gr8Configurator(name, project, javaToolchainService) 35 | configurators.add(name) 36 | 37 | action.execute(configurator) 38 | 39 | val provider = configurator.registerTasks() 40 | 41 | return provider.flatMap { it.outputJar } 42 | } 43 | 44 | /** 45 | * Replaces the default jar in outgoingVariants with [newJar] 46 | * Because it replaces the existing jar, the variant will keep the dependencies and attributes 47 | * of the java component. In particular, "org.gradle.dependency.bundling" will be "external" despite 48 | * the newJar most likely shading some dependencies. 49 | * 50 | * In order to not propagate dependencies, create a separate "shade" configuration and make "compileOnly" 51 | * extend it 52 | * 53 | * @param newJar the new jar to use 54 | * See [org.gradle.api.artifacts.dsl.ArtifactHandler] for details of the supported notations. 55 | */ 56 | fun replaceOutgoingJar(newJar: Any) { 57 | project.configurations.configureEach { configuration -> 58 | configuration.outgoing { publications -> 59 | val removed = publications.artifacts.removeIf { it.classifier.isNullOrEmpty() } 60 | if (removed) { 61 | publications.artifact(newJar) { artifact -> 62 | // Pom and maven consumers do not like the `-all` or `-shadowed` classifiers 63 | artifact.classifier = "" 64 | } 65 | } 66 | } 67 | } 68 | } 69 | 70 | /** 71 | * Adds a new variant with "org.gradle.dependency.bundling": "shadowed" 72 | */ 73 | fun addShadowedVariant(shadowedJar: Any) { 74 | val producerConfiguration = project.configurations.create("gr8") { 75 | it.isCanBeResolved = false 76 | it.isCanBeConsumed = true 77 | it.attributes { 78 | it.attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage::class.java, Usage.JAVA_RUNTIME)) 79 | it.attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling::class.java, Bundling.SHADOWED)) 80 | it.attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category::class.java, Category.LIBRARY)) 81 | it.attribute( 82 | LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named( 83 | LibraryElements::class.java, 84 | LibraryElements.JAR 85 | )) 86 | } 87 | } 88 | 89 | val components = project.components 90 | val javaComponent = components.findByName("java") as AdhocComponentWithVariants 91 | javaComponent.addVariantsFromConfiguration(producerConfiguration) {} 92 | 93 | project.artifacts.add("gr8", shadowedJar) 94 | } 95 | 96 | /** 97 | * Removes `gradleApi()` from the `api` configuration. 98 | * 99 | * `gradleApi()` is automatically added as an `api` dependency by the `java-gradle-plugin` plugin but this is generally not desired because: 100 | * - The Gradle API version used to compile a plugin may be different from the version used to run it (see https://github.com/gradle/gradle/issues/1835) 101 | * - `compileOnly` is often a better choice as it doesn't leak the version to consumers. The version is determined by the Gradle version used at runtime. 102 | * 103 | * Note: there's no public API for determining whether a dependency is actually the `gradleApi()` dependency. 104 | * This method makes a best guess by removing all `FileCollectionDependency`. If you added `FileCollectionDependency`, 105 | * you'll want to use something else. 106 | */ 107 | fun removeGradleApiFromApi() { 108 | val apiDependencies = project.configurations.getByName("api").dependencies 109 | apiDependencies.firstOrNull { 110 | it is FileCollectionDependency 111 | }.let { 112 | apiDependencies.remove(it) 113 | } 114 | } 115 | 116 | fun registerFilterTransform(excludePatterns: List) { 117 | registerFilterTransform(excludePatterns, FilterTransform.artifactType) 118 | } 119 | 120 | fun registerFilterTransform(excludePatterns: List, artifactType: String) { 121 | project.dependencies.registerTransform(FilterTransform::class.java) { 122 | it.from.attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, "jar") 123 | it.to.attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, artifactType) 124 | 125 | it.parameters.excludes = excludePatterns 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /gr8-plugin-common/src/main/kotlin/com/gradleup/gr8/Gr8Task.kt: -------------------------------------------------------------------------------- 1 | package com.gradleup.gr8 2 | 3 | import org.gradle.api.file.ConfigurableFileCollection 4 | import org.gradle.api.file.RegularFileProperty 5 | import org.gradle.api.provider.Property 6 | import org.gradle.api.tasks.* 7 | import org.gradle.jvm.toolchain.JavaCompiler 8 | 9 | @CacheableTask 10 | abstract class Gr8Task : JavaExec() { 11 | @get:Classpath 12 | internal abstract val programFiles: ConfigurableFileCollection 13 | 14 | @get:Classpath 15 | internal abstract val classPathFiles: ConfigurableFileCollection 16 | 17 | @get:InputFiles 18 | @get:PathSensitive(PathSensitivity.RELATIVE) 19 | internal abstract val proguardConfigurationFiles: ConfigurableFileCollection 20 | 21 | @get:OutputFile 22 | internal abstract val outputJar: RegularFileProperty 23 | 24 | @get:OutputFile 25 | internal abstract val mapping: RegularFileProperty 26 | 27 | @get:Nested 28 | @get:Optional 29 | internal abstract val javaCompiler: Property 30 | 31 | override fun exec() { 32 | val javaHome = javaCompiler.get().metadata.installationPath.asFile.absolutePath 33 | 34 | args("--release") 35 | args("--classfile") 36 | args("--output") 37 | args(outputJar.get().asFile.absolutePath) 38 | args("--pg-map-output") 39 | args(mapping.get().asFile.absolutePath) 40 | 41 | classPathFiles.forEach { file -> 42 | args("--classpath") 43 | args(file.absolutePath) 44 | } 45 | 46 | proguardConfigurationFiles.forEach { file -> 47 | args("--pg-conf") 48 | args(file.absolutePath) 49 | } 50 | 51 | args("--lib") 52 | args(javaHome) 53 | 54 | programFiles.forEach { 55 | args(it.absolutePath) 56 | } 57 | 58 | super.exec() 59 | } 60 | } -------------------------------------------------------------------------------- /gr8-plugin-external/api/gr8-plugin-external.api: -------------------------------------------------------------------------------- 1 | public class com/gradleup/gr8/Gr8Plugin : org/gradle/api/Plugin { 2 | public fun ()V 3 | public synthetic fun apply (Ljava/lang/Object;)V 4 | public fun apply (Lorg/gradle/api/Project;)V 5 | } 6 | 7 | -------------------------------------------------------------------------------- /gr8-plugin-external/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import com.gradleup.librarian.gradle.Librarian 2 | 3 | plugins { 4 | id("org.jetbrains.kotlin.jvm") 5 | id("java-gradle-plugin") 6 | } 7 | 8 | dependencies { 9 | implementation(project(":gr8-plugin-common")).excludeKotlinStdlib() 10 | } 11 | 12 | fun Dependency?.excludeKotlinStdlib() { 13 | (this as? ExternalModuleDependency)?.apply { 14 | exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib") 15 | exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-jdk7") 16 | exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-jdk8") 17 | } 18 | } 19 | 20 | Librarian.module(project) 21 | 22 | gradlePlugin { 23 | plugins { 24 | create("gr8") { 25 | id = "com.gradleup.gr8.external" 26 | implementationClass = "com.gradleup.gr8.Gr8Plugin" 27 | // This is required by the Gradle publish plugin 28 | displayName = "Gr8 Plugin External" 29 | description = "The Gr8 Plugin packaged with external dependencies" 30 | } 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /gr8-plugin-external/src/main/kotlin/com/gradleup/gr8/Gr8Plugin.kt: -------------------------------------------------------------------------------- 1 | package com.gradleup.gr8 2 | 3 | import org.gradle.api.Plugin 4 | import org.gradle.api.Project 5 | 6 | open class Gr8Plugin: Plugin { 7 | override fun apply(target: Project) { 8 | target.extensions.create("gr8", Gr8Extension::class.java, target) 9 | } 10 | } 11 | 12 | -------------------------------------------------------------------------------- /gr8-plugin/api/gr8-plugin.api: -------------------------------------------------------------------------------- 1 | public class com/gradleup/gr8/Gr8Plugin : org/gradle/api/Plugin { 2 | public fun ()V 3 | public synthetic fun apply (Ljava/lang/Object;)V 4 | public fun apply (Lorg/gradle/api/Project;)V 5 | } 6 | 7 | -------------------------------------------------------------------------------- /gr8-plugin/build.gradle.kts: -------------------------------------------------------------------------------- 1 | @file:Suppress("UnstableApiUsage") 2 | 3 | import com.gradleup.gr8.FilterTransform 4 | import com.gradleup.librarian.gradle.Librarian 5 | 6 | plugins { 7 | id("org.jetbrains.kotlin.jvm") 8 | id("java-gradle-plugin") 9 | id("com.gradleup.gr8") 10 | } 11 | 12 | val filteredClasspathDependencies: Configuration = configurations.create("filteredClasspathDependencies") { 13 | attributes { 14 | attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, FilterTransform.artifactType) 15 | attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_API)) 16 | } 17 | } 18 | 19 | filteredClasspathDependencies.extendsFrom(configurations.getByName("compileOnly")) 20 | 21 | dependencies { 22 | implementation(project(":gr8-plugin-common")) 23 | compileOnly("dev.gradleplugins:gradle-api:6.7") 24 | } 25 | 26 | if (true) { 27 | gr8 { 28 | val shadowedJar = create("default") { 29 | addProgramJarsFrom(configurations.getByName("runtimeClasspath")) 30 | addProgramJarsFrom(tasks.getByName("jar")) 31 | addClassPathJarsFrom(filteredClasspathDependencies) 32 | 33 | proguardFile("rules.pro") 34 | 35 | r8Version("887704078a06fc0090e7772c921a30602bf1a49f") 36 | systemClassesToolchain { 37 | languageVersion.set(JavaLanguageVersion.of(11)) 38 | } 39 | registerFilterTransform(listOf(".*/impldep/META-INF/versions/.*")) 40 | } 41 | 42 | removeGradleApiFromApi() 43 | replaceOutgoingJar(shadowedJar) 44 | } 45 | } 46 | 47 | gradlePlugin { 48 | plugins { 49 | create("gr8") { 50 | id = "com.gradleup.gr8" 51 | implementationClass = "com.gradleup.gr8.Gr8Plugin" 52 | // This is required by the Gradle publish plugin 53 | displayName = "Gr8 Plugin" 54 | description = "The Gr8 Plugin packaged with all dependencies relocated" 55 | } 56 | } 57 | } 58 | 59 | Librarian.module(project) 60 | 61 | // See https://github.com/GradleUp/librarian/issues/50 62 | afterEvaluate { 63 | extensions.getByType().publications.configureEach { 64 | this as MavenPublication 65 | if (name.lowercase().contains("marker")) { 66 | this.groupId = "com.gradleup.gr8" 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /gr8-plugin/rules.pro: -------------------------------------------------------------------------------- 1 | # Keep our public API 2 | -keep class com.gradleup.** { *; } 3 | 4 | # Keep class names to make debugging easier 5 | -dontobfuscate 6 | 7 | # Makes it easier to debug on MacOS case-insensitive filesystem when unzipping the jars 8 | -repackageclasses com.gradleup.gr8.relocated 9 | 10 | 11 | # We need to keep type arguments (Signature) for Gradle to be able to instantiate abstract models like `Property` 12 | # Else it fails with 13 | # 'Declaration of property alwaysGenerateTypesMatching does not include any type arguments in its property type interface org.gradle.api.provider.SetProperty' 14 | -keepattributes Signature,Exceptions,*Annotation*,InnerClasses,PermittedSubclasses,EnclosingMethod,Deprecated,SourceFile,LineNumberTable 15 | 16 | # kotlin-reflect uses EnumSetOf that makes a reflexive access to "values" 17 | # https://github.com/JetBrains/kotlin/blob/0f9a413ee986f4fd80e26aed2685a1823b2b4279/core/descriptors/src/org/jetbrains/kotlin/builtins/PrimitiveType.java#L39 18 | -keepclassmembers class * extends java.lang.Enum { 19 | public static **[] values(); 20 | } 21 | 22 | #-keep class com.android.tools.r8.threading.providers.blocking.ThreadingModuleBlockingProvider { *; } 23 | #-keep class com.android.tools.r8.threading.providers.singlethreaded.ThreadingModuleSingleThreadedProvider { *; } 24 | -------------------------------------------------------------------------------- /gr8-plugin/src/main/kotlin/com/gradleup/gr8/Gr8Plugin.kt: -------------------------------------------------------------------------------- 1 | package com.gradleup.gr8 2 | 3 | import org.gradle.api.Plugin 4 | import org.gradle.api.Project 5 | 6 | open class Gr8Plugin: Plugin { 7 | override fun apply(target: Project) { 8 | target.extensions.create("gr8", Gr8Extension::class.java, target) 9 | } 10 | } 11 | 12 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx4g 2 | -------------------------------------------------------------------------------- /gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [libraries] 2 | gradle-api = "dev.gradleplugins:gradle-api:7.3" # for ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE 3 | librarian = "com.gradleup.librarian:librarian-gradle-plugin:0.0.8-SNAPSHOT-ba3e33fb6601dae9ea75e1ef75aa9b46bf640b74" 4 | gr8-published = "com.gradleup:gr8-plugin:0.11.0-SNAPSHOT-ac9451b86ec13bc59a090a38585fa20b88eb072e" 5 | gradle-publish = "com.gradle.publish:plugin-publish-plugin:0.15.0" 6 | kgp = "org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.20" 7 | vespene = "net.mbonnin.vespene:vespene-lib:0.6.1" 8 | 9 | [plugins] 10 | -------------------------------------------------------------------------------- /gradle/repositories.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | listOf(repositories, dependencyResolutionManagement.repositories).forEach { 3 | it.apply { 4 | mavenCentral() 5 | google() 6 | gradlePluginPortal() 7 | maven("https://storage.googleapis.com/gradleup/m2") 8 | } 9 | } 10 | } 11 | 12 | dependencyResolutionManagement { 13 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 14 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GradleUp/gr8/390b4023479bad28858c48af6604967556b89ef1/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /librarian.root.properties: -------------------------------------------------------------------------------- 1 | java.compatibility=8 2 | kotlin.compatibility=1.9.0 3 | 4 | kdoc.olderVersions= 5 | 6 | sonatype.backend=Default 7 | 8 | pom.groupId=com.gradleup 9 | pom.version=0.11.3-SNAPSHOT 10 | pom.description=Gradle + R8 = <3 11 | pom.vcsUrl=https://github.com/GradleUp/gr8 12 | pom.developer=gr8 authors 13 | pom.license=MIT License 14 | 15 | gcs.bucket=gradleup 16 | gcs.prefix=m2 17 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | includeBuild("build-logic") 2 | 3 | apply(from = "./gradle/repositories.gradle.kts") 4 | 5 | include(":gr8-plugin") 6 | include(":gr8-plugin-external") 7 | include(":gr8-plugin-common") 8 | 9 | -------------------------------------------------------------------------------- /test-plugin/README.md: -------------------------------------------------------------------------------- 1 | A test plugin that uses gr8 to relocate itself -------------------------------------------------------------------------------- /test-plugin/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import com.gradleup.gr8.FilterTransform 2 | import org.w3c.dom.Element 3 | 4 | plugins { 5 | id("org.jetbrains.kotlin.jvm").version("2.0.21") 6 | id("maven-publish") 7 | id("com.gradleup.gr8") 8 | } 9 | 10 | group = "com.gradleup.gr8.test" 11 | version = "0.1" 12 | 13 | dependencies { 14 | compileOnly("dev.gradleplugins:gradle-api:7.6") 15 | implementation("com.apollographql.apollo:apollo-runtime:4.1.0") 16 | 17 | testImplementation("dev.gradleplugins:gradle-test-kit:6.9") 18 | testImplementation("org.jetbrains.kotlin:kotlin-test") 19 | } 20 | 21 | val compileOnlyDependenciesForGr8: Configuration = configurations.create("compileOnlyDependenciesForGr8") { 22 | attributes { 23 | attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, FilterTransform.artifactType) 24 | attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_API)) 25 | } 26 | } 27 | 28 | compileOnlyDependenciesForGr8.extendsFrom(configurations.getByName("compileOnly")) 29 | 30 | gr8 { 31 | val shadowedJar = create("default") { 32 | addProgramJarsFrom(configurations.getByName("runtimeClasspath")) 33 | addProgramJarsFrom(tasks.getByName("jar")) 34 | addClassPathJarsFrom(compileOnlyDependenciesForGr8) 35 | 36 | proguardFile("rules.pro") 37 | 38 | r8Version("887704078a06fc0090e7772c921a30602bf1a49f") 39 | systemClassesToolchain { 40 | languageVersion.set(JavaLanguageVersion.of(11)) 41 | } 42 | } 43 | registerFilterTransform(listOf(".*/impldep/META-INF/versions/.*")) 44 | addShadowedVariant(shadowedJar) 45 | } 46 | 47 | tasks.named("test") { 48 | dependsOn("publishAllPublicationsToPluginTestRepository") 49 | } 50 | 51 | java { 52 | toolchain { 53 | // Tests use a pretty old version of Gradle so let's stick with an old version of Java as well 54 | languageVersion.set(JavaLanguageVersion.of(11)) 55 | } 56 | } 57 | 58 | publishing { 59 | repositories { 60 | maven { 61 | name = "pluginTest" 62 | url = uri("file://${rootProject.layout.buildDirectory.asFile.get()}/localMaven") 63 | } 64 | } 65 | 66 | publications.create("default", MavenPublication::class.java) { 67 | from(components.getByName("java")) 68 | } 69 | publications.create("marker", MavenPublication::class.java) { 70 | this.groupId = "com.gradleup.test" 71 | this.artifactId = "com.gradleup.test.gradle.plugin" 72 | 73 | /** 74 | * From https://github.com/gradle/gradle/blob/38930bc7f5891f3d2ca00d20ab0af22013c17f00/subprojects/plugin-development/src/main/java/org/gradle/plugin/devel/plugins/MavenPluginPublishPlugin.java#L85 75 | */ 76 | this.pom.withXml { 77 | val root: Element = asElement() 78 | val document = root.ownerDocument 79 | val dependencies = root.appendChild(document.createElement("dependencies")) 80 | val dependency = dependencies.appendChild(document.createElement("dependency")) 81 | val groupId = dependency.appendChild(document.createElement("groupId")) 82 | groupId.textContent = "com.gradleup.test" 83 | val artifactId = dependency.appendChild(document.createElement("artifactId")) 84 | artifactId.textContent = "com.gradleup.test.gradle.plugin" 85 | val version = dependency.appendChild(document.createElement("version")) 86 | version.textContent = project.version.toString() 87 | } 88 | } 89 | } 90 | 91 | 92 | -------------------------------------------------------------------------------- /test-plugin/fixtures/test-project/build.gradle.kts: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | mavenCentral() 4 | maven("../../build/localMaven") 5 | } 6 | // configurations.named("classpath").configure { 7 | // attributes { 8 | // attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.SHADOWED)) 9 | // } 10 | // } 11 | dependencies { 12 | classpath("com.gradleup.gr8.test:test-plugin:0.1") 13 | } 14 | } 15 | 16 | apply(plugin = "com.gradleup.test") -------------------------------------------------------------------------------- /test-plugin/fixtures/test-project/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GradleUp/gr8/390b4023479bad28858c48af6604967556b89ef1/test-plugin/fixtures/test-project/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /test-plugin/fixtures/test-project/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /test-plugin/fixtures/test-project/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MSYS* | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /test-plugin/fixtures/test-project/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /test-plugin/fixtures/test-project/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | } 4 | } -------------------------------------------------------------------------------- /test-plugin/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx8g -------------------------------------------------------------------------------- /test-plugin/gradle/wrapper: -------------------------------------------------------------------------------- 1 | ../../gradle/wrapper/ -------------------------------------------------------------------------------- /test-plugin/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MSYS* | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /test-plugin/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /test-plugin/rules.pro: -------------------------------------------------------------------------------- 1 | # Keep kotlin metadata so that the Kotlin compiler knows about top level functions 2 | -keep class kotlin.Metadata { *; } 3 | # Keep Unit as it's in the signature of public methods: 4 | -keep class kotlin.Unit { *; } 5 | 6 | # We need to keep type arguments (Signature) for Gradle to be able to instantiate abstract models like `Property` 7 | # Else it fails with 8 | # 'Declaration of property alwaysGenerateTypesMatching does not include any type arguments in its property type interface org.gradle.api.provider.SetProperty' 9 | -keepattributes Signature,Exceptions,*Annotation*,InnerClasses,PermittedSubclasses,EnclosingMethod,Deprecated,SourceFile,LineNumberTable 10 | 11 | # kotlin-reflect uses EnumSetOf that makes a reflexive access to "values" 12 | # https://github.com/JetBrains/kotlin/blob/0f9a413ee986f4fd80e26aed2685a1823b2b4279/core/descriptors/src/org/jetbrains/kotlin/builtins/PrimitiveType.java#L39 13 | -keepclassmembers class * extends java.lang.Enum { 14 | public static **[] values(); 15 | } 16 | 17 | # Keep everything com.gradleup.** as it's being used from Gradle 18 | -keep class com.gradleup.** { *; } 19 | 20 | # Allow to make some classes public so that we can repackage them without breaking package-private members 21 | -allowaccessmodification 22 | # Makes it easier to debug on MacOS case-insensitive filesystem when unzipping the jars 23 | -dontusemixedcaseclassnames 24 | -dontobfuscate 25 | -repackageclasses com.gradleup.relocated 26 | 27 | 28 | -------------------------------------------------------------------------------- /test-plugin/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | includeBuild("../") 3 | } 4 | 5 | apply(from = "../gradle/repositories.gradle.kts") -------------------------------------------------------------------------------- /test-plugin/src/main/kotlin/com/gradleup/test/TestPlugin.kt: -------------------------------------------------------------------------------- 1 | package com.gradleup.test 2 | 3 | import org.gradle.api.Plugin 4 | import org.gradle.api.Project 5 | 6 | class TestPlugin: Plugin { 7 | override fun apply(target: Project) { 8 | /** 9 | * A lot of the newer kotlin API like lowercase() are actually inlined. CharSequence.contentEquals is one that I found 10 | * that is not inlined 11 | */ 12 | val a: CharSequence = "" 13 | println("equals?" + a.contentEquals("")) 14 | } 15 | } -------------------------------------------------------------------------------- /test-plugin/src/main/resources/META-INF/gradle-plugins/com.gradleup.test.properties: -------------------------------------------------------------------------------- 1 | implementation-class=com.gradleup.test.TestPlugin 2 | -------------------------------------------------------------------------------- /test-plugin/src/test/kotlin/MainTests.kt: -------------------------------------------------------------------------------- 1 | import org.gradle.testkit.runner.BuildResult 2 | import org.gradle.testkit.runner.GradleRunner 3 | import org.gradle.testkit.runner.TaskOutcome 4 | import org.gradle.testkit.runner.UnexpectedBuildFailure 5 | import org.junit.Test 6 | import java.io.File 7 | import kotlin.test.assertEquals 8 | import kotlin.test.fail 9 | 10 | class MainTests { 11 | 12 | private fun runTest(block: (File) -> Unit = {}): BuildResult? { 13 | val projectDir = File("build/testProject") 14 | projectDir.deleteRecursively() 15 | File("fixtures/test-project").copyRecursively(projectDir) 16 | block(projectDir) 17 | 18 | // We need at least Gradle 6 for metadata 19 | return GradleRunner.create().withGradleVersion("6.0") 20 | .withProjectDir(projectDir) 21 | .forwardStdOutput(System.out.writer()) 22 | .forwardStdError(System.err.writer()) 23 | .withDebug(true) 24 | .withArguments("dependencies") 25 | .build() 26 | } 27 | 28 | @Test 29 | fun regularJarFails() { 30 | try { 31 | runTest() 32 | fail("A failure was expected") 33 | } catch (e: UnexpectedBuildFailure) { 34 | assert(e.message!!.contains("boolean kotlin.text.StringsKt.contentEquals(java.lang.CharSequence, java.lang.CharSequence)")) 35 | } 36 | } 37 | 38 | @Test 39 | fun gr8JarSucceeds() { 40 | val result = runTest { 41 | File(it, "build.gradle.kts").apply { 42 | // Uncomment the attribute selection 43 | writeText(readText().replace("//", "")) 44 | } 45 | } 46 | assertEquals(TaskOutcome.SUCCESS, result!!.task(":dependencies")!!.outcome) 47 | } 48 | } --------------------------------------------------------------------------------