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
module appMod {
requires greetMod;
}
package appPack;
import greetPack.Hello;
public class Entry {
public static void main(String[] args) {
System.out.println(new Hello().sayHello());
}
}
module greetMod {
exports greetPack;
}
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.
Most Android projects only have one module, the app module. The build. gradle (Module: app) file here is in the app folder.
The subproject producer defines a task named buildInfo that generates a properties file containing build information e.g. the project version. You can then map the task provider to its output file and Gradle will automatically establish a task dependency.
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
.
Directory structure:
├── build.gradle
└── greetModSrc
├── greetPack
│ └── Hello.java
└── module-info.java
sourceSets {
main {
java {
srcDirs 'greetModSrc'
}
}
}
Directory structure:
├── appModSrc
│ ├── appPack
│ │ └── Entry.java
│ └── module-info.java
└── 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/MVCE-Superstars/multi-java9-gradle
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With