在 Gradle 中编译一个 JDK 8 项目 + 一个 JDK 9 “module-info.java”

Tom*_*ski 5 java javac gradle java-9 java-module

我正在开发一个面向 JDK 8 的 Java 库,我正在使用 OpenJDK 11 在 Gradle 5 中构建它。为了面向 JDK 8,我是 javac 的--release选项。

但是,我也希望我的库与 JPMS 兼容。换句话说:

MCVE

构建.gradle

plugins {
    id 'java'
    id 'org.javamodularity.moduleplugin' version '1.4.1' // *
}

repositories {
    mavenCentral()
}

dependencies {
    compileOnly 'org.projectlombok:lombok:1.18.6'
}

compileJava.options.compilerArgs.addAll(['--release', '9']) // **
Run Code Online (Sandbox Code Playgroud)

*org.javamodularity.moduleplugin设置--module-pathcompileJava

** 目前还没有 Gradle DSL --release#2510

src/main/java/module-info.java

plugins {
    id 'java'
    id 'org.javamodularity.moduleplugin' version '1.4.1' // *
}

repositories {
    mavenCentral()
}

dependencies {
    compileOnly 'org.projectlombok:lombok:1.18.6'
}

compileJava.options.compilerArgs.addAll(['--release', '9']) // **
Run Code Online (Sandbox Code Playgroud)

src/main/java/pl/tlinkowski/sample/Sample.java

module pl.tlinkowski.sample {
  requires lombok;
  exports pl.tlinkowski.sample;
}
Run Code Online (Sandbox Code Playgroud)

这个 MCVE 编译,但所有类(而不是 only module-info.class)都是 JDK 9 类格式(v.53)。

其他构建工具

我想要做的当然是可能的:

  1. 马文
    • 例如ThreeTen-Extra(他们的方法归结为:首先用 编译所有东西--release 9,然后除了module-info.java用编译所有东西--release 8)。
  2. 蚂蚁
    • 例如Lombok(他们的方法归结为:有module-info.java一个单独的“源集”——主源集用 编译--release 8,“模块信息”源集用 编译--release 9)。

我试过的

我喜欢 Lombok 的方法,所以我build.gradle按如下方式操作源集:

sourceSets {
    main { // all but module-info
        java {
            exclude 'module-info.java'
        }
    }
    mainModuleInfo { // module-info only
        java {
            srcDirs = ['src/main/java']
            outputDir = file("$buildDir/classes/java/main")
            include 'module-info.java'
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,我配置了一个任务依赖项并--release为两个编译任务添加了适当的选项:

classes.dependsOn mainModuleInfoClasses

compileJava.options.compilerArgs.addAll(['--release', '8'])
compileMainModuleInfoJava.options.compilerArgs.addAll(['--release', '9'])
Run Code Online (Sandbox Code Playgroud)

如果我现在编译,我会得到:

错误:包 lombok 不存在

所以我仍然不知道如何指示org.javamodularity.moduleplugin

  • --module-path用于main
  • 设置适当--module-pathmainModuleInfo

Tom*_*ski 4

编辑:自版本1.5.0以来, Gradle Modules Plugin现在支持此功能。

\n\n

这是一个工作build.gradle片段:

\n\n
plugins {\n    id \'java\'\n    id \'org.javamodularity.moduleplugin\' version \'1.5.0\'\n}\n\nrepositories {\n    mavenCentral()\n}\n\ndependencies {\n    compileOnly \'org.projectlombok:lombok:1.18.6\'\n}\n\nmodularity.mixedJavaRelease 8\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

好的,我设法通过以下方式使其工作:

\n\n
    \n
  1. 禁用org.javamodularity.moduleplugin
  2. \n
  3. 删除自定义源集(没有必要)
  4. \n
  5. 添加自定义compileModuleInfoJava任务并将其设置--module-path为任务的类路径compileJava(受到本 Gradle 手册的启发)
  6. \n
\n\n

这是完整的源代码build.gradle

\n\n
plugins {\n    id \'java\'\n}\n\nrepositories {\n    mavenCentral()\n}\n\ndependencies {\n    compileOnly \'org.projectlombok:lombok:1.18.6\'\n}\n\ncompileJava {\n    exclude \'module-info.java\'\n\n    options.compilerArgs = [\'--release\', \'8\']\n}\n\ntask compileModuleInfoJava(type: JavaCompile) {\n    classpath = files() // empty\n    source = \'src/main/java/module-info.java\'\n    destinationDir = compileJava.destinationDir // same dir to see classes compiled by compileJava\n\n    doFirst {\n        options.compilerArgs = [\n                \'--release\', \'9\',\n                \'--module-path\', compileJava.classpath.asPath,\n        ]\n    }\n}\n\ncompileModuleInfoJava.dependsOn compileJava\nclasses.dependsOn compileModuleInfoJava\n
Run Code Online (Sandbox Code Playgroud)\n\n

笔记:

\n\n
    \n
  • 它编译
  • \n
  • 我验证了它module-info.class是 JDK 9 格式(第 8 个字节是0x35\xe2\x86\x92 v.53),而其他类是 JDK 8 格式(第 8 个字节是0x34\xe2\x86\x92 v.52
  • \n
  • 然而,禁用org.javamodularity.moduleplugin并不令人满意,因为这意味着测试将不再在模块路径等上运行。
  • \n
\n