Gradle:具有不同源和目标兼容性的多项目

Posted

技术标签:

【中文标题】Gradle:具有不同源和目标兼容性的多项目【英文标题】:Gradle: multi project with different source & target compatibility 【发布时间】:2016-02-09 16:47:19 【问题描述】:

我有使用 java 7 进行构建的多项目 gradle 配置。我正在添加一个必须使用 Java 6 构建的新项目。

从这个Q&A,我尝试了提出的不同解决方案,但都没有奏效。

这是顶层 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"
        
    

我曾尝试在子项目中确保源代码兼容性,但这似乎没有效果。

更新

我创建了一个多模块 gradle 项目的示例,其中一个子项目使用 Java 6,另一个子项目使用 Java 8。我在 gradle.properties 中使用了 org.gradle.java.home 属性来设置每个子项目他们每个人的 Java 主页。这是github repo。

子项目包含使用 Java 8 中的 APIs 的每个类,使用 java 6 的子项目预计会失败,但构建运行成功。

这是父 build.gradle 文件:

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

父settings.gradle的内容:

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

Java 6 子项目的 build.gradle 内容:

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'

Java 6 子项目的 gradle.properties 的内容:

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

java 8 子项目的 build.gradle:

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'

这是 gradle.properties :

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

我正在打印sourceCompatibilitytargetCompatibility,它们对每个项目都有很好的价值。

我正在使用gradle clean build 进行构建。

gradle -v 输出这个:

------------------------------------------------------------
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

我使用 Java 8 作为我的默认 Jdk。

提前致谢,

【问题讨论】:

【参考方案1】:

我引用了我从 gradle 论坛得到的答案:

您不能在每个项目级别更改 java.home,因为它适用于整个多项目构建。

设置编译器的源代码级别只会影响您可以使用哪些语言功能(例如 Lambdas)。它对 API 没有影响。这与 Gradle 无关,即使您直接运行 javac 也是如此。为确保您没有使用错误的 API,您必须设置编译任务的 bootClasspath。

tasks.withType(JavaCompile) 
  options.fork = true
  options.bootClasspath = "path/to/rt.jar"

【讨论】:

【参考方案2】:

与其他编程语言类似,Gradle 有很多方法可以完成相同的任务。在多项目构建中按项目定义特定插件或依赖项将使您的构建保持自包含,并有望创建更多可维护的代码。

来自 Gradle 文档Chapter 11 Section 2:

您还可以使用属性向项目对象添加属性 文件。您可以在 Gradle 用户主页中放置一个 gradle.properties 文件 目录(由“GRADLE_USER_HOME”环境变量定义, 如果未设置默认为 USER_HOME/.gradle) 或在您的项目中 目录。对于多项目构建,您可以放置​​ gradle.properties 任何子项目目录中的文件。 a中设置的属性 可以通过项目对象访问 gradle.properties 文件。这 用户主目录中的属性文件优先于 项目目录中的属性文件。

这意味着在每个子项目gradle.properties 文件中,您可以定义项目将使用的Java 版本或其他依赖项。在 Gradle 项目根 gradle.properties 文件中设置 Gradle Java 版本的示例如下:

org.gradle.java.home=/path_to_jdk_7

在您的子项目gradle.properties 文件中,您将拥有类似于:

com.myproject.app=/path_to_jdk_6

更新

Gradle 提供了监控子项目的工具。通过在父项build.gradle 中包含以下内容,可以调用一个任务来打印子项目及其父项。

allprojects 
    task versioner << task -> println "Loaded: $task.project.name"

subprojects 
    versioner << println " - Depends on parent"

为了验证 Java 版本是否不同,您可以尝试通过 JavaExec 从子项目中运行一个类。这可以在子项目build.gradle文件中调用如下:

task runApp(type: JavaExec) 

    classpath = sourceSets.main.runtimeClasspath

    //make sure the path points to project's java class being called 
    main = "com.test.MainClass"

【讨论】:

我已经在我的子项目中添加了 gradle.properties,但它似乎不起作用 org.gradle.java.home=/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home 您是否通过注释掉repositories 之后的项目来清除顶层build.gradle 并在根gradle.properties 文件中声明JAVA 版本? 在存储库之后注释了代码,添加了*** gradle.settings 和 org.gradle.java.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Home 但仍然没有使用 java 6 编译:( 我已经在一个示例项目上测试了 gradle.properties 的使用,并上传到了 github。 感谢您上传项目。我能够成功构建并运行该项目。我不确定什么没有加载,因为子项目正在加载正确的 Java 版本,如原始问题中所述。如果问题发生了变化,我建议再问一个问题,我可以尝试在那里提供见解。

以上是关于Gradle:具有不同源和目标兼容性的多项目的主要内容,如果未能解决你的问题,请参考以下文章

如何导入别人的android studio项目,解决gradle版本不兼容问题

如何将 Gradle 项目中 Kotlin 的字节码版本设置为 Java 8?

Dexguard 7.3.01 与 gradle 2.3.0 不兼容

如何跳过“此项目正在使用版本 xxx 的 android gradle 插件,与此版本的 android studio 不兼容”对话框?

vue项目跨域问题

Android gradle 插件与最新 Gradle 版本的兼容性