Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gradle: multi project with different source & target compatibility

I have multi-project gradle configuration which is using java 7 for building. I am adding a new project that have to be built with Java 6.

From this Q&A I have tried the different solutions proposed but none of them worked.

Here is the top level build.gradle:

allprojects {
    apply plugin: 'idea'
    apply plugin: 'java'


    repositories {
        maven { url 'http://repo1.maven.org/maven2' }
        mavenLocal()
    }

    sourceCompatibility = 1.7
    targetCompatibility = 1.7

    gradle.projectsEvaluated {
        tasks.withType(JavaCompile) {
            options.compilerArgs << "-Xlint:-options"
        }
    }
}

I have tried to enfore source compatibility in the child project but it seems that this has no effect.

Update:

I have created an example of multi-module gradle project with one of the sub-project using Java 6 and another one java 8. I have used org.gradle.java.home attribute in gradle.properties for each of the sub-projects to set the Java home for each of them. Here is the github repo.

The subprojects contain each one class using Apis from Java 8, the subproject using java 6 is expected to fail, but the build runs successfully.

Here is the parent build.gradle file :

group 'com.test'
version '1.0-SNAPSHOT'
repositories {
   mavenCentral()
}

The content of the parent settings.gradle:

rootProject.name = 'Parent'
include 'child2Java6'
include 'child1Java8'

the content of build.gradle of the Java 6 subproject :

group 'com.test'
version '1.0-SNAPSHOT'

apply plugin: 'java'

sourceCompatibility = JavaVersion.VERSION_1_6
targetCompatibility = JavaVersion.VERSION_1_6
repositories {
    mavenCentral()
}
compileJava.doFirst {
    println "source compatibility  " + sourceCompatibility
    println "target compatibility  " + targetCompatibility
}
dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.11'
}

the content of gradle.properties of the Java 6 subproject :

org.gradle.java.home=/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/

build.gradle for java 8 sub-project:

group 'com.test'
version '1.0-SNAPSHOT'

apply plugin: 'java'


sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
repositories {
    mavenCentral()
}
compileJava.doFirst {
    println "source compatibility  " + sourceCompatibility
    println "target compatibility  " + targetCompatibility
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.11'
}

It's gradle.properties :

org.gradle.java.home=/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/

I am printing the sourceCompatibility and targetCompatibility and they have the good values for each project.

I am using gradle clean build for building.

The gradle -v outputs this :

------------------------------------------------------------
Gradle 2.9
------------------------------------------------------------

Build time:   2015-11-17 07:02:17 UTC
Build number: none
Revision:     b463d7980c40d44c4657dc80025275b84a29e31f

   Groovy:       2.4.4
   Ant:          Apache Ant(TM) version 1.9.3 compiled on December 23 2013
   JVM:          1.8.0_65 (Oracle Corporation 25.65-b01)
   OS:           Mac OS X 10.11.1 x86_64

I am using Java 8 as my default Jdk.

Thanks in advance,

like image 732
Master Mind Avatar asked Feb 09 '16 16:02

Master Mind


2 Answers

I am quoting the answer I got from gradle's forum :

You cannot change the java.home on a per-project level, because it applies to the whole multi-project build.

Setting the source level of the compiler only has an effect on which language features you can use (e.g. Lambdas). It has no effect on APIs. That is unrelated to Gradle and true even if you run javac directly. To make sure you are not using the wrong APIs, you'll have to set the bootClasspath of the compile task.

tasks.withType(JavaCompile) {
  options.fork = true
  options.bootClasspath = "path/to/rt.jar"
}
like image 169
Mustapha Saeed Avatar answered Oct 08 '22 11:10

Mustapha Saeed


Similar to other programming languages, Gradle has many ways to accomplish the same task. Defining specific plugins or dependencies by project across a multi project build will keep your builds self contained and hopefully create more maintainable code.

From Gradle Documentation Chapter 11 Section 2:

You can also add properties to your project objects using properties files. You can place a gradle.properties file in the Gradle user home directory (defined by the “GRADLE_USER_HOME” environment variable, which if not set defaults to USER_HOME/.gradle) or in your project directory. For multi-project builds you can place gradle.properties files in any subproject directory. The properties set in a gradle.properties file can be accessed via the project object. The properties file in the user's home directory has precedence over property files in the project directories.

That means in each subproject gradle.properties file you can define the version of Java, or other dependencies, the project will use. An example of setting the Gradle Java version in your Gradle project root gradle.properties file would be:

org.gradle.java.home=/path_to_jdk_7

In your subproject gradle.properties file you would have something similar to:

com.myproject.app=/path_to_jdk_6

UPDATE

Gradle provides tools to keep an eye on sub-projects. By including the following in the parent build.gradle a task can be called to print the child projects and their parents.

allprojects {
    task versioner << {task -> println "Loaded: $task.project.name"}
}
subprojects {
    versioner << {println " - Depends on parent"}
}

In order to verify Java versions are different you can try running a class from the sub-project via JavaExec. This can be called in the child projects build.gradle file as follows:

task runApp(type: JavaExec) {

    classpath = sourceSets.main.runtimeClasspath

    //make sure the path points to project's java class being called 
    main = "com.test.MainClass"
}
like image 34
Nathan Avatar answered Oct 08 '22 11:10

Nathan