Gradle:构建一个与Java 8兼容的模块化库

时间:2018-02-22 13:32:51

标签: java gradle build.gradle java-9 jigsaw

所以Java 9就在那里,很快就会出现Java 10.我们应该准备好在Java 9项目中使用我们的库。我是通过以下方式做到的:

  1. 提供module-info.java
  2. build.gradle
  3. 中添加了(实验性的)jigsaw plugin
  4. 根据gradle网站上的guide手动进行更改,而不是使用拼图插件。
  5. 到目前为止,两种方法都运行良好,我可以在Java 9项目中使用生成的Jar。

    问题是,虽然我没有使用除module-info.java之外的Java 9功能,但生成的Jar与Java 8不兼容。当我设置targetCompatibility = 8时,一条错误消息告诉我也要相应地设置sourceCompatibility = 8。然后拒绝我应该设置module-info.java的{​​{1}}。

    如何解决这个问题?

    我再次移除了拼图插件,并尝试了这个,但卡住了:

    1. 设置sourceCompatibility = 9sourceCompatibility = 8
    2. 创建一个包含单个文件targetCompatibility = 8
    3. 的新源集moduleInfo
    4. 为新的sourceset
    5. 设置module-info.javasourceCompatibility = 9

      现在编译工作正常,Gradle在尝试编译targetCompatibility = 9时使用Java 9。但是,缺少模块(在本例中为log4j),我收到此错误:

      module-info.java

      这是: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 使用的(Gradle版本是4.5.1):

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

2 个答案:

答案 0 :(得分:2)

好的,我终于搞定了。如果其他人想知道如何做,这就是我所做的:

  • 将Java版本设置为8,以便Java 8应用程序可以使用该库:

    sourceCompatibility = 8
    targetCompatibility = 8

  • 配置模块名称

    ext.moduleName = com.dua3.utility

  • 添加仅包含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 :(得分:0)

这个问题已有一年多的历史了,但是如果有人跌跌撞撞,那么自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)
}