【问题标题】:Gradle sourceCompatibility has no effect to subprojectsGradle sourceCompatibility 对子项目没有影响
【发布时间】:2014-01-28 11:44:02
【问题描述】:

我的机器上安装了 Java 6 和 7。 Gradle 使用 1.7(使用 gradle -v 检查)。但我需要编译我的代码以与 Java 1.6 兼容。据我了解的文档,我可以使用sourceCompatibility 属性来执行此操作(间接使用默认为sourceCompatibility 的targetCompatibility)。

所以我在我的构建文件中添加了以下行(在根级别,而不是在任何闭包中):

sourceCompatibility = 1.6

(确保我在一些试验中也添加了targetCompatibility = 1.6,但这应该没有什么区别)

为了检查结果是否实际上与 1.6 兼容,我将生成的 jar cd 解压缩到 WEB-INF/classes 文件夹中,并在遇到的第一个 .class 文件上使用了 javap -verbose。但是无论我设置目标兼容性还是使用1.5而不是1.6还是指定为字符串('1.6'),每次javap的结果都是

minor version: 0
major version: 51

Afaik 这意味着它是 Java 1.7 字节码,这是错误的。

任何想法为什么sourceCompatibility-setting 不起作用?还是javap不是检查兼容性的正确方法?

更新: 是的,这实际上是一个多项目构建,但我只检查了其中一个子项目的构建结果。在这个子项目的构建文件中,我进行了上述更改以确保它们被实际应用。此外,我在根项目的构建文件中添加了以下内容(正如@Vidya 建议的那样):

allprojects {
    sourceCompatibility = 1.6
    targetCompatibility = 1.6
}

但这也无济于事。

更新 2: 我在相关的 build.gradle 文件中用这个 sn-p 检查了 sourceCompatibility 的设置:

compileJava.doFirst {
    println "source compatibility " + sourceCompatibility
}

它显示我的 sourceCompatibility 设置为 1.7,尽管我尝试将其设置为 1.6。当我提取最简单的子项目并自行构建时,sourceCompatibility 设置正确,Java Byte 代码与 1.6 兼容。但是,即使这个子项目在多项目构建中使用时也使用了错误的 sourceCompatibility。

顺便说一句:我在一些子项目中使用的插件是:java、war、jetty、gwt

更新 3: 我将构建的脚本更改为仅使用 java 插件(因此仅构建一些 jar)并删除了 war、jetty 和 gwt 插件的使用。但是,尽管我在allprojects 部分和一些子项目中设置了它,但所有项目仍然设置为 sourceCompatibility 1.7。现在在构建脚本中只剩下一些规范(maven、文件和其他子项目)的声明,要使用的存储库的声明,一些其他任务的声明(构建任务不依赖于,所以它不应该受到影响)以及为创建的 jar 文件配置清单文件(我在清单文件中添加了规范和实现版本和标题)。

我看不出这会如何影响 sourceCompatibility 设置。

【问题讨论】:

  • 为了满足您的要求,您需要设置targetCompatibility。但是我认为您不能拥有源兼容性>目标兼容性,并且您的目标兼容性默认为源兼容性。因此,我希望这能正常工作。这是一个多项目构建吗?您确定为正确的项目设置sourceCompatibility?
  • 另一种方法是使用 Java 6 运行 Gradle。这也将捕获您无意中使用某些 Java 7 API 的情况,并避免每当您将 Java 7 编译器与源代码兼容时发出的恼人的 javac 警告6 并且不要将 Java 6 标准库放在编译器的引导类路径中。
  • 我完全重复了你的步骤(也使用 JDK7 运行 Gradle),它对我来说很好用 (major version: 50)。此时很可能是您的构建有问题。例如,某些构建脚本或第三方插件可能会覆盖您的配置。但是如果没有可重复的例子,就很难再提供帮助。您可以尝试的一件事是检查 compileJava.doFirst { println sourceCompatibility } 打印的内容。也尝试使用干净的构建,尽管这不是必需的。
  • 它正在打印compileJava.sourceCompatibility,默认为project.sourceCompatibility(这是您迄今为止设置的)。您可以尝试直接使用tasks.withType(JavaCompile) { sourceCompatibility = "1.6"; targetCompatibility = "1.6" } 设置任务级属性(这些是最重要的属性),尽管通常没有必要这样做。
  • @PeterNiederwieser 我将这个tasks.withType(JavaCompile) { sourceCompatibility = "1.6"; targetCompatibility = "1.6" } 添加到allProjects{},它现在可以工作了。即使使用原始构建脚本中的所有插件。如果您将此添加为答案,我会接受。不过,我仍然很好奇为什么它不能通过项目属性起作用。

标签: java gradle compatibility bytecode


【解决方案1】:

似乎此行为是由指定sourceCompatibility 引起的之前 apply plugin: 'java',如果您尝试在allprojects 中设置兼容性选项,则会发生这种情况。

在我的设置中,这种情况可以通过替换来解决:

allprojects {
    sourceCompatibility = 1.6
    targetCompatibility = 1.6
}

与:

allprojects {
    apply plugin: 'java'
    sourceCompatibility = 1.6
    targetCompatibility = 1.6
}

如果其他人可以在不同的设置中验证这一点,我会很高兴。

我仍然不确定这是否应该被报告为一个错误,但我相信这个解决方案比上面提到的解决方法更好(不过这很有帮助)。

【讨论】:

  • 好收获。第一个 sn-p 是错误的,因为这些属性仅由 java 插件引入。在 1.x 中,它会给出关于将值分配给不存在的属性的弃用警告,在 2.0 中它将彻底失败。
  • 我们刚刚和我的一位同事讨论了这个“警告”话题。由于某种原因,代码没有发出警告(Gradle 1.8 和 1.12)。我还是不太清楚为什么。
  • 如果在应用java插件之前设置了sourceCompatibility,肯定会发出如下弃用警告:Deprecated dynamic property: "sourceCompatibility" on "root project 'foo'", value: "1.6".
  • 非常感谢,这也为我解决了问题!我想我当时也没有收到警告,但我现在确实收到了一个警告(gradle 1.10),当我在没有“应用插件'java'”的情况下再次尝试时。
  • 这可能很明显,但在 subprojects 块中使用时也有效(在“java”或“groovy”插件应用程序之后)。
【解决方案2】:

症状表明某处有人正在覆盖project.sourceCompatibility。但考虑到定制 Gradle 的方式有很多种,我无法从远处判断这是谁。

作为一种解决方法,您可以在任务级别设置属性,这才是最重要的:

tasks.withType(JavaCompile) { 
    sourceCompatibility = "1.6"
    targetCompatibility = "1.6" 
}

将此添加到allProjects { ... } 块。

【讨论】:

  • 我们今天也遇到了同样的情况。这是一个很好的解决方法,我仍然很好奇导致 sourceCompatibility 设置被覆盖的原因。
  • 带括号还是不带括号? ""
  • 我实际上不认为您希望在 allProjects 块中使用它。这不是让它评估每个项目的块吗?如果你把它放在你的根 gradle 项目的底部,我想你只会执行一次它,它会命中每个配置的 javaCompile 任务。
【解决方案3】:

如果您使用 sourceCompatibility 或 targetCompatibility,您需要在 build.gradle 文件中定义 compileJava 任务。如果没有 compileJava 任务,两个兼容性变量都会在 Intellij 中显示为未使用的变量。我正在使用 Gradle 2.10 版。

【讨论】:

    【解决方案4】:

    要解决这个问题,只需检查构建Gradle(应用程序),并将以下代码放入其中。

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    

    同样在构建Gradle(项目)中,你必须有下面的代码。

    allprojects {
        repositories {
            google()
            mavenCentral()
            jcenter()
            sourceCompatibility = 1.6
            targetCompatibility = 1.6
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-05-15
      • 2020-01-15
      • 1970-01-01
      • 1970-01-01
      • 2018-08-30
      • 2020-11-10
      • 2015-11-04
      • 2010-12-01
      • 2013-10-07
      相关资源
      最近更新 更多