Maven Incremental Module Build

If you are working with a Maven Multi Module Build on command line it could happen that you might think: Wouldn't it be nice to build only the modules which you have changed and not all modules in the reactor.

You can of course control what you build by using the --projects command line option and add the appropriate modules you would like to build. For example like this:

1mvn --projects module1,module2 clean package

But you need to think everytime you run the build about which modules have been changed and you need to adapt the list of changed modules manually.

Apart from that you need to think about the case if your modules are used by other modules in your build. This means module1 is a module dependency of another module. This can simply handled by Maven automatically by using the command line option --also-make-dependents which will build the modules which are dependencies of the modules given in the projects list.

1mvn --projects module1,module2 --also-make-dependents clean package

There are often suggestions to change into the directory of the module you would like to build but this is simply wrong. If you start the build there Maven will read only the pom file of that single module and you have no chance of letting Maven anlyze the modules and their needed order etc. So always keep in the root directory of your multi module build and select the appropriate modules via --projects option.

The above will of course fine but this is cumbersome.

All this steps I have described can be handled in an automatic way by using the The Incremental Module Builder extensions.

To use the Incremental Module Build you need to run at best Maven 3.3.1+ and Java 7 as Maven 3.3.1+ itself. Furthermore you should configure it via the extensions.xml file in the .mvn/ folder of your project which should look like this:

1<extensions xmlns="http://maven.apache.org/EXTENSIONS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2  xsi:schemaLocation="http://maven.apache.org/EXTENSIONS/1.0.0 http://maven.apache.org/xsd/core-extensions-1.0.0.xsd">
3  <extension>
4    <groupId>com.soebes.maven.extensions</groupId>
5    <artifactId>incremental-module-builder</artifactId>
6    <version>0.1.0</version>
7  </extension>
8</extensions>

Another prerequisite is having configured correctly the scm area in your root pom of the project cause those information are used to analyze for changed files. You can run the incremental module builder via:

1mvn -b incremental package

which will printout something similar like this:

  1~/ws-git/supose (master *)$ mvn -b incremental package
  2[INFO] Scanning for projects...
  3[INFO] ------------------------------------------------------------------------
  4[INFO] Reactor Build Order:
  5[INFO]
  6[INFO] Subversion Repository Search Engine
  7[INFO] SupoSE :: Test
  8[INFO] SupoSE :: Filter
  9[INFO] SupoSE :: Filter : Filter Model
 10[INFO] SupoSE :: Filter : Filter
 11[INFO] SupoSE :: Core
 12[INFO] SupoSE :: CLI
 13[INFO] SupoSE :: WAR
 14[INFO] SupoSE :: Integration Test
 15[INFO] SupoSE :: Users Guide
 16[INFO] SupoSE :: Assembly
 17[INFO]  ------------------------------------
 18[INFO]  Maven Incremental Module Builder
 19[INFO]  Version: 0.1.0
 20[INFO]  ------------------------------------
 21[INFO]
 22[INFO] Using the IncrementalModuleBuilder implementation with a thread count of 3
 23[INFO] Executing: /bin/sh -c cd '/Users/kama/ws-git/supose' && 'git' 'rev-parse' '--show-toplevel'
 24[INFO] Working directory: /Users/kama/ws-git/supose
 25[INFO] Executing: /bin/sh -c cd '/Users/kama/ws-git/supose' && 'git' 'status' '--porcelain' '.'
 26[INFO] Working directory: /Users/kama/ws-git/supose
 27[INFO]  Changed file: supose-cli/pom.xml modified
 28[INFO] Changed Project: com.soebes.supose:supose-cli:jar:0.7.1-SNAPSHOT
 29[INFO] New Calculated Reactor:
 30[INFO]  SupoSE :: CLI
 31[INFO]  SupoSE :: Assembly
 32[INFO] Building project: com.soebes.supose:supose-cli:jar:0.7.1-SNAPSHOT
 33[INFO]
 34[INFO] ------------------------------------------------------------------------
 35[INFO] Building SupoSE :: CLI 0.7.1-SNAPSHOT
 36[INFO] ------------------------------------------------------------------------
 37[INFO]
 38[INFO] --- maven-enforcer-plugin:1.4.1:enforce (enforce-maven) @ supose-cli ---
 39[INFO]
 40[INFO] --- buildnumber-maven-plugin:1.4:create (default) @ supose-cli ---
 41[INFO] Executing: /bin/sh -c cd '/Users/kama/ws-git/supose/supose-cli' && 'git' 'rev-parse' '--verify' 'HEAD'
 42[INFO] Working directory: /Users/kama/ws-git/supose/supose-cli
 43[INFO] Storing buildNumber: 2cf6fbf37dbd3a0922ebd607a5b0504e76a0fd76 at timestamp: 1470779925110
 44[INFO] Storing buildScmBranch: master
 45[INFO]
 46[INFO] --- maven-resources-plugin:3.0.1:resources (default-resources) @ supose-cli ---
 47[INFO] Using 'UTF-8' encoding to copy filtered resources.
 48[INFO] Copying 1 resource
 49[INFO]
 50[INFO] --- maven-compiler-plugin:3.5.1:compile (default-compile) @ supose-cli ---
 51[INFO] Nothing to compile - all classes are up to date
 52[INFO]
 53[INFO] --- maven-resources-plugin:3.0.1:testResources (default-testResources) @ supose-cli ---
 54[INFO] Using 'UTF-8' encoding to copy filtered resources.
 55[INFO] Copying 1 resource
 56[INFO]
 57[INFO] --- maven-compiler-plugin:3.5.1:testCompile (default-testCompile) @ supose-cli ---
 58[INFO] Nothing to compile - all classes are up to date
 59[INFO]
 60[INFO] --- maven-surefire-plugin:2.19.1:test (default-test) @ supose-cli ---
 61
 62-------------------------------------------------------
 63 T E S T S
 64-------------------------------------------------------
 65Running com.soebes.supose.cli.SuposeCLITest
 66Tests run: 22, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.527 sec - in com.soebes.supose.cli.SuposeCLITest
 67
 68Results :
 69
 70Tests run: 22, Failures: 0, Errors: 0, Skipped: 0
 71
 72[INFO]
 73[INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ supose-cli ---
 74[INFO]
 75[INFO] --- maven-site-plugin:3.5.1:attach-descriptor (attach-descriptor) @ supose-cli ---
 76[INFO] Building project: com.soebes.supose:supose-assembly:pom:0.7.1-SNAPSHOT
 77[INFO]
 78[INFO] ------------------------------------------------------------------------
 79[INFO] Building SupoSE :: Assembly 0.7.1-SNAPSHOT
 80[INFO] ------------------------------------------------------------------------
 81[INFO]
 82[INFO] --- maven-enforcer-plugin:1.4.1:enforce (enforce-maven) @ supose-assembly ---
 83[INFO]
 84[INFO] --- buildnumber-maven-plugin:1.4:create (default) @ supose-assembly ---
 85[INFO]
 86[INFO] --- maven-site-plugin:3.5.1:attach-descriptor (attach-descriptor) @ supose-assembly ---
 87[INFO]
 88[INFO] --- appassembler-maven-plugin:1.10:assemble (default) @ supose-assembly ---
 89[INFO]
 90[INFO] --- maven-assembly-plugin:2.6:single (default) @ supose-assembly ---
 91[INFO] Reading assembly descriptor: src/main/assembly/bin.xml
 92[INFO] Reading assembly descriptor: src/main/assembly/bin-unix.xml
 93[INFO] Reading assembly descriptor: src/main/assembly/src.xml
 94[INFO] Building zip: /Users/kama/ws-git/supose/supose-assembly/target/supose-assembly-0.7.1-SNAPSHOT-bin.zip
 95[INFO] Building tar: /Users/kama/ws-git/supose/supose-assembly/target/supose-assembly-0.7.1-SNAPSHOT-bin-unix.tar.gz
 96[INFO] Building tar: /Users/kama/ws-git/supose/supose-assembly/target/supose-assembly-0.7.1-SNAPSHOT-src.tar.gz
 97[INFO] Building zip: /Users/kama/ws-git/supose/supose-assembly/target/supose-assembly-0.7.1-SNAPSHOT-src.zip
 98[INFO] ------------------------------------------------------------------------
 99[INFO] Reactor Summary:
100[INFO]
101[INFO] SupoSE :: CLI ...................................... SUCCESS [ 16.145 s]
102[INFO] SupoSE :: Assembly ................................. SUCCESS [  2.425 s]
103[INFO] ------------------------------------------------------------------------
104[INFO] BUILD SUCCESS
105[INFO] ------------------------------------------------------------------------
106[INFO] Total time: 18.853 s (Wall Clock)
107[INFO] Finished at: 2016-08-09T23:59:02+02:00
108[INFO] Final Memory: 27M/437M
109[INFO] ------------------------------------------------------------------------

As you can see the Incremental Module Builder will analyze automatically which modules have been changed and will also build the dependent modules. There is one point which is not very convinient. You always need to give on command line the -b incrmental part. But this can be handled by using the .mvn/maven.config file with the following content:

1-b incremental

form this point on you can do it simply via:

1mvn package

If you like to prevent usage of the incremental module build you can simply force this by using this:

1mvn -b multithreaded package

which is the default which is used by Maven.

Currently the Incremental Module Builder is in a proof of concept state but it works for me and helped me a lot. If you find issues please don't hesitate to file in an issue report. Apart from that any feedback is welcome.