簡體   English   中英

Gradle:構建兼容Java的模塊化庫8

[英]Gradle: Building a modularized library that is compatible with Java 8

所以 Java 9 就在那里,很快就會有 Java 10。是時候讓我們的庫准備好在 Java 9 項目中使用了。 我是通過以下方式做到的:

  1. 提供模塊信息.java
  2. build.gradle中添加了(實驗性的) 拼圖插件
  3. 根據 gradle 站點上的指南手動進行更改,而不是使用拼圖插件。

到目前為止,這兩種方法都可以正常工作,我可以在 Java 9 個項目中使用生成的 Jar。

問題是,生成的 Jar 與 Java 8 不兼容,盡管我沒有使用 Java 9 功能,除了module-info.java 當我設置targetCompatibility = 8時,一條錯誤消息告訴我還相應地設置sourceCompatibility = 8 然后拒絕我應該為其設置sourceCompatibility = 9module-info.java

如何解決?

我再次刪除了拼圖插件,並嘗試了這個,但卡住了:

  1. 設置sourceCompatibility = 8targetCompatibility = 8
  2. 創建一個新的源集moduleInfo ,其中包含單個文件module-info.java
  3. 為新的源集設置sourceCompatibility = 9targetCompatibility = 9

現在編譯工作正常,並且 Gradle 在嘗試編譯module-info.java時使用 Java 9 。 但是,缺少模塊(在本例中為 log4j),我收到此錯誤:

:compileJava UP-TO-DATE
:processResources NO-SOURCE
:classes UP-TO-DATE
:jar UP-TO-DATE
:sourcesJar UP-TO-DATE
:assemble UP-TO-DATE
:spotbugsMain UP-TO-DATE
:compileModuleInfoJava
classpath:
compilerArgs: [--module-path, , --add-modules, ALL-SYSTEM]
D:\git\utility\src\module-info\java\module-info.java:14: error: module not found: org.apache.logging.log4j
    requires org.apache.logging.log4j;
                               ^
warning: using incubating module(s): jdk.incubator.httpclient
1 error
1 warning
:compileModuleInfoJava FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compileModuleInfoJava'.
> Compilation failed; see the compiler error output for details.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 1s
5 actionable tasks: 1 executed, 4 up-to-date

這是使用的build.gradle (Gradle 版本是 4.5.1):

plugins {
  id "com.github.spotbugs" version "1.6.0"
}

apply plugin: 'maven'
apply plugin: 'maven-publish'
apply plugin: 'java-library'
apply plugin: 'com.github.spotbugs'

sourceCompatibility = 8
targetCompatibility = 8

group = 'com.dua3.utility'

repositories {
    mavenLocal()
    jcenter()
}

dependencies {
  compile     group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.10.0'
  testRuntime group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.10.0'

  // Use JUnit test framework
  testImplementation 'junit:junit:4.12'
}

ext.moduleName = 'com.dua3.utility' 

sourceSets {
    moduleInfo {
        java {
            srcDir 'src/module-info/java'            
        }
    }
}

compileModuleInfoJava {
    sourceCompatibility = 9
    targetCompatibility = 9

    inputs.property("moduleName", moduleName)

    doFirst {
        options.compilerArgs = [
            '--module-path', classpath.asPath,
            '--add-modules', 'ALL-SYSTEM'
        ]
        classpath = files()  
        System.out.println("classpath: "+classpath.asPath)
        System.out.println("compilerArgs: "+options.compilerArgs)
    }
}

tasks.withType(com.github.spotbugs.SpotBugsTask) {
    reports {
        xml.enabled false
        html.enabled true
    }
}

task sourcesJar(type: Jar, dependsOn: classes) {
    classifier = 'sources'
    from sourceSets.main.allSource
}

task javadocJar(type: Jar, dependsOn: javadoc) {
    classifier = 'javadoc'
    from javadoc.destinationDir
}

artifacts {
    archives sourcesJar
// fails with jigsaw:    archives javadocJar
}

defaultTasks 'build', 'publishToMavenLocal', 'install'

這是module-info.java

module com.dua3.utility {
    exports com.dua3.utility;
    exports com.dua3.utility.io;
    exports com.dua3.utility.jfx;
    exports com.dua3.utility.swing;
    exports com.dua3.utility.lang;
    exports com.dua3.utility.math;
    exports com.dua3.utility.text;

    requires javafx.controls;
    requires javafx.web;
    requires java.xml;
    requires java.desktop;
    requires org.apache.logging.log4j;
}

好的,我終於搞定了 如果其他人想知道如何做,這就是我所做的:

  • 將Java版本設置為8,以便Java 8應用程序可以使用該庫:

    sourceCompatibility = 8
    targetCompatibility = 8

  • 配置模塊名稱

    ext.moduleName = com.dua3.utility

  • 添加僅包含module-info.java的新module-info.java

      sourceSets { moduleInfo { java { srcDir 'src/module-info/java' } } } 
  • 為moduleInfo,sourceSet,configure modules設置與Java 9的兼容性,並設置輸出目錄:

      compileModuleInfoJava { sourceCompatibility = 9 targetCompatibility = 9 inputs.property("moduleName", moduleName) doFirst { classpath += sourceSets.main.compileClasspath options.compilerArgs = [ '--module-path', classpath.asPath, '--add-modules', 'ALL-SYSTEM,org.apache.logging.log4j', '-d', sourceSets.main.output.classesDirs.asPath ] } } 
  • 配置jar任務以包含moduleInfo

     jar { from sourceSets.main.output from sourceSets.moduleInfo.output } 

如果您使用的是SpotBugs插件,則還必須顯式配置sourceSet,否則在嘗試處理ModuleInfo sourceSet時會失敗。

我終於得到了這個版本的build.gradle

plugins {
  id "com.github.spotbugs" version "1.6.0"
}

apply plugin: 'maven'
apply plugin: 'maven-publish'
apply plugin: 'java-library'
apply plugin: 'com.github.spotbugs'

sourceCompatibility = 8
targetCompatibility = 8

group = 'com.dua3.utility'

repositories {
    mavenLocal()
    jcenter()
}

dependencies {
  compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.10.0'
  testRuntime group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.10.0'

  // Use JUnit test framework
  testImplementation 'junit:junit:4.12'
}

ext.moduleName = 'com.dua3.utility' 

sourceSets {
    moduleInfo {
        java {
            srcDir 'src/module-info/java'            
        }
    }
}

compileModuleInfoJava {
    sourceCompatibility = 9
    targetCompatibility = 9

    inputs.property("moduleName", moduleName)

    doFirst {
        classpath += sourceSets.main.compileClasspath

        options.compilerArgs = [
            '--module-path', classpath.asPath,
            '--add-modules', 'ALL-SYSTEM',
            '-d', sourceSets.main.output.classesDirs.asPath
        ]
    }
}

jar 
{
    from sourceSets.main.output
    from sourceSets.moduleInfo.output
}

spotbugs {
    sourceSets = [sourceSets.main]
}

tasks.withType(com.github.spotbugs.SpotBugsTask) {
    reports {
        xml.enabled false
        html.enabled true
    }
}

task sourcesJar(type: Jar, dependsOn: classes) {
    classifier = 'sources'
    from sourceSets.main.allSource
}

task javadocJar(type: Jar, dependsOn: javadoc) {
    classifier = 'javadoc'
    from javadoc.destinationDir
}

artifacts {
    archives sourcesJar
    archives javadocJar
}

defaultTasks 'build', 'publishToMavenLocal', 'install'

問題已經超過一年了,但是如果有人在這里遇到麻煩,那么從1.5.0版本開始, Gradle Modules Plugin現在支持此功能。

使用此插件,您不必創建自定義源集,只需調用modularity.mixedJavaRelease方法即可。

這是一個如何將插件應用於一個主build.gradle

plugins {
  // your remaining plugins here

  id 'org.javamodularity.moduleplugin' version '1.5.0' apply false
}

subprojects {
  // your remaining subproject configuration here

  apply plugin: 'org.javamodularity.moduleplugin'
  modularity.mixedJavaRelease 8 // sets "--release 8" for main code, and "--release 9" for "module-info.java"

  // test.moduleOptions.runOnClasspath = true // optional (if you want your tests to still run on classpath)
}

我為此開發了一個 Gradle 插件: https://github.com/Glavo/module-info-compiler

試過Gradle Modules Plugin,但是還是有些麻煩的問題,所以開發了這個插件,專門用來編譯module-info.java的編譯器。

它不是通過調用javac實現的。 是一個可以運行在Java上面的完整編譯器 8.識別module-info.java的語法,並根據它生成對應的module-info.class文件。

它只檢查語法,並不實際檢查那些包、類或模塊,因此它可以在不配置任何模塊路徑的情況下工作。

這個 Gradle 插件已經為你處理好了一切。 對於包含module-info.java的 Java 8 項目,你只需要這樣做:

plugins {
    id("java")
    id("org.glavo.compile-module-info-plugin") version "2.0"
}

tasks.compileJava {
    options.release.set(8)
}

這個答案復制了自己在另一個問題下寫的答案( https://stackoverflow.com/a/72074642/7659948 )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM