问题
My question: How do I set a module path for gradle build
?
I've become comfortable working with Java modules from the command line. I do a frequent exercise in Powershell which results in these source files.
└───src
├───appMod
│ │ module-info.java
│ │
│ └───appPack
│ Entry.java
│
└───greetMod
│ module-info.java
│
└───greetPack
Hello.java
appMod/module-info
module appMod {
requires greetMod;
}
appMod/appPack.Entry
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.Hello
package greetPack;
public class Hello {
public String sayHello() {
return "Greetings from Hello class!";
}
}
Since the appMod module requires greetMod, I compile and jar greetMod first.
javac -d out/greetMod src/greetMod/module-info.java src/greetMod/greetPack/Hello.java;
jar cf lib/greetJar.jar -C out/greetMod .;
Then I compile and jar appMod, but as I do so I specify the module path (-p) where the new greetMod jar (greetJar) can be found (in 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 .;
I can then run this or jlink it in part by adding a module path.
java -p lib -m appMod;
jlink -p lib --add-modules appMod --launcher launch=appMod --output dist;
dist/bin/launch
I now want to do this same exercise in Gradle, but I can't figure out how to do the equivalent of setting a module path such as -p lib
. I've seen code for 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.
回答1:
I know it can be confusing, but it can definitely be done by gradle. You will need to use a multiproject build to have this work. In your top-most build.gradle
, do this:
subprojects {
apply plugin: 'java'
sourceCompatibility = 1.9
compileJava {
doFirst {
options.compilerArgs += [
'--module-path', classpath.asPath
]
classpath = files()
}
}
}
In your settings.gradle
:
rootProject.name = 'module-testing'
include 'src:greetMod'
include 'src:appMod'
Everything inside appMod
should be moved into a folder called appModSrc
. Do the same for greetMod
so use greetModSrc
.
greetMod
Directory structure:
├── build.gradle
└── greetModSrc
├── greetPack
│ └── Hello.java
└── module-info.java
build.gradle
sourceSets {
main {
java {
srcDirs 'greetModSrc'
}
}
}
appMod
Directory structure:
├── 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')
}
With this setup, you can simply run ./gradlew :src:appMod:run
:
> Task :src:appMod:run
Greetings from Hello class!
You can download the idea project here: https://github.com/smac89/multi-java9-gradle
回答2:
Since Gradle 6.4 you can used set the inferModulePath property on the project Java plugin to automatically set the module path:
subprojects {
plugins.withType(JavaPlugin).configureEach {
java {
modularity.inferModulePath = true
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
}
}
回答3:
First please note: I am on Gradle 6.6.1 with Java 15.
This is what I have observed:
in order to make the compile work, every project needs:
java { modularity.inferModulePath = true }
this can be turned on at root
build.gradle
viasubprojects { apply plugin: "java" java { modularity.inferModulePath = true } }
in order to use modulepath with
gradle run
(ServiceLoader working WITHOUT META-INF, reflection restrictions ...) you have to use following application section: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' }
Took me quite some time to put all together from several Gradle pages --- but it is all here.
Note:
This will not but non-modular jars to the module-path.
来源:https://stackoverflow.com/questions/58708213/gradle-build-add-module-path