Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make Multi-Release JAR Files with Gradle?

Java9 introduces with Multi-Release JARs.

Let's say that I have multimodule Gradle project using java8:

project-root
      settings.gradle
      build.gradle 
      /module1
          /src
          ... (common maven structure)
      /module2
      /module3

This is a common multi-module project in Gradle. Let's say I need MR-Jar for module1.

I can't add module1-java9 targeting Java9 because the base is on 8 - so far, both my Gradle and IntelliJ IDEA complains. Gradle is compiled with the java8, but I need to enable java9 runtime just for the module (don't know how); in IntelliJ IDEA I can set the java9 runtime for the module, but it gets overwritten every time when gradle config is reloaded.

Moreover, even if I add it somehow, I need to instruct module1 to 1) build second and 2) to include module1-java9. Here is a drawing of this situation:

project-root
      settings.gradle
      build.gradle 
      /module1
      /module1-java9  (added java9 module)
      /module2
      ...

Alternatively, this could be done under module1, having different sources: src and src-java9. but I doubt this would ever be accepted. Here is a drawing:

project-root
      settings.gradle
      build.gradle 
      /module1
          /src
          /src-java9 (added java9 source folder)
      /module2
      /module3

So far I only see that module1-java9 is a separate project (not a module) and that module1 simply calls the gradle there and takes the output. Yeah, it's gradle calling gradle :)))

Is there any developer-friendly way to do this?

like image 917
igr Avatar asked Dec 05 '17 07:12

igr


1 Answers

As mentioned in the comments on the question, this blog post and the associated example project describe how to create a multi-release JAR with Gradle.

In case the blog post or example project should go away, you may also refer to the following setup which was derived from the example project and tailored a bit to the setup that is given in the question (as far as details are provided).

Overview

project-root/
├── build.gradle
├── module1
│   └── src
│       └── main
│           ├── java
│           │   └── com
│           │       └── acme
│           │           ├── JdkSpecific.java
│           │           └── Shared.java
│           └── java9
│               └── com
│                   └── acme
│                       └── JdkSpecific.java
├── module2
│   └── whatever
├── module3
│   └── whatever
└── settings.gradle

build.gradle

allprojects {
    apply plugin: 'java'

    compileJava {
        sourceCompatibility = 8
        targetCompatibility = 8
    }
}

dependencies {
    implementation project(':module1')
}

project(':module1') {
    sourceSets {
        java9 {
            java {
                srcDirs = ['src/main/java9']
            }
        }
    }

    compileJava9Java {
        sourceCompatibility = 9
        targetCompatibility = 9
    }

    dependencies {
        java9Implementation files(sourceSets.main.output.classesDirs) {
                builtBy compileJava
            }
    }

    jar {
        into('META-INF/versions/9') {
            from sourceSets.java9.output
        }
        manifest.attributes('Multi-Release': 'true')
    }
}

settings.gradle

include 'module1', 'module2', 'module3'
like image 58
Chriki Avatar answered Oct 10 '22 04:10

Chriki