Gradle build - 添加模块路径

Gradle build - add module path

我的问题:如何为 gradle build 设置模块路径?

我已经习惯了从命令行使用 Java 模块。我经常在 Powershell 中进行练习,结果生成了这些源文件。

└───src
    ├───appMod
    │   │   module-info.java
    │   │
    │   └───appPack
    │           Entry.java
    │
    └───greetMod
        │   module-info.java
        │
        └───greetPack
                Hello.java

appMod/module-info

module appMod {
    requires greetMod;
}

appMod/appPack.条目

package appPack;

import greetPack.Hello;

public class Entry {
    public static void main(String[] args) {
        System.out.println(new Hello().sayHello());
    }
}

greetMod/module-info

module greetMod {
    exports greetPack;
}

greetMod/greetPack.你好

package greetPack;

public class Hello {
    public String sayHello() {
        return "Greetings from Hello class!";
    }
}

由于appMod模块需要greetMod,我先编译并jar greetMod。

javac -d out/greetMod src/greetMod/module-info.java src/greetMod/greetPack/Hello.java;
jar cf lib/greetJar.jar -C out/greetMod .;

然后我编译和 jar appMod,但是当我这样做时,我指定了可以找到新的 greetMod jar (greetJar) 的模块路径 (-p)(在 lib 中)。

javac -d out/appMod -p lib src/appMod/module-info.java src/appMod/appPack/Entry.java;
jar cfe lib/appJar.jar appPack.Entry -C out/appMod .;

然后我可以 运行 这个或通过添加模块路径部分地 jlink 它。

java -p lib -m appMod;
jlink -p lib --add-modules appMod --launcher launch=appMod --output dist;
dist/bin/launch

我现在想在 Gradle 中做同样的练习,但我不知道如何做相当于设置模块路径的操作,例如 -p lib。我看过 sourceSets, and countless variations of dependencies, but so far I haven't been able to put together something that works. I've also read conflicting statements that both say that Gradle doesn't fully support Java modules, and that Gradle does support them.

的代码

我知道这可能会造成混淆,但 gradle 绝对可以做到。您将需要使用多项目构建来完成这项工作。在你最上面的 build.gradle 中,这样做:

subprojects {
    apply plugin: 'java'

    sourceCompatibility = 1.9

    compileJava {
        doFirst {
            options.compilerArgs += [
                    '--module-path', classpath.asPath
            ]
            classpath = files()
        }
    }
}

在你的 settings.gradle:

rootProject.name = 'module-testing'

include 'src:greetMod'
include 'src:appMod'

appMod 中的所有内容都应移至名为 appModSrc 的文件夹中。对 greetMod 做同样的事情,所以使用 greetModSrc.


欢迎模组

目录结构:

├── build.gradle
└── greetModSrc
    ├── greetPack
    │   └── Hello.java
    └── module-info.java

build.gradle

sourceSets {
    main {
        java {
            srcDirs 'greetModSrc'
        }
    }
}

应用模组

目录结构:

├── appModSrc
│   ├── appPack
│   │   └── Entry.java
│   └── module-info.java
└── build.gradle

build.gradle

plugins {
    id 'application'
}

sourceSets {
    main {
        java {
            srcDirs 'appModSrc'
        }
    }
}

application {
    mainClassName 'appPack.Entry'
}

jar {
    doFirst {
        manifest {
            attributes('ModuleMainClass': mainClassName)
        }
    }
}

dependencies {
    implementation project(':src:greetMod')
}

使用此设置,您可以简单地 运行 ./gradlew :src:appMod:run:

> Task :src:appMod:run
Greetings from Hello class!

您可以在这里下载创意项目:https://github.com/MVCE-Superstars/multi-java9-gradle

由于Gradle 6.4 you can used set the inferModulePath属性项目上Java插件自动设置模块路径:

subprojects {
    plugins.withType(JavaPlugin).configureEach {
        java {
            modularity.inferModulePath = true
            sourceCompatibility = JavaVersion.VERSION_11
            targetCompatibility = JavaVersion.VERSION_11
        }
    }
}

首先请注意:我在 Gradle 6.6.1 和 Java 15.

这是我观察到的:

  1. 为了编译工作,每个项目需要:

    java {
        modularity.inferModulePath = true
    }
    
  2. 这可以在根 build.gradle 通过

    打开
     subprojects {
         apply plugin: "java"
         java {
             modularity.inferModulePath = true
         }
     }
    
  3. 为了将模块路径与 gradle run 一起使用(ServiceLoader 在没有 META-INF、反射限制的情况下工作...),您必须使用以下应用程序部分:

    application {
         mainModule = 'org.gradle.sample.app' // name defined in module-info.java
         mainClass = 'org.gradle.sample.Main'
         // DO NOT USE   mainClassName = 'org.gradle.sample.Main'
    }
    

我花了很长时间才从几个 Gradle 页把所有的东西放在一起 --- 但这就是全部 here.

注:

这将不会 non-modular jar 到 module-path。