"Das war schon immer so", "Da kann ja jeder kommen" und andere Leitsätze
Egal, ob es make, ant oder maven waren: Meist bestimmte das Werkzeug den Build und nicht die Entwickler oder die Art der Software, die es zusammenzubauen galt. Im wesentlichen nutze ich die Werkzeuge daher immer nur deshalb, weil sie Verfügbar im jeweiligen Kontext sind, oder weil es einfach eine breite Masse von Nutzern gibt, sodaß man nicht so alleine ist.Im Moment nutze ich in jeden professionellen Projekt Maven und weiß daher, welche Kosten es entfesselt, um seinen Nutzen zu bringen. Den Nutzen der vernünftigen Abhängigkeitsumsetzung will ich nicht missen, aber der Rest ist weder gut lesbar noch gut im Ablauf verständlich. Ich finde die Schreibeweisen nach wie vor unleserlich und das Werkzeug unverständlich in seiner Sprache und Komplexität.
Peak Maven?
Nachdem ich also nun viele Jahre lang leidenschaftslos beim Buildwerkzeug war, sehe ich jetzt auf die umfassenden Lösungenmit Maven in großen Projekten (wie dem CoreMedia 7 Blueprint) wie auf die letzten Werke des Maven-Barock. Großartige umfassende Lösungen, die mir netto sehr helfen (weil ich sie nicht selbst schreiben mußte), Maven und das Projekt im Griff zu halten, und die so vieles bedacht haben, das ich nicht einmal bemerke.Kleine Danksagung zum 1.8er Release
Den Grund, warum sich meine Sicht auf Buildwerkzeuge nun geändert hat, möchte ich anhand einer kleinen Begebenheit illustrieren: Immer wenn ich kleinere Softwareprojekte anderen Menschen bereitstellen will, reicht es nicht, daß ich reprodzierbar aus meiner IDE getestet eine Software purzeln lassen kann. Bevor ich also beschreibe, was ich getan habe und was eventuell bei anderen dann gerade einmal nicht genauso aussieht, schreibe ich lieber gleich die notwendigen Build-Skripte, um den Vorgang zu dokumentieren und dabei gleich zu automatisieren.Bei tangram habe ich mich noch lange mit der Auswahl des Werkzeugs gequält, weil ich mich nicht auch noch in meiner Freitzeit mit Maven herumschlagen wollte und kein anderes Tool mir spontan unter "das machen alle so" oder "das war einfach da" vorlag. Letztlich hat Gradle über Maven gewonnen und ich habe mich ahnungslos in die Umsetzung gestürzt. Heute verstehen wir uns recht gut.
Als ich vor kurzem wieder ein paar Zeilen Code herausgeben wollte, stand ich mit einem kompletten Fremdprojekt und einem alten ANT-Script da. JFileSync sollte - weit vor der NSA-Affäre, die mir keine neuen Erkenntnisse brachte - um für mich notwendige Features erweitert werden. Das Ergebnis wollte ich wieder gerne reprodzierbar als nutzbares Programm erzeugen können. Und das ging mit Gradle so erschreckend gut und einfach - und mit wenigen Worten, daß ich mich gleich wieder in Goodies für ein schöneres Ergebnis stürzen konnte.
Gradle-Deutsch / Deutsch-Gradle
Wir haben also ein Java-Programmapply plugin: 'java'
Und wir hätten den Code gerne sauber in aktueller Java-Version, mit UTF-8 und ohne alten Kram.
sourceCompatibility = 1.7
targetCompatibility = 1.7
compileJava.options.encoding = 'UTF-8'
compileJava.options.deprecation = true
Der Source-Code und die Ressourcen finden sich zusammen im Verzeichnis src.
sourceSets {
main {
java {
srcDir 'src'
}
resources {
srcDir 'src'
}
}
}
Damit man das ganze kompilieren kann, muß man aus diesen Quellen
repositories {
maven { url "http://repo1.maven.org/maven2" }
maven { url "http://sardine.googlecode.com/svn/maven/" }
maven { url "http://repo2.maven.org/maven2/org/bouncycastle" }
}
diese Dinge besorgen
dependencies {
compile 'org.slf4j:slf4j-api:1.5.8'
compile 'org.slf4j:slf4j-log4j12:1.5.8'
compile 'org.apache.httpcomponents:httpclient:4.2.5'
compile 'commons-lang:commons-lang:2.6'
compile 'org.apache.commons:commons-compress:1.3'
compile 'org.bouncycastle:bcprov-jdk16:1.46'
compile 'javax.servlet:servlet-api:2.5'
}
Ach, und ich würde gerne weiterhin Eclipse nutzen
apply plugin: 'eclipse'
Könnt Ihr Euch bitte auf ein Vereichnis für den Output einigen?
eclipse.classpath.conventionMapping.defaultOutputDir = {
new File(project.projectDir, 'build/classes/main')
}
Du solltest aber sauberer Arbeiten als meine IDE!
defaultTasks 'clean', 'build'
Das ganze soll am Ende ein benutzbares Programm werden.
apply plugin: 'application'
Den Einstieg findest Du dabei in dieser Java-Klasse:
mainClassName = 'jfs.JFileSync'
Wow! Du hast ja automatisch Start-Scripts für Unix und Windows erzeugt! Danke! Ich hätte da noch ein paar Verbesserungsvorschläge...
startScripts {
doLast {
// Add some more reasonable memory settings to JFileSync3
unixScript.text =
unixScript.text.replace('DEFAULT_JVM_OPTS=""',
'DEFAULT_JVM_OPTS="-ms1280m -mx1536m -Xms1280m -Xmx1536m"')
windowsScript.text =
windowsScript.text.replace('DEFAULT_JVM_OPTS=',
'DEFAULT_JVM_OPTS=-ms1280m -mx1536m -Xms1280m -Xmx1536m')
windowsScript.text = windowsScript.text.replace('java.exe', '%JAVA_CMD%')
windowsScript.text =
windowsScript.text.replace('@rem Find %JAVA_CMD%',
'set JAVA_PREFIX=start ... java.exe')
windowsScript.text =
windowsScript.text.replace('"%JAVA_EXE%" %DEFAULT_JVM_OPTS%',
'%JAVA_PREFIX% "%JAVA_EXE%" %DEFAULT_JVM_OPTS%')
}
}Und ich habe da gerade diesen netten Launcher für Java-Anwendungen unter Windows gefunden
buildscript {
repositories {
maven { url "http://repo.smokejumperit.com" }
ivy {artifactPattern 'http://gradle-launch4j.googlecode.com/files/[module]-[revision].[ext]'}
}
dependencies {
classpath 'com.smokejumperit:gradle-plugins:0.8.2'
classpath 'edu.sc.seis:gradle-launch4j:1.0.5'
}
}
den will ich haben!
apply plugin: 'launch4j'
Schreib doch bitte einfach rein, wer das gemacht hat, danke.
launch4j {
mainClassName = project.mainClassName
version = '3.0.0'
copyright = '(C) 2002-2013, J. Heidrich, M. Goellnitz'
downloadUrl = 'https://www.dropbox.com/s/3n4snlbw9tyjgec/JFileSync3.zip'
supportUrl = 'https://github.com/mgoellnitz/JFileSync3'
icon = "$project.projectDir/win/JFileSync.ico"
dontWrapJar = true
xmlFileName = 'JFileSync3-launcher.xml'
initialHeapSize = 1024
maxHeapSize = 1536
}
Ach, und wo Du gerade da bist: Pack das doch noch mal etwas anders ein, als sonst
distZip {
into(project.name) {
from "$buildDir/launch4j"
include '*.exe'
include '*.xml'
}
into(project.name) {
from '.'
include 'legal/*.*'
include 'profiles/*.*'
include 'README.md'
}
}
Oh, äh. Testen. Machst Du das noch schnell? Ich habe da vier Beispiele abgelegt.
apply plugin:com.smokejumperit.gradle.ExecPlugin
task(encryptionTest) << {
// Extract distribution
println "Extracting distribution"
ant.unzip(src: "$buildDir/distributions/${project.name}.zip", dest: "$buildDir")
// Extract test data
println "Extracting test data"
ant.unzip(src: "test/test-folders.zip", dest: "$buildDir/${project.name}")
println "Encrypting"
String cmd = "";
cmd = "cmd /c bin${File.separator}${project.name} -config 1encrypt.xml -nogui -nohistory -quiet"
project.exec(cmd, "$buildDir/${project.name}")
println "Decrypting taking every folders metadata into account"
cmd = "cmd /c bin${File.separator}${project.name} -config 2decrypt1.xml -nogui -nohistory -quiet"
project.exec(cmd, "$buildDir/${project.name}")
println "Decrypting ignoring every folders metadata"
cmd = "cmd /c bin${File.separator}${project.name} -config 3decrypt2.xml -nogui -nohistory -quiet"
project.exec(cmd, "$buildDir/${project.name}")
println "And now please compare by hand"
cmd = "cmd /c bin${File.separator}${project.name} -config 4compare.xml -nohistory"
project.exec(cmd, "$buildDir/${project.name}")
}
Macht das bitte nicht nur in der Kürze sondern auch in so kurzer Zeit und so, daß man es immer wieder lesen kann, mit anderen Werkzeugen. Für mich ist Gradle nun weiterhin die erste Wahl in allen Projekten, in denen ich die Wahl habe.
Keine Kommentare:
Kommentar veröffentlichen