As for now we have a project structure with single source folder named src
, which contains source code for three modules. What I want to do is:
1) Compile source code. This is easily done with sourceSets definition:
sourceSets { main { java { srcDir 'src' } } }
2) Put compilation results into three jars. I am doing this via three 'jar' type tasks:
I am doing this now via three separate tasks:
util.jar
task utilJar(type: Jar) { from(sourceSets.main.output) { include "my/util/package/**" } }
client.jar
task clientJar(type: Jar) { from(sourceSets.main.output) { include "my/client/package/**" } }
server.jar
task serverJar(type: Jar) { from(sourceSets.main.output) { include "**" } excludes.addAll(utilJar.includes) excludes.addAll(clientJar.includes) }
The thing is that server.jar
should contain all classes that are not contained within client.jar
and util.jar
. In ant build script we solve this problem by using difference
ant task. How this can be done in gradle (my current approach doesn't work)?
Maybe my approach is completely wrong. Please advice.
P.S. as for now we CAN NOT change the project source code folder structure.
A multi-release JAR file allows for a single JAR file to support multiple major versions of Java platform releases. For example, a multi-release JAR file can depend on both the Java 8 and Java 9 major platform releases, where some class files depend on APIs in Java 8 and other class files depend on APIs in Java 9.
Yes. You can have multiple build files in one project. The only thing you can't do, of course, is have multiple files named build. gradle in the same folder.
Gradle declares dependencies on JAR files inside your project's module_name /libs/ directory (because Gradle reads paths relative to the build. gradle file).
I will post my working solution here as an answer (I've got a hint on gradle's forum).
The scopes in gradle are very strange thing :) I thought that every task definition creates an object of some 'Task' class, which is something like 'JarTask' in this particular case. Then I can access any property of the class from anywhere in my build.gradle script. However, I found the only place where I can see the patterns, which are included in jar file - inside a from
block of a task. So my working solution for now is to:
1) Define a project-level collection to contain patterns to be excluded from server.jar
2) Exclude all patterns in from
block of serverJar
task.
Please see final version below
sourceSets { main { java { srcDir 'src' } } } // holds classes included into client.jar and util.jar, so they are to be excluded from server.jar ext.serverExcludes = [] // util.jar task utilJar(type: Jar) { from(sourceSets.main.output) { include "my/util/package/**" project.ext.serverExcludes.addAll(includes) } } // client.jar task clientJar(type: Jar) { from(sourceSets.main.output) { include "my/client/package/**" project.ext.serverExcludes.addAll(includes) } } // server.jar task serverJar(type: Jar) { from(sourceSets.main.output) { exclude project.ext.serverExcludes } }
I think the approach is wrong. I recommend making a project with 3 sub projects.
project - util - server (depends on util) - client (depends on util)
If for some reason you cannot change the class structure use this kind of build files:
settings.gradle
include 'util', 'client', 'server'
build.gradle
subprojects { apply plugin: 'java' } project(':util') { sourceSets { main { java { srcDir '../src' include 'util/**' } } } } project(':server') { sourceSets { main { java { srcDir '../src' include 'server/**' } } } dependencies { compile project(':util') } } project(':client') { sourceSets { main { java { srcDir '../src' include 'client/**' } } } dependencies { compile project(':util') } }
You still need directories for subprojects but the sources are in one place as you wanted.
When you run gradle assemble
you will have 3 jars with separate set of classes. The advantage of this solution is that we make a proper Gradle multi module project with correct dependencies, not just tasks for building jars.
Please read Multi-Project Builds.
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