home

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

2013-09-08-maven-tmpfs.org (6973B)


      1 #+title: Maven Tmpfs
      2 #+date: <2013-09-08 Sun>
      3 #+filetags: maven tmpfs ssd
      4 #+setupfile: ../templates/post.org
      5 
      6 * Introduction
      7 
      8 Je suis un utilisateur convaincu de [[http://maven.apache.org/][maven]], malgré ces défauts, le
      9 moto *"Convention over configuration"* me va vraiment bien. Que ce soit
     10 au boulot ou à la maison, j'ai plus d'ordinateurs équipés de ssd (ou de
     11 mémoire flash) que de disque traditionnel (mécanique ?). Pour augmenter
     12 un peu la durée de vie de ces disques SSD, j'ai cherché à savoir comment
     13 /déporter/ le /build/ de maven (qui, pour rappel, se passe dans le
     14 dossier =target/=) hors du SSD ; ici ce sera dans le dossier =/tmp/= qui
     15 est monté en mémoire (merci =tmpfs=), mais on peut imaginer déporter ça
     16 sur un autre disque, etc.. Après quelques recherches j'ai trouvés
     17 quelques inspirations.
     18 
     19 #+BEGIN_QUOTE
     20   *Limitations*
     21 
     22   Dans la solution présentée ci-dessous les principales limitations sont
     23   les suivantes (que j'essaierais de diminuer au fil du temp ;P) :
     24 
     25   1. Il est nécessaire de modifier le pom.xml du projet ; cela ne
     26      s'appliquera donc pas à tous les projets maven sans modification du
     27      pom.xml.
     28   2. Cela ne fonctionne que sur une plateforme qui support les liens
     29      symboliques (Linux, Mac OS X, et autre UNIX).
     30   3. Cela ne fonctionne qu'avec Java 7 ou plus.
     31   4. Si vous utilisez m2e, il va gentillement gueuler et c'est moche ; pour résoudre le
     32      problème, il faut faire un tour vers [[http://wiki.eclipse.org/M2E_plugin_execution_not_covered][M2E plugin execution not covered]].
     33 #+END_QUOTE
     34 
     35 Pour [[http://maven.apache.org/][maven]], le dossier =target/= vient de la propriété
     36 =project.build.directory=. Dans la théorie, il suffirait de modifier
     37 (dans =$HOME/.m2/settings.xml=) cette propriété et le tour serait jouer.
     38 Malheuresement ce n'est pas possible, =project.build.directory= est une
     39 propriété interne et n'est, à priori, pas modifiable.
     40 
     41 Notre souhait est le suivant :
     42 
     43 1. Le build doit se faire dans =/tmp/m2/=, ce qui pour un projet se
     44    traduit par =/tmp/m2/${groupId}:${artifactId}=.
     45 2. Le dossier =target/= dans les sources est un lien symbolique vers le
     46    dossier dans =/tmp/m2/=
     47 3. On passe par un *profile* qui n'est *pas actif* par défaut (pour ne
     48    pas faire chier le monde) mais *activable via une propriété* (maven
     49    nous permet de le faire et c'est cool =^_^=). La propriété utilisée
     50    sera =external.build.root=.
     51 
     52 Le code ci-dessous est repris directement de mon inspiration[fn:1]. Il
     53 s'occupe de créer le dossier =${groupId}:${artifactId}= dans
     54 =external.build.root= et de faire le lien dans le dossier courant.
     55 
     56 #+begin_src xml
     57 <project>
     58     <!-- […] -->
     59     <profiles>
     60         <profile>
     61             <id>external-build-dir</id>
     62             <activation>
     63                 <activeByDefault>false</activeByDefault>
     64                 <property>
     65                     <name>external.build.root</name>
     66                 </property>
     67             </activation>
     68             <build>
     69                 <plugins>
     70                     <plugin>
     71                         <groupId>com.alexecollins.maven.plugin</groupId>
     72                         <artifactId>script-maven-plugin</artifactId>
     73                         <version>1.0.0</version>
     74                         <executions>
     75                             <execution>
     76                                 <id>prep-work-tree</id>
     77                                 <goals>
     78                                     <goal>execute</goal>
     79                                 </goals>
     80                                 <phase>initialize</phase>
     81                                 <configuration>
     82                                     <script>
     83                                         import java.nio.file.*
     84                                         def dir =
     85                                         "${external.build.root}/${project.groupId}:${project.artifactId}"
     86                                         println "using Maven dir ${dir}"
     87                                         def dirPath = Paths.get(dir)
     88                                         if (!Files.exists(dirPath)) {
     89                                         Files.createDirectories(dirPath)
     90                                         }
     91                                         def target = Paths.get("${project.build.directory}")
     92                                         if (!Files.exists(target)) {
     93                                         Files.createSymbolicLink(target, dirPath)
     94                                         }</script>
     95                                 </configuration>
     96                             </execution>
     97                             <execution>
     98                                 <id>drop-symlink</id>
     99                                 <goals>
    100                                     <goal>execute</goal>
    101                                 </goals>
    102                                 <phase>clean</phase>
    103                                 <configuration>
    104                                     <script>
    105                                         import java.nio.file.*
    106                                         def target = Paths.get("${project.build.directory}")
    107                                         if (Files.isSymbolicLink(target)) {
    108                                         Files.delete(target)
    109                                         }
    110                                     </script>
    111                                 </configuration>
    112                             </execution>
    113                         </executions>
    114                         <dependencies>
    115                             <dependency>
    116                                 <groupId>org.codehaus.groovy</groupId>
    117                                 <artifactId>groovy</artifactId>
    118                                 <version>1.8.6</version>
    119                             </dependency>
    120                         </dependencies>
    121                         <configuration>
    122                             <language>groovy</language>
    123                         </configuration>
    124                     </plugin>
    125                 </plugins>
    126             </build>
    127         </profile>
    128     </profiles>
    129     <!-- […] -->
    130 </project>
    131 #+end_src
    132 
    133 Ainsi, il suffit ensuite d'avoir quelques choses du genre dans son
    134 =$HOME/.m2/settings.xml= pour que les builds qui ont ce profil se
    135 /build/ dans =/tmp/m2/=. On peut aussi ne rien avoir dans
    136 =$HOME/.m2/settings.xml= et utilise =-Dexternal.build.root=/tmp/m2/=
    137 avec la commande =mvn=.
    138 
    139 #+begin_src xml
    140 <settings>
    141     <!-- […] -->
    142     <profiles>
    143         <profile>
    144             <id>build-in-ramfs</id>
    145             <properties>
    146                 <external.build.root>/tmp/m2/</external.build.root>
    147             </properties>
    148         </profile>
    149     </profiles>
    150     <activeProfiles>
    151         <activeProfile>build-in-ramfs</activeProfile>
    152     </activeProfiles>
    153     <!-- […] -->
    154 </settings>
    155 #+end_src
    156 
    157 
    158 [fn:1] [[http://elehack.net/writings/programming/maven-target-in-tmpfs][PuttingMaven build directories out-of-tree]] par [[http://elehack.net/][Michal Ekstrand]]