Putting Maven build directories out-of-tree
So you want to have Maven put its build output somewhere out-of-tree.
There are several reasons to do this:
- You have lots of RAM, and want to speed up builds by putting class files in RAM.
- You have an SSD, and want to reduce needless wear cycles by putting class files in RAM (or on a spinning disk).
- Your source tree is on a network file system, and you want compilation output to be local.
Helpfully, the Maven Way is to have all Maven-generated output go to
a dedicated directory, target/
, where it can be easily
separated. Theoretically, you can probably set
project.build.directory
to point to wherever you want, and
get Maven to build somewhere else. However, if parts of the build system
assume that output goes into target/
(a questionable
assumption, but I make it myself in pieces of the LensKit site
generation workflow).
So, I have put together a Maven snippet you can put in your project’s
POM to enable support for out-of-tree builds, automatically creating a
work directory in some external directory (specified by the
external.build.root
Maven property) and making
target/
a symbolic link to this work directory. Here it is,
just put it in <profiles>
in your
pom.xml
:
If you set external.build.root
to
e.g. /tmp/maven-builds
(at the command line with
-D
, or in your ~/.m2/settings.xml
), then all
your Maven output will go into
/tmp/maven-builds/<group>:<artifact>
.
mvn clean
will delete this directory tree and remove the
symbolic link. If you don’t have a external.build.root
,
then the profile will not activate and your code will be built as
normal.
And if the directory you point external.build.root
to is
a RAM-based file system (tmpfs
on Linux), Maven compiler
output will all be stored in RAM and not hit disk at all. On many modern
Linux distros, /run
is available as a tmpfs
;
some (including Fedora 19) also make /tmp
a
tmpfs
by default.
A few caveats and explanations:
- This won’t work on Windows, I don’t think, as there are no symbolic links.
- Only works on Java 7, I use NIO.2 to make the symbolic links.
- Why not use
maven-antrun-plugin
? Because it creates an Ant file intarget
, then runs it; this results intarget/
being created before the code to make the symbolic link is run. - Why use
script-maven-plugin
instead ofgmaven-plugin
? Only because one of the builds I’m using this in usesgmaven-plugin
configured with Groovy 2, which breaks theexecute
goal.script-maven-plugin
uses generic BSF and avoids this problem.
Have fun!