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]]