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