├── .github └── workflows │ └── nebula.yml ├── .gitignore ├── .java-version ├── LICENSE ├── README.md ├── build.gradle ├── gradle.lockfile ├── gradle.properties ├── gradle ├── idea-codestyle.xml ├── idea-copyright.xml ├── idea-inspections.xml ├── idea.gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src ├── integTest └── groovy │ └── nebula │ └── plugin │ └── compile │ └── JavaCrossCompilePluginIntegrationSpec.groovy ├── main └── kotlin │ └── nebula │ └── plugin │ └── compile │ ├── JavaCrossCompileExtension.kt │ ├── JavaCrossCompilePlugin.kt │ └── provider │ ├── DefaultLocationJDKPathProvider.kt │ ├── EnvironmentJDKPathProvider.kt │ ├── JDKPathProvider.kt │ └── SDKManJDKPathProvider.kt └── test └── groovy └── nebula └── plugin └── compile └── provider └── DefaultLocationJDKPathProviderTest.groovy /.github/workflows/nebula.yml: -------------------------------------------------------------------------------- 1 | name: Nebula Build 2 | on: 3 | push: 4 | branches: 5 | - '*' 6 | tags: 7 | - v*.*.* 8 | - v*.*.*-rc.* 9 | pull_request: 10 | 11 | jobs: 12 | validation: 13 | name: "Gradle Wrapper Validation" 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v2 17 | - uses: gradle/wrapper-validation-action@v1 18 | buildmultijdk: 19 | if: (!startsWith(github.ref, 'refs/tags/v')) 20 | needs: validation 21 | runs-on: ubuntu-latest 22 | strategy: 23 | matrix: 24 | # test against latest update of some major Java version(s), as well as specific LTS version(s) 25 | java: [ 8 ] 26 | name: Gradle Build without Publish 27 | steps: 28 | - uses: actions/checkout@v1 29 | - name: Set up JDK 1.7 30 | uses: actions/setup-java@v1 31 | with: 32 | java-version: 1.7 33 | - uses: actions/checkout@v1 34 | - name: Setup jdk 35 | uses: actions/setup-java@v1 36 | with: 37 | java-version: ${{ matrix.java }} 38 | - uses: actions/cache@v1 39 | id: gradle-cache 40 | with: 41 | path: ~/.gradle/caches 42 | key: ${{ runner.os }}-gradle-${{ hashFiles('**/gradle/dependency-locks/*.lockfile') }} 43 | restore-keys: | 44 | - ${{ runner.os }}-gradle- 45 | - uses: actions/cache@v1 46 | id: gradle-wrapper-cache 47 | with: 48 | path: ~/.gradle/wrapper 49 | key: ${{ runner.os }}-gradlewrapper-${{ hashFiles('gradle/wrapper/*') }} 50 | restore-keys: | 51 | - ${{ runner.os }}-gradlewrapper- 52 | - name: Gradle build 53 | run: ./gradlew --stacktrace build --scan 54 | 55 | validatepluginpublication: 56 | if: startsWith(github.ref, 'refs/tags/v') 57 | needs: validation 58 | runs-on: ubuntu-latest 59 | name: Gradle Plugin Publication Validation 60 | env: 61 | NETFLIX_OSS_SONATYPE_USERNAME: ${{ secrets.ORG_SONATYPE_USERNAME }} 62 | NETFLIX_OSS_SONATYPE_PASSWORD: ${{ secrets.ORG_SONATYPE_PASSWORD }} 63 | steps: 64 | - uses: actions/checkout@v1 65 | - name: Setup jdk 8 66 | uses: actions/setup-java@v1 67 | with: 68 | java-version: 1.8 69 | - uses: actions/cache@v1 70 | id: gradle-cache 71 | with: 72 | path: ~/.gradle/caches 73 | key: ${{ runner.os }}-gradle-${{ hashFiles('**/gradle/dependency-locks/*.lockfile') }} 74 | restore-keys: | 75 | - ${{ runner.os }}-gradle- 76 | - uses: actions/cache@v1 77 | id: gradle-wrapper-cache 78 | with: 79 | path: ~/.gradle/wrapper 80 | key: ${{ runner.os }}-gradlewrapper-${{ hashFiles('gradle/wrapper/*') }} 81 | restore-keys: | 82 | - ${{ runner.os }}-gradlewrapper- 83 | - name: Verify plugin publication 84 | if: | 85 | startsWith(github.ref, 'refs/tags/v') && 86 | (!contains(github.ref, '-rc.')) 87 | run: ./gradlew --stacktrace -Dgradle.publish.key=${{ secrets.gradlePublishKey }} -Dgradle.publish.secret=${{ secrets.gradlePublishSecret }} -Prelease.useLastTag=true final publishPlugin --validate-only -x check -x signPluginMavenPublication 88 | publish: 89 | if: startsWith(github.ref, 'refs/tags/v') 90 | needs: validatepluginpublication 91 | runs-on: ubuntu-latest 92 | name: Gradle Build and Publish 93 | env: 94 | NETFLIX_OSS_SONATYPE_USERNAME: ${{ secrets.ORG_SONATYPE_USERNAME }} 95 | NETFLIX_OSS_SONATYPE_PASSWORD: ${{ secrets.ORG_SONATYPE_PASSWORD }} 96 | NETFLIX_OSS_SIGNING_KEY: ${{ secrets.ORG_SIGNING_KEY }} 97 | NETFLIX_OSS_SIGNING_PASSWORD: ${{ secrets.ORG_SIGNING_PASSWORD }} 98 | NETFLIX_OSS_REPO_USERNAME: ${{ secrets.ORG_NETFLIXOSS_USERNAME }} 99 | NETFLIX_OSS_REPO_PASSWORD: ${{ secrets.ORG_NETFLIXOSS_PASSWORD }} 100 | steps: 101 | - uses: actions/checkout@v1 102 | - name: Set up JDK 1.7 103 | uses: actions/setup-java@v1 104 | with: 105 | java-version: 1.7 106 | - uses: actions/checkout@v1 107 | - name: Setup jdk 8 108 | uses: actions/setup-java@v1 109 | with: 110 | java-version: 1.8 111 | - uses: actions/cache@v1 112 | id: gradle-cache 113 | with: 114 | path: ~/.gradle/caches 115 | key: ${{ runner.os }}-gradle-${{ hashFiles('**/gradle/dependency-locks/*.lockfile') }} 116 | restore-keys: | 117 | - ${{ runner.os }}-gradle- 118 | - uses: actions/cache@v1 119 | id: gradle-wrapper-cache 120 | with: 121 | path: ~/.gradle/wrapper 122 | key: ${{ runner.os }}-gradlewrapper-${{ hashFiles('gradle/wrapper/*') }} 123 | restore-keys: | 124 | - ${{ runner.os }}-gradlewrapper- 125 | - name: Publish candidate 126 | if: | 127 | startsWith(github.ref, 'refs/tags/v') && 128 | contains(github.ref, '-rc.') 129 | run: ./gradlew --info --stacktrace -Prelease.useLastTag=true candidate 130 | - name: Publish release 131 | if: | 132 | startsWith(github.ref, 'refs/tags/v') && 133 | (!contains(github.ref, '-rc.')) 134 | run: ./gradlew --info --stacktrace -Dgradle.publish.key=${{ secrets.gradlePublishKey }} -Dgradle.publish.secret=${{ secrets.gradlePublishSecret }} -Prelease.useLastTag=true final 135 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | .DS_Store 3 | generated/ 4 | out/ 5 | .gradle 6 | .idea 7 | *.ipr 8 | *.iml 9 | *.iws 10 | -------------------------------------------------------------------------------- /.java-version: -------------------------------------------------------------------------------- 1 | 1.8 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gradle Java Cross-Compile Plugin 2 | 3 | ![Support Status](https://img.shields.io/badge/nebula-unsupported-red.svg) 4 | [![Gradle Plugin Portal](https://img.shields.io/maven-metadata/v/https/plugins.gradle.org/m2/com.netflix.nebula/gradle-java-cross-compile-plugin/maven-metadata.xml.svg?label=gradlePluginPortal)](https://plugins.gradle.org/plugin/com.netflix.nebula.java-cross-compile) 5 | [![Maven Central](https://img.shields.io/maven-central/v/com.netflix.nebula/gradle-java-cross-compile-plugin)](https://maven-badges.herokuapp.com/maven-central/com.netflix.nebula/gradle-java-cross-compile-plugin) 6 | ![Build](https://github.com/nebula-plugins/gradle-java-cross-compile-plugin/actions/workflows/nebula.yml/badge.svg) 7 | [![Apache 2.0](https://img.shields.io/github/license/nebula-plugins/gradle-java-cross-compile-plugin.svg)](http://www.apache.org/licenses/LICENSE-2.0) 8 | 9 | **This plugin is no longer supported. We recommend using [Gradle Toolchains](https://docs.gradle.org/current/userguide/toolchains.html) instead** 10 | 11 | Automatically configures the bootstrap classpath when the requested `targetCompatibility` is less than the current Java version, avoiding: 12 | 13 | warning: [options] bootstrap class path not set in conjunction with -source 1.7 14 | 15 | The plugin supports Java, Groovy joint compilation, and Kotlin. The plugin locates JDKs via either: 16 | 17 | - Environment variables 18 | - In the form `JDK1x` where `x` is the major version, for instance `JDK18` for Java 8 19 | - Default installation locations for MacOS, Ubuntu and Windows 20 | - Where more than one version of the JDK is available for a given version is available, the highest is used 21 | - The lookup prefers Oracle JDKs, but falls back to OpenJDK (zulu) where possible 22 | - [SDKMAN!](http://sdkman.io/) JDK candidates 23 | - The lookup prefers JDKs with no suffix, then Oracle JDKs then OpenJDK (zulu) 24 | 25 | # Quick Start 26 | 27 | Refer to the [Gradle Plugin Portal](https://plugins.gradle.org/plugin/nebula.java-cross-compile) for instructions on how to apply the plugin. 28 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 Netflix, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | plugins { 19 | id 'com.netflix.nebula.plugin-plugin' version '20.8.1' 20 | id "org.jetbrains.kotlin.jvm" version "1.8.0" 21 | } 22 | 23 | apply from: 'gradle/idea.gradle' 24 | 25 | def kotlinVersion = '1.8.0' 26 | 27 | 28 | dependencies { 29 | implementation 'com.netflix.nebula:nebula-gradle-interop:latest.release' 30 | compileOnly "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}" 31 | compileOnly "org.jetbrains.kotlin:kotlin-compiler-embeddable:${kotlinVersion}" 32 | compileOnly "org.jetbrains.kotlin:kotlin-annotation-processing-gradle:${kotlinVersion}" 33 | compileOnly "org.jetbrains.kotlin:kotlin-android-extensions:${kotlinVersion}" 34 | compileOnly "org.jetbrains.kotlin:kotlin-compiler-runner:${kotlinVersion}" 35 | compileOnly "org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}" 36 | testImplementation "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}" 37 | } 38 | 39 | description 'Gradle Java Cross-Compile Plugin' 40 | 41 | contacts { 42 | 'nebula-plugins-oss@netflix.com' { 43 | moniker 'Nebula Plugins Maintainers' 44 | github 'nebula-plugins' 45 | } 46 | } 47 | 48 | 49 | gradlePlugin { 50 | plugins { 51 | javaCrossCompile { 52 | id = 'com.netflix.nebula.java-cross-compile' 53 | displayName = 'Gradle Java Cross-Compile Plugin' 54 | description = project.description 55 | implementationClass = 'nebula.plugin.compile.JavaCrossCompilePlugin' 56 | tags.set(['nebula', 'compile', 'java', 'groovy', 'kotlin']) 57 | } 58 | } 59 | } 60 | 61 | javaCrossCompile { 62 | disableKotlinSupport = true 63 | } 64 | 65 | -------------------------------------------------------------------------------- /gradle.lockfile: -------------------------------------------------------------------------------- 1 | # This is a Gradle generated file for dependency locking. 2 | # Manual edits can break the build and are not advised. 3 | # This file is expected to be part of source control. 4 | cglib:cglib-nodep:3.2.2=integTestRuntimeClasspath,testRuntimeClasspath 5 | com.netflix.nebula:nebula-gradle-interop:2.1.1=compileClasspath,integTestCompileClasspath,integTestRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath 6 | com.netflix.nebula:nebula-test:10.5.0=integTestCompileClasspath,integTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath 7 | junit:junit:4.13.2=integTestCompileClasspath,integTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath 8 | net.java.dev.jna:jna:5.6.0=integTestRuntimeClasspath,testRuntimeClasspath 9 | org.apiguardian:apiguardian-api:1.1.2=integTestCompileClasspath,integTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath 10 | org.codehaus.groovy:groovy:3.0.12=integTestCompileClasspath,integTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath 11 | org.hamcrest:hamcrest-core:1.3=integTestCompileClasspath,integTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath 12 | org.hamcrest:hamcrest:2.2=integTestCompileClasspath,integTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath 13 | org.jetbrains.intellij.deps:trove4j:1.0.20200330=integTestRuntimeClasspath,testRuntimeClasspath 14 | org.jetbrains.kotlin:kotlin-android-extensions:1.8.0=compileClasspath,integTestRuntimeClasspath,testRuntimeClasspath 15 | org.jetbrains.kotlin:kotlin-annotation-processing-gradle:1.8.0=compileClasspath,integTestRuntimeClasspath,testRuntimeClasspath 16 | org.jetbrains.kotlin:kotlin-build-common:1.8.0=compileClasspath,integTestRuntimeClasspath,testRuntimeClasspath 17 | org.jetbrains.kotlin:kotlin-compiler-embeddable:1.8.0=compileClasspath,integTestRuntimeClasspath,testRuntimeClasspath 18 | org.jetbrains.kotlin:kotlin-compiler-runner:1.8.0=compileClasspath,integTestRuntimeClasspath,testRuntimeClasspath 19 | org.jetbrains.kotlin:kotlin-daemon-client:1.8.0=compileClasspath,integTestRuntimeClasspath,testRuntimeClasspath 20 | org.jetbrains.kotlin:kotlin-daemon-embeddable:1.8.0=integTestRuntimeClasspath,testRuntimeClasspath 21 | org.jetbrains.kotlin:kotlin-gradle-plugin-idea-proto:1.8.0=integTestRuntimeClasspath,testRuntimeClasspath 22 | org.jetbrains.kotlin:kotlin-gradle-plugin-idea:1.8.0=integTestRuntimeClasspath,testRuntimeClasspath 23 | org.jetbrains.kotlin:kotlin-gradle-plugin-model:1.8.0=compileClasspath,integTestCompileClasspath,integTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath 24 | org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0=compileClasspath,integTestCompileClasspath,integTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath 25 | org.jetbrains.kotlin:kotlin-klib-commonizer-api:1.8.0=integTestRuntimeClasspath,testRuntimeClasspath 26 | org.jetbrains.kotlin:kotlin-native-utils:1.8.0=integTestRuntimeClasspath,testRuntimeClasspath 27 | org.jetbrains.kotlin:kotlin-project-model:1.8.0=integTestRuntimeClasspath,testRuntimeClasspath 28 | org.jetbrains.kotlin:kotlin-reflect:1.8.0=compileClasspath 29 | org.jetbrains.kotlin:kotlin-scripting-common:1.8.0=integTestRuntimeClasspath,testRuntimeClasspath 30 | org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.8.0=integTestRuntimeClasspath,testRuntimeClasspath 31 | org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.8.0=integTestRuntimeClasspath,testRuntimeClasspath 32 | org.jetbrains.kotlin:kotlin-scripting-jvm:1.8.0=integTestRuntimeClasspath,testRuntimeClasspath 33 | org.jetbrains.kotlin:kotlin-stdlib-common:1.8.0=compileClasspath,integTestCompileClasspath,integTestRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath 34 | org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0=compileClasspath,integTestCompileClasspath,integTestRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath 35 | org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0=compileClasspath,integTestCompileClasspath,integTestRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath 36 | org.jetbrains.kotlin:kotlin-stdlib:1.8.0=compileClasspath,integTestCompileClasspath,integTestRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath 37 | org.jetbrains.kotlin:kotlin-tooling-core:1.8.0=compileClasspath,integTestCompileClasspath,integTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath 38 | org.jetbrains.kotlin:kotlin-util-io:1.8.0=integTestRuntimeClasspath,testRuntimeClasspath 39 | org.jetbrains.kotlin:kotlin-util-klib:1.8.0=integTestRuntimeClasspath,testRuntimeClasspath 40 | org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.5.0=compileClasspath,integTestRuntimeClasspath,testRuntimeClasspath 41 | org.jetbrains:annotations:13.0=compileClasspath,integTestCompileClasspath,integTestRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath 42 | org.junit.platform:junit-platform-commons:1.9.0=integTestCompileClasspath,integTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath 43 | org.junit.platform:junit-platform-engine:1.9.0=integTestCompileClasspath,integTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath 44 | org.objenesis:objenesis:2.4=integTestRuntimeClasspath,testRuntimeClasspath 45 | org.opentest4j:opentest4j:1.2.0=integTestCompileClasspath,integTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath 46 | org.spockframework:spock-core:2.3-groovy-3.0=integTestCompileClasspath,integTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath 47 | org.spockframework:spock-junit4:2.3-groovy-3.0=integTestCompileClasspath,integTestRuntimeClasspath,testCompileClasspath,testRuntimeClasspath 48 | empty=annotationProcessor,compile,integTestAnnotationProcessor,integTestCompile,integTestRuntime,runtime,testAnnotationProcessor,testCompile,testRuntime 49 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | systemProp.nebula.features.coreLockingSupport=true 2 | -------------------------------------------------------------------------------- /gradle/idea-codestyle.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 251 | 253 | -------------------------------------------------------------------------------- /gradle/idea-copyright.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /gradle/idea-inspections.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 21 | 32 | 33 | 37 | -------------------------------------------------------------------------------- /gradle/idea.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Netflix, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | idea { 19 | project { 20 | def javaTarget = '1.7' 21 | jdkName = javaTarget 22 | languageLevel = javaTarget 23 | 24 | wildcards += 'logback.groovy' 25 | 26 | ipr { 27 | withXml { provider -> 28 | def node = provider.asNode() 29 | 30 | // Code styles 31 | def codestyle = new XmlParser().parse(file('gradle/idea-codestyle.xml')) 32 | node.append(codestyle) 33 | 34 | // Inspections 35 | def inspections = new XmlParser().parse(file('gradle/idea-inspections.xml')) 36 | node.append(inspections) 37 | 38 | // Copyright 39 | def copyrightManager = node.component.find { it.'@name' == 'CopyrightManager' } 40 | node.remove(copyrightManager) 41 | def copyright = new XmlParser().parse(file('gradle/idea-copyright.xml')) 42 | node.append(copyright) 43 | 44 | // VCS mappings 45 | def vcsDirectoryMappings = node.component.find { it.'@name' == 'VcsDirectoryMappings' } 46 | def mappings = vcsDirectoryMappings.iterator() 47 | while (mappings.hasNext()) { 48 | mappings.next() 49 | mappings.remove() 50 | } 51 | 52 | def gitRoot = file('.git') 53 | if (gitRoot.exists()) { 54 | vcsDirectoryMappings.appendNode('mapping', ['directory': gitRoot.parentFile, 'vcs': 'Git']) 55 | } 56 | 57 | // Annotation processing 58 | node.component.find { it.@name == 'CompilerConfiguration' }['annotationProcessing'][0].replaceNode { 59 | annotationProcessing { 60 | profile(default: true, name: 'Default', useClasspath: 'true', enabled: true) { 61 | outputRelativeToContentRoot(value: true) 62 | processorPath(useClasspath: true) 63 | } 64 | } 65 | } 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nebula-plugins/gradle-java-cross-compile-plugin/0b54d5a65e7b56141da80394b1fd5b7a48f4ad72/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.3-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original 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 POSIX generated by Gradle. 22 | # 23 | # Important for running: 24 | # 25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 26 | # noncompliant, but you have some other compliant shell such as ksh or 27 | # bash, then to run this script, type that shell name before the whole 28 | # command line, like: 29 | # 30 | # ksh Gradle 31 | # 32 | # Busybox and similar reduced shells will NOT work, because this script 33 | # requires all of these POSIX shell features: 34 | # * functions; 35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 37 | # * compound commands having a testable exit status, especially «case»; 38 | # * various built-in commands including «command», «set», and «ulimit». 39 | # 40 | # Important for patching: 41 | # 42 | # (2) This script targets any POSIX shell, so it avoids extensions provided 43 | # by Bash, Ksh, etc; in particular arrays are avoided. 44 | # 45 | # The "traditional" practice of packing multiple parameters into a 46 | # space-separated string is a well documented source of bugs and security 47 | # problems, so this is (mostly) avoided, by progressively accumulating 48 | # options in "$@", and eventually passing that to Java. 49 | # 50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 52 | # see the in-line comments for details. 53 | # 54 | # There are tweaks for specific operating systems such as AIX, CygWin, 55 | # Darwin, MinGW, and NonStop. 56 | # 57 | # (3) This script is generated from the Groovy template 58 | # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 59 | # within the Gradle project. 60 | # 61 | # You can find Gradle at https://github.com/gradle/gradle/. 62 | # 63 | ############################################################################## 64 | 65 | # Attempt to set APP_HOME 66 | 67 | # Resolve links: $0 may be a link 68 | app_path=$0 69 | 70 | # Need this for daisy-chained symlinks. 71 | while 72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 73 | [ -h "$app_path" ] 74 | do 75 | ls=$( ls -ld "$app_path" ) 76 | link=${ls#*' -> '} 77 | case $link in #( 78 | /*) app_path=$link ;; #( 79 | *) app_path=$APP_HOME$link ;; 80 | esac 81 | done 82 | 83 | # This is normally unused 84 | # shellcheck disable=SC2034 85 | APP_BASE_NAME=${0##*/} 86 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit 87 | 88 | # Use the maximum available, or set MAX_FD != -1 to use that value. 89 | MAX_FD=maximum 90 | 91 | warn () { 92 | echo "$*" 93 | } >&2 94 | 95 | die () { 96 | echo 97 | echo "$*" 98 | echo 99 | exit 1 100 | } >&2 101 | 102 | # OS specific support (must be 'true' or 'false'). 103 | cygwin=false 104 | msys=false 105 | darwin=false 106 | nonstop=false 107 | case "$( uname )" in #( 108 | CYGWIN* ) cygwin=true ;; #( 109 | Darwin* ) darwin=true ;; #( 110 | MSYS* | MINGW* ) msys=true ;; #( 111 | NONSTOP* ) nonstop=true ;; 112 | esac 113 | 114 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 115 | 116 | 117 | # Determine the Java command to use to start the JVM. 118 | if [ -n "$JAVA_HOME" ] ; then 119 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 120 | # IBM's JDK on AIX uses strange locations for the executables 121 | JAVACMD=$JAVA_HOME/jre/sh/java 122 | else 123 | JAVACMD=$JAVA_HOME/bin/java 124 | fi 125 | if [ ! -x "$JAVACMD" ] ; then 126 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 127 | 128 | Please set the JAVA_HOME variable in your environment to match the 129 | location of your Java installation." 130 | fi 131 | else 132 | JAVACMD=java 133 | if ! command -v java >/dev/null 2>&1 134 | then 135 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 136 | 137 | Please set the JAVA_HOME variable in your environment to match the 138 | location of your Java installation." 139 | fi 140 | fi 141 | 142 | # Increase the maximum file descriptors if we can. 143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 144 | case $MAX_FD in #( 145 | max*) 146 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 147 | # shellcheck disable=SC3045 148 | MAX_FD=$( ulimit -H -n ) || 149 | warn "Could not query maximum file descriptor limit" 150 | esac 151 | case $MAX_FD in #( 152 | '' | soft) :;; #( 153 | *) 154 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 155 | # shellcheck disable=SC3045 156 | ulimit -n "$MAX_FD" || 157 | warn "Could not set maximum file descriptor limit to $MAX_FD" 158 | esac 159 | fi 160 | 161 | # Collect all arguments for the java command, stacking in reverse order: 162 | # * args from the command line 163 | # * the main class name 164 | # * -classpath 165 | # * -D...appname settings 166 | # * --module-path (only if needed) 167 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 168 | 169 | # For Cygwin or MSYS, switch paths to Windows format before running java 170 | if "$cygwin" || "$msys" ; then 171 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 172 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 173 | 174 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 175 | 176 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 177 | for arg do 178 | if 179 | case $arg in #( 180 | -*) false ;; # don't mess with options #( 181 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 182 | [ -e "$t" ] ;; #( 183 | *) false ;; 184 | esac 185 | then 186 | arg=$( cygpath --path --ignore --mixed "$arg" ) 187 | fi 188 | # Roll the args list around exactly as many times as the number of 189 | # args, so each arg winds up back in the position where it started, but 190 | # possibly modified. 191 | # 192 | # NB: a `for` loop captures its iteration list before it begins, so 193 | # changing the positional parameters here affects neither the number of 194 | # iterations, nor the values presented in `arg`. 195 | shift # remove old arg 196 | set -- "$@" "$arg" # push replacement arg 197 | done 198 | fi 199 | 200 | 201 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 202 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 203 | 204 | # Collect all arguments for the java command; 205 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of 206 | # shell script including quotes and variable substitutions, so put them in 207 | # double quotes to make sure that they get re-expanded; and 208 | # * put everything else in single quotes, so that it's not re-expanded. 209 | 210 | set -- \ 211 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 212 | -classpath "$CLASSPATH" \ 213 | org.gradle.wrapper.GradleWrapperMain \ 214 | "$@" 215 | 216 | # Stop when "xargs" is not available. 217 | if ! command -v xargs >/dev/null 2>&1 218 | then 219 | die "xargs is not available" 220 | fi 221 | 222 | # Use "xargs" to parse quoted args. 223 | # 224 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 225 | # 226 | # In Bash we could simply go: 227 | # 228 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 229 | # set -- "${ARGS[@]}" "$@" 230 | # 231 | # but POSIX shell has neither arrays nor command substitution, so instead we 232 | # post-process each arg (as a line of input to sed) to backslash-escape any 233 | # character that might be a shell metacharacter, then use eval to reverse 234 | # that process (while maintaining the separation between arguments), and wrap 235 | # the whole thing up as a single "set" statement. 236 | # 237 | # This will of course break if any of these variables contains a newline or 238 | # an unmatched quote. 239 | # 240 | 241 | eval "set -- $( 242 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 243 | xargs -n1 | 244 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 245 | tr '\n' ' ' 246 | )" '"$@"' 247 | 248 | exec "$JAVACMD" "$@" 249 | -------------------------------------------------------------------------------- /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 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.gradle.enterprise' version '3.8.1' 3 | } 4 | 5 | gradleEnterprise { 6 | buildScan { 7 | publishAlways() 8 | termsOfServiceUrl = 'https://gradle.com/terms-of-service' 9 | termsOfServiceAgree = 'yes' 10 | } 11 | } 12 | 13 | rootProject.name = 'gradle-java-cross-compile-plugin' 14 | -------------------------------------------------------------------------------- /src/integTest/groovy/nebula/plugin/compile/JavaCrossCompilePluginIntegrationSpec.groovy: -------------------------------------------------------------------------------- 1 | package nebula.plugin.compile 2 | 3 | import nebula.test.IntegrationSpec 4 | import org.gradle.api.JavaVersion 5 | import org.junit.Assume 6 | import spock.lang.Unroll 7 | 8 | class JavaCrossCompilePluginIntegrationSpec extends IntegrationSpec { 9 | def 'plugin applies'() { 10 | buildFile << """\ 11 | apply plugin: 'com.netflix.nebula.java-cross-compile' 12 | """ 13 | 14 | when: 15 | runTasksSuccessfully('help') 16 | 17 | then: 18 | noExceptionThrown() 19 | } 20 | 21 | @Unroll 22 | def 'sourceCompatibility set to #sourceCompatibility'(Double sourceCompatibility) { 23 | buildFile << """\ 24 | apply plugin: 'com.netflix.nebula.java-cross-compile' 25 | apply plugin: 'java' 26 | 27 | java { 28 | sourceCompatibility = $sourceCompatibility 29 | } 30 | """ 31 | 32 | when: 33 | def result = runTasks('help') 34 | 35 | then: 36 | println result.standardOutput 37 | println result.standardError 38 | result.rethrowFailure() 39 | 40 | where: 41 | sourceCompatibility | _ 42 | // 1.7 | _ 43 | 1.8 | _ 44 | } 45 | 46 | def 'missing jdk throws exception'() { 47 | Assume.assumeTrue(JavaVersion.current() < JavaVersion.VERSION_1_9) 48 | 49 | buildFile << """\ 50 | apply plugin: 'com.netflix.nebula.java-cross-compile' 51 | apply plugin: 'java' 52 | 53 | java { 54 | sourceCompatibility = 1.4 55 | } 56 | """ 57 | 58 | when: 59 | def result = runTasks('help') 60 | 61 | then: 62 | def failure = result.failure 63 | failure != null 64 | failure.cause.cause.message == 'Could not locate a compatible JDK for target compatibility 1.4. Change the source/target compatibility, set a JDK_14 environment variable with the location, or install to one of the default search locations' 65 | } 66 | 67 | @Unroll 68 | def 'java compilation does not warn about bootstrap class path (gradle #gradle)'() { 69 | buildFile << """\ 70 | apply plugin: 'com.netflix.nebula.java-cross-compile' 71 | apply plugin: 'java' 72 | 73 | java { 74 | sourceCompatibility = 1.7 75 | } 76 | """ 77 | if (gradle != 'current') { 78 | gradleVersion = gradle 79 | } 80 | 81 | writeHelloWorld('helloworld') 82 | 83 | when: 84 | def result = runTasks('compileJava') 85 | 86 | then: 87 | !result.standardError.contains("warning: [options] bootstrap class path not set in conjunction with -source 1.7") 88 | 89 | where: 90 | gradle | _ 91 | '6.7' | _ 92 | '6.8' | _ 93 | '6.9' | _ 94 | '7.4' | _ 95 | //'current' | _ 96 | } 97 | 98 | def 'kotlin cross compile can be disabled'() { 99 | Assume.assumeTrue(JavaVersion.current() >= JavaVersion.VERSION_1_9) 100 | buildFile << """\ 101 | buildscript { 102 | repositories { 103 | mavenCentral() 104 | } 105 | 106 | dependencies { 107 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.50" 108 | } 109 | } 110 | 111 | apply plugin: 'com.netflix.nebula.java-cross-compile' 112 | apply plugin: 'kotlin' 113 | 114 | javaCrossCompile { 115 | disableKotlinSupport = true 116 | } 117 | 118 | java { 119 | sourceCompatibility = 1.8 120 | } 121 | """ 122 | 123 | expect: 124 | def result = runTasksSuccessfully('help', '--warning-mode', 'none') 125 | } 126 | 127 | 128 | def 'Do not apply opinions if using Java Toolchains'() { 129 | buildFile << """\ 130 | apply plugin: 'com.netflix.nebula.java-cross-compile' 131 | apply plugin: 'java' 132 | 133 | 134 | java { 135 | toolchain { 136 | languageVersion = JavaLanguageVersion.of(8) 137 | } 138 | } 139 | 140 | """ 141 | 142 | writeHelloWorld('helloworld') 143 | 144 | when: 145 | def result = runTasks('compileJava', '-d') 146 | 147 | then: 148 | result.standardOutput.contains("Toolchain is configured for this project, skipping java-cross-compile plugin configuration") 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/main/kotlin/nebula/plugin/compile/JavaCrossCompileExtension.kt: -------------------------------------------------------------------------------- 1 | package nebula.plugin.compile 2 | 3 | open class JavaCrossCompileExtension { 4 | var enabled: Boolean = true 5 | var disableKotlinSupport: Boolean = false 6 | } -------------------------------------------------------------------------------- /src/main/kotlin/nebula/plugin/compile/JavaCrossCompilePlugin.kt: -------------------------------------------------------------------------------- 1 | package nebula.plugin.compile 2 | 3 | import com.netflix.nebula.interop.versionGreaterThan 4 | import com.netflix.nebula.interop.versionLessThan 5 | import nebula.plugin.compile.provider.DefaultLocationJDKPathProvider 6 | import nebula.plugin.compile.provider.EnvironmentJDKPathProvider 7 | import nebula.plugin.compile.provider.JDKPathProvider 8 | import nebula.plugin.compile.provider.SDKManJDKPathProvider 9 | import org.gradle.api.JavaVersion 10 | import org.gradle.api.Plugin 11 | import org.gradle.api.Project 12 | import org.gradle.api.file.FileCollection 13 | import org.gradle.api.plugins.JavaBasePlugin 14 | import org.gradle.api.plugins.JavaPluginExtension 15 | import org.gradle.api.provider.ProviderFactory 16 | import org.gradle.api.tasks.compile.JavaCompile 17 | import org.gradle.jvm.toolchain.internal.DefaultToolchainSpec 18 | import org.slf4j.Logger 19 | import org.slf4j.LoggerFactory 20 | import java.io.File 21 | import javax.inject.Inject 22 | 23 | class JavaCrossCompilePlugin @Inject constructor(private val providerFactory: ProviderFactory) : Plugin { 24 | companion object { 25 | const val RT_JAR_PATH = "jre/lib/rt.jar" 26 | const val CLASSES_JAR_PATH = "../Classes/classes.jar" 27 | val ADDITIONAL_JARS = listOf("jsse", "jce", "charsets") 28 | 29 | val logger: Logger = LoggerFactory.getLogger(JavaCrossCompilePlugin::class.java) 30 | } 31 | override fun apply(project: Project) { 32 | val providers = listOf(EnvironmentJDKPathProvider(providerFactory, project), DefaultLocationJDKPathProvider(), SDKManJDKPathProvider(providerFactory, project)) 33 | val extension = project.extensions.create("javaCrossCompile", JavaCrossCompileExtension::class.java) 34 | project.plugins.apply(JavaBasePlugin::class.java) 35 | project.afterEvaluate { 36 | configureBootstrapClasspath(project, providers, extension) 37 | } 38 | } 39 | 40 | private fun configureBootstrapClasspath(project: Project, providers: List, extension: JavaCrossCompileExtension) { 41 | if (!extension.enabled) { 42 | return 43 | } 44 | // Do not configure project if toolchains are used 45 | val javaPluginExtension = project.extensions.findByType(JavaPluginExtension::class.java) 46 | if(javaPluginExtension == null) { 47 | return 48 | } 49 | val toolchain = javaPluginExtension.toolchain 50 | if((toolchain as DefaultToolchainSpec).isConfigured) { 51 | project.logger.debug("Toolchain is configured for this project, skipping java-cross-compile plugin configuration") 52 | return 53 | } 54 | val targetCompatibility = javaPluginExtension.targetCompatibility 55 | if (targetCompatibility < JavaVersion.current()) { 56 | with(project.tasks) { 57 | val location by lazy { targetCompatibility.locate(project, providers) } 58 | withType(JavaCompile::class.java) { 59 | if (JavaVersion.current() >= JavaVersion.VERSION_1_9) { 60 | if (project.gradle.versionLessThan("6.6-rc-1")) { 61 | it.options.compilerArgs.addAll(listOf("--release", targetCompatibility.majorVersion)) 62 | } else { 63 | it.options.release.set(targetCompatibility.majorVersion.toInt()) 64 | } 65 | } else { 66 | if (project.gradle.versionGreaterThan("4.2.1")) { 67 | it.options.bootstrapClasspath = location.bootstrapClasspath 68 | } else { 69 | it.options.javaClass.getDeclaredMethod("setBootClasspath", String::class.java).invoke(it.options, location.bootClasspath) 70 | } 71 | } 72 | } 73 | } 74 | } 75 | } 76 | 77 | private fun JavaVersion.locate(project: Project, providers: List): JavaLocation { 78 | logger.debug("Locating JDK for $this") 79 | val jdkHome = providers 80 | .firstNotNullOfOrNull { 81 | val jdkHome = it.provide(this) 82 | if (jdkHome == null) { 83 | logger.debug("Provider $it did not find a JDK") 84 | null 85 | } else { 86 | logger.debug("Provider $it found a JDK at $jdkHome") 87 | jdkHome 88 | } 89 | } ?: throw cannotLocate() 90 | logger.debug("Found JDK for $this at $jdkHome") 91 | val runtimeJars = listOf( 92 | File(jdkHome, RT_JAR_PATH), 93 | File(jdkHome, CLASSES_JAR_PATH) 94 | ) 95 | val runtimeJar = runtimeJars 96 | .firstNotNullOfOrNull { 97 | if (it.exists()) { 98 | logger.debug("Found runtime classes jar $it") 99 | it 100 | } else { 101 | logger.debug("Runtime classes jar $it does not exist") 102 | null 103 | } 104 | } ?: throw cannotLocate() 105 | val libDir = runtimeJar.parentFile 106 | val jarFiles = listOf(runtimeJar) + ADDITIONAL_JARS.map { File(libDir, "$it.jar") } 107 | val classpath = jarFiles.joinToString(File.pathSeparator) 108 | return JavaLocation(jdkHome, project.files(classpath)) 109 | } 110 | 111 | private fun JavaVersion.cannotLocate(): IllegalStateException = IllegalStateException("Could not locate a compatible JDK for target compatibility $this. Change the source/target compatibility, set a JDK_1$majorVersion environment variable with the location, or install to one of the default search locations") 112 | 113 | data class JavaLocation(val jdkHome: String, val bootstrapClasspath: FileCollection) { 114 | val bootClasspath: String 115 | get() = bootstrapClasspath.joinToString(File.pathSeparator) 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/main/kotlin/nebula/plugin/compile/provider/DefaultLocationJDKPathProvider.kt: -------------------------------------------------------------------------------- 1 | package nebula.plugin.compile.provider 2 | 3 | import org.gradle.api.JavaVersion 4 | import org.slf4j.Logger 5 | import org.slf4j.LoggerFactory 6 | import java.io.File 7 | import java.io.FileFilter 8 | 9 | /** 10 | * Provide JDK path from known default installation locations. 11 | */ 12 | class DefaultLocationJDKPathProvider : JDKPathProvider { 13 | companion object { 14 | val logger: Logger = LoggerFactory.getLogger(DefaultLocationJDKPathProvider::class.java) 15 | var basePaths = listOf( 16 | File("/usr/lib/jvm"), 17 | File("/opt/hostedtoolcache"), 18 | File("/Library/Java/JavaVirtualMachines"), 19 | File("""C:\Program Files\Java""") 20 | ) 21 | } 22 | 23 | override fun provide(javaVersion: JavaVersion): String? { 24 | val candidates = basePaths.flatMap { 25 | it.listFiles(FileFilter { it.isDirectory })?.toList() ?: emptyList() 26 | }.reversed() 27 | 28 | if (candidates.isEmpty()) { 29 | logger.debug("No candidates were found in search locations $basePaths") 30 | return null 31 | } 32 | 33 | listOf("oracle", "openjdk").forEach { variant -> 34 | val jdkHome = candidates.firstOrNull { 35 | logger.debug("Evaluating Ubuntu candidate ${it.name}") 36 | it.name.startsWith("java-${javaVersion.majorVersion}-$variant") 37 | } 38 | if (jdkHome != null) { 39 | logger.debug("Found Ubuntu JDK at $jdkHome") 40 | return jdkHome.absolutePath 41 | } 42 | } 43 | 44 | listOf("jdk", "jre", "jdk+fx").forEach { javaPackage -> 45 | val candidatesForJavaPackage = candidates.firstOrNull { 46 | logger.debug("Evaluating Github Actions java-package candidate ${it.name}") 47 | it.name.startsWith(javaPackage) 48 | }?.listFiles(FileFilter { it.isDirectory })?.toList() ?: emptyList() 49 | 50 | val candidatesForJavaVersion = candidatesForJavaPackage.firstOrNull { 51 | logger.debug("Evaluating Github Actions java-version candidate ${it.name}") 52 | it.name.startsWith("${javaVersion.majorVersion}.") 53 | }?.listFiles(FileFilter { it.isDirectory })?.toList() ?: emptyList() 54 | 55 | listOf("x64", "x86").forEach { architecture -> 56 | val jdkHomeWithGithubActions = candidatesForJavaVersion.firstOrNull { 57 | logger.debug("Evaluating Github Actions architecture candidate ${it.name}") 58 | it.name.startsWith(architecture) 59 | } 60 | if (jdkHomeWithGithubActions != null) { 61 | logger.debug("Found Github Actions JDK at $jdkHomeWithGithubActions") 62 | return jdkHomeWithGithubActions.absolutePath 63 | } 64 | } 65 | } 66 | 67 | val jdkHome = candidates.firstOrNull { 68 | logger.debug("Evaluating macOS/Windows candidate ${it.name}") 69 | val version = "1.${javaVersion.majorVersion}.0" 70 | val name = it.name 71 | listOf( 72 | "jdk$version", 73 | "jdk-$version", 74 | "$version.jdk", 75 | "zulu$version", 76 | "zulu-${javaVersion.majorVersion}.jdk" 77 | ).any { name.startsWith(it) } 78 | } 79 | 80 | if (jdkHome != null) { 81 | val macOsJdkHome = File(jdkHome, "Contents/Home") 82 | if (macOsJdkHome.exists()) { 83 | logger.debug("Found macOS JDK at $jdkHome") 84 | return macOsJdkHome.absolutePath 85 | } 86 | } 87 | 88 | if (jdkHome == null) { 89 | logger.debug("No JDKs found in candidate locations $candidates ") 90 | return null 91 | } 92 | return jdkHome.absolutePath 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/kotlin/nebula/plugin/compile/provider/EnvironmentJDKPathProvider.kt: -------------------------------------------------------------------------------- 1 | package nebula.plugin.compile.provider 2 | 3 | import com.netflix.nebula.interop.versionLessThan 4 | import org.gradle.api.JavaVersion 5 | import org.gradle.api.Project 6 | import org.gradle.api.provider.ProviderFactory 7 | 8 | /** 9 | * Provide JDK path from environment variables. 10 | */ 11 | class EnvironmentJDKPathProvider constructor(private val providerFactory: ProviderFactory, private val project: Project) : JDKPathProvider { 12 | override fun provide(javaVersion: JavaVersion): String? { 13 | return if(project.gradle.versionLessThan("6.5")) { 14 | val jdkEnvVariable = providerFactory.environmentVariable("JDK_1${javaVersion.majorVersion}").forUseAtConfigurationTime() 15 | if(jdkEnvVariable.isPresent) jdkEnvVariable.get() else null 16 | } else { 17 | System.getenv("JDK_1${javaVersion.majorVersion}") 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/kotlin/nebula/plugin/compile/provider/JDKPathProvider.kt: -------------------------------------------------------------------------------- 1 | package nebula.plugin.compile.provider 2 | 3 | import org.gradle.api.JavaVersion 4 | 5 | interface JDKPathProvider { 6 | fun provide(javaVersion: JavaVersion): String? 7 | } -------------------------------------------------------------------------------- /src/main/kotlin/nebula/plugin/compile/provider/SDKManJDKPathProvider.kt: -------------------------------------------------------------------------------- 1 | package nebula.plugin.compile.provider 2 | 3 | import com.netflix.nebula.interop.versionLessThan 4 | import org.gradle.api.JavaVersion 5 | import org.gradle.api.Project 6 | import org.gradle.api.provider.ProviderFactory 7 | import org.slf4j.Logger 8 | import org.slf4j.LoggerFactory 9 | import java.io.File 10 | import java.io.FileFilter 11 | 12 | /** 13 | * Provide JDK path from SDKMan candidates. 14 | */ 15 | class SDKManJDKPathProvider constructor(private val providerFactory: ProviderFactory, private val project: Project): JDKPathProvider { 16 | companion object { 17 | const val SDKMAN_JAVA_CANDIDATES = ".sdkman/candidates/java" 18 | 19 | val logger: Logger = LoggerFactory.getLogger(SDKManJDKPathProvider::class.java) 20 | } 21 | 22 | override fun provide(javaVersion: JavaVersion): String? { 23 | 24 | val userHome = if(project.gradle.versionLessThan("6.5")) System.getProperty("user.home") else providerFactory.systemProperty("user.home").forUseAtConfigurationTime().get() 25 | val javaCandidates = File(userHome, SDKMAN_JAVA_CANDIDATES) 26 | val candidates = javaCandidates.listFiles(FileFilter { it.isDirectory })?.reversed() ?: emptyList() 27 | 28 | if (candidates.isEmpty()) { 29 | logger.debug("No candidates were found in $javaCandidates") 30 | return null 31 | } 32 | 33 | listOf("", "oracle", "zulu").forEach { variant -> 34 | val jdkHome = candidates.firstOrNull { 35 | logger.debug("Evaluating SDKMan candidate ${it.name}") 36 | isRightVersion(it.name, javaVersion) && (variant.isEmpty() || it.name.endsWith(variant)) 37 | } 38 | if (jdkHome != null) { 39 | logger.debug("Found SDKMan provided JDK at $jdkHome") 40 | return jdkHome.absolutePath 41 | } 42 | } 43 | 44 | logger.debug("No JDKs found in candidate locations $candidates") 45 | return null 46 | } 47 | 48 | private fun isRightVersion(name: String, javaVersion: JavaVersion): Boolean = 49 | name.startsWith("${javaVersion.majorVersion}u") || name.startsWith("${javaVersion.majorVersion}.") 50 | } 51 | -------------------------------------------------------------------------------- /src/test/groovy/nebula/plugin/compile/provider/DefaultLocationJDKPathProviderTest.groovy: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Copyright 2019 Netflix, Inc. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | package nebula.plugin.compile.provider 20 | 21 | import nebula.test.ProjectSpec 22 | import org.gradle.api.JavaVersion 23 | import spock.lang.Subject 24 | import spock.lang.Unroll 25 | 26 | @Subject(DefaultLocationJDKPathProvider) 27 | class DefaultLocationJDKPathProviderTest extends ProjectSpec { 28 | List updatedBasePaths = new ArrayList() 29 | ObjectGraphBuilder builder 30 | 31 | def setup() { 32 | // setup to update read-only property 33 | builder = new ObjectGraphBuilder() 34 | builder.classLoader = this.class.classLoader 35 | builder.classNameResolver = "nebula.plugin.compile.provider" 36 | } 37 | 38 | def 'provides JDK from Ubuntu style location'() { 39 | given: 40 | File sampleUbuntuJDKPath = new File(project.projectDir, "java-8-openjdk") 41 | sampleUbuntuJDKPath.mkdirs() 42 | updatedBasePaths.add(project.projectDir) 43 | 44 | def provider = builder.defaultLocationJDKPathProvider(basePaths: updatedBasePaths) // update read-only property 45 | 46 | when: 47 | def actualJdkPath = provider.provide(JavaVersion.VERSION_1_8) 48 | def expectedPath = sampleUbuntuJDKPath.path 49 | 50 | then: 51 | assert actualJdkPath == expectedPath 52 | } 53 | 54 | def 'provides JDK from OSX style location'() { 55 | given: 56 | File sampleOSXJDKPath = new File(project.projectDir, "zulu1.8.0_181.jdk/Contents/Home") 57 | sampleOSXJDKPath.mkdirs() 58 | updatedBasePaths.add(project.projectDir) 59 | 60 | def provider = builder.defaultLocationJDKPathProvider(basePaths: updatedBasePaths) // update read-only property 61 | 62 | when: 63 | def actualJdkPath = provider.provide(JavaVersion.VERSION_1_8) 64 | def expectedPath = sampleOSXJDKPath.path 65 | 66 | then: 67 | assert actualJdkPath == expectedPath 68 | } 69 | 70 | def 'provides JDK from Windows style location'() { 71 | given: 72 | File sampleWindowsJDKPath = new File(project.projectDir, "jdk1.8.0_172") 73 | sampleWindowsJDKPath.mkdirs() 74 | updatedBasePaths.add(project.projectDir) 75 | 76 | def provider = builder.defaultLocationJDKPathProvider(basePaths: updatedBasePaths) // update read-only property 77 | 78 | when: 79 | def actualJdkPath = provider.provide(JavaVersion.VERSION_1_8) 80 | def expectedPath = sampleWindowsJDKPath.path 81 | 82 | then: 83 | assert actualJdkPath == expectedPath 84 | } 85 | 86 | @Unroll 87 | def 'provides JDK from Github Actions style location for #javaPackage/#javaVersion/#architecture'() { 88 | given: 89 | File sampleGithubActionsJDKPath = new File(project.projectDir, "$javaPackage/$javaVersion/$architecture") 90 | sampleGithubActionsJDKPath.mkdirs() 91 | updatedBasePaths.add(project.projectDir) 92 | 93 | def provider = builder.defaultLocationJDKPathProvider(basePaths: updatedBasePaths) // update read-only property 94 | 95 | when: 96 | def actualJdkPath = provider.provide(JavaVersion.VERSION_1_8) 97 | def expectedPath = sampleGithubActionsJDKPath.path 98 | 99 | then: 100 | assert actualJdkPath == expectedPath 101 | 102 | where: 103 | javaVersion | javaPackage | architecture 104 | '8.0.232' | 'jdk' | 'x64' 105 | '8.0.172' | 'jre' | 'x86' 106 | } 107 | 108 | def 'does not find JDK when none is set'() { 109 | given: 110 | def provider = builder.defaultLocationJDKPathProvider(basePaths: updatedBasePaths) // update read-only property 111 | 112 | when: 113 | def actualJdkPath = provider.provide(JavaVersion.VERSION_1_8) 114 | 115 | then: 116 | assert actualJdkPath == null 117 | } 118 | 119 | } 120 | --------------------------------------------------------------------------------