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.
Advertisement
Answer
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/MVCE-Superstars/multi-java9-gradle