Maven Tmpfs
Sun, 8 September, 2013 (600 Words)Je suis un utilisateur convaincu de [maven](), malgré ces défauts, le moto
“Convention over configuration” me va vraiment bien. Que ce soit au boulot ou
à la maison, j’ai plus d’ordinateurs équipés de ssd (ou de mémoire flash) que de
disque traditionnel (mécanique ?). Pour augmenter un peu la durée de vie de
ces disques SSD, j’ai cherché à savoir comment déporter le build de maven
(qui, pour rappel, se passe dans le dossier target/
) hors du SSD ; ici ce
sera dans le dossier /tmp/
qui est monté en mémoire (merci tmpfs
),
mais on peut imaginer déporter ça sur un autre disque, etc.. Après quelques
recherches j’ai trouvés quelques inspirations.
Limitations
Dans la solution présentée ci-dessous les principales limitations sont les suivantes (que j’essaierais de diminuer au fil du temp ;P) :
- Il est nécessaire de modifier le pom.xml du projet ; cela ne s’appliquera donc pas à tous les projets maven sans modification du pom.xml.
- Cela ne fonctionne que sur une plateforme qui support les liens symboliques (Linux, Mac OS X, et autre UNIX).
- Cela ne fonctionne qu’avec Java 7 ou plus.
- Si vous utilisez m2e, il va gentillement gueuler et c’est moche ; pour résoudre le problème, il faut faire un tour vers M2E plugin execution not covered.
Pour [maven](), le dossier target/
vient de la propriété
project.build.directory
. Dans la théorie, il suffirait de modifier (dans
$HOME/.m2/settings.xml
) cette propriété et le tour serait jouer.
Malheuresement ce n’est pas possible, project.build.directory
est une
propriété interne et n’est, à priori, pas modifiable.
Notre souhait est le suivant :
- Le build doit se faire dans
/tmp/m2/
, ce qui pour un projet se traduit par/tmp/m2/${groupId}:${artifactId}
. - Le dossier
target/
dans les sources est un lien symbolique vers le dossier dans/tmp/m2/
- On passe par un profile qui n’est pas actif par défaut (pour ne pas
faire chier le monde) mais activable via une propriété (maven nous permet
de le faire et c’est cool
^_^
). La propriété utilisée seraexternal.build.root
.
Le code ci-dessous est repris directement de mon inspiration1. Il
s’occupe de créer le dossier ${groupId}:${artifactId}
dans
external.build.root
et de faire le lien dans le dossier courant.
<project>
<!-- […] -->
<profiles>
<profile>
<id>external-build-dir</id>
<activation>
<activeByDefault>false</activeByDefault>
<property>
<name>external.build.root</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>com.alexecollins.maven.plugin</groupId>
<artifactId>script-maven-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<id>prep-work-tree</id>
<goals>
<goal>execute</goal>
</goals>
<phase>initialize</phase>
<configuration>
<script>
import java.nio.file.*
def dir =
"${external.build.root}/${project.groupId}:${project.artifactId}"
println "using Maven dir ${dir}"
def dirPath = Paths.get(dir)
if (!Files.exists(dirPath)) {
Files.createDirectories(dirPath)
}
def target = Paths.get("${project.build.directory}")
if (!Files.exists(target)) {
Files.createSymbolicLink(target, dirPath)
}</script>
</configuration>
</execution>
<execution>
<id>drop-symlink</id>
<goals>
<goal>execute</goal>
</goals>
<phase>clean</phase>
<configuration>
<script>
import java.nio.file.*
def target = Paths.get("${project.build.directory}")
if (Files.isSymbolicLink(target)) {
Files.delete(target)
}
</script>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>1.8.6</version>
</dependency>
</dependencies>
<configuration>
<language>groovy</language>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<!-- […] -->
</project>
Ainsi, il suffit ensuite d’avoir quelques choses du genre dans son
$HOME/.m2/settings.xml
pour que les builds qui ont ce profil se build
dans /tmp/m2/
. On peut aussi ne rien avoir dans $HOME/.m2/settings.xml
et utilise -Dexternal.build.root=/tmp/m2/
avec la commande mvn
.
<settings>
<!-- […] -->
<profiles>
<profile>
<id>build-in-ramfs</id>
<properties>
<external.build.root>/tmp/m2/</external.build.root>
</properties>
</profile>
</profiles>
<activeProfiles>
<activeProfile>build-in-ramfs</activeProfile>
</activeProfiles>
<!-- […] -->
</settings>