Build-Automatisierung
Transcription
Build-Automatisierung
Software-Engineering 2: Automatische Build-Werkzeuge Prof. Dr. Axel Böttcher 22. Oktober 2012 Motivation 1 Entwicklungprozesse in der Praxis, Beispiel Facbook: Our development cycle is extremely fast, and we’ve built tools to keep it that way. It’s common to write code and have it running on the live site a few days later. This comes as a pleasant surprise to engineers who have worked at other companies where code takes months or years to see the light of day. If you work with us, you will be able to make an immediate impact. (siehe https://www.facebook.com/careers/teams/engineering, kopiert am 18.10.2012) Motivation 2: Die IDE-Konfiguration ist Entwickler-spezifisch Zum Beispiel das Eclipse .classpath-file: <?xml version="1.0" encoding="UTF-8"?> <classpath> <classpathentry including="**/*.java" kind="src" output="target/test-classes" path="src/test/java"/> <classpathentry including="**/*.java|*.properties|*.xml" kind="src" path="src/main/java"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> <classpathentry kind="lib" path="/Users/axel/Eclipse/ShareIt/lib/antlr-2.7.6.jar"/> <classpathentry kind="lib" path="/Users/axel/Eclipse/ShareIt/lib/junit-3.8.jar"/> <classpathentry kind="lib" path="/Users/axel/Eclipse/ShareIt/lib/architecture-rules-2.1.1.jar"/> <classpathentry kind="lib" path="/Users/axel/Eclipse/ShareIt/lib/asm-1.5.3.jar"/> </classpath> Was passiert zum Beispiel, wenn ab sofort Junit Version 4.10 verwendet verden soll? =⇒Abstraktion erforderlich Motivation Frage: welche Schritte sind notwendig, um Software auslieferfertig zu bauen? Maven Konzepte I Abstrakte Projektbeschreibung durch ein Project Object Model (POM): pom.xml I Convention over Configuration: was nicht explizit vorgegeben ist, wird nach einer Konvention behandelt. I Declarative Execution I Build anhand von Life Cycles“ ” Plugin-Mechanismus. Durch Herunterladen von Plugins nach Bedarf sehr schlanke Basis. I I Verwaltung von Abhängigkeiten (Dependencies) in Repositories Die Maven Koordinaten groupId Bezeichnet die Organisationseinheit (Gruppe, Abteilung, Firma ...), die für das Projekt verantwortlich ist atifactId Bezeichnet ein spezielles Projekt dieser Gruppe version Die Version des Projekts packaging Auslieferungsformat (jar, war, ...) Archetypen Ein maven-archetyp ist ein Projekt-Prototyp (Vorlage), z.B. Web-Projekt, Web-Projekt auf Jetty-Basis, J2EE-Projekt ........ (über 600 vordefinierte Archetypen) Mit mvn archetype:generate alleine zeigt Maven eine Liste aller verfügbarer Projekt-Archetypen an und ermöglicht eine interaktive Konfiguration. Start: Erzeugen eines Projektes mvn archetype:generate\ -DinteractiveMode=false\ -DgroupId=edu.hm.se2\ -DartifactId=demo\ -DpackageName=edu.hm.cs.se2.demo\ -Dpackage=edu.hm.cs.se2.demo erzeugt ein simples Stub-Projekt mit folgendem pom: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>edu.hm.se2</groupId> <artifactId>demo</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>demo</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </project> Build Lifecycles Maven kennt standardmäßig die drei Build Lifecycles default, clean und site, bestehend aus jeweils mehreren abhängigen Phasen: Build Lifecycles Maven kennt standardmäßig die drei Build Lifecycles default, clean und site, bestehend aus jeweils mehreren abhängigen Phasen: validate initialize generate-sources pre-clean clean post-clean pre-site site post-site compile site-deploy test package install deploy Build Lifecycles Maven kennt standardmäßig die drei Build Lifecycles default, clean und site, bestehend aus jeweils mehreren abhängigen Phasen: validate initialize generate-sources pre-clean clean post-clean pre-site site post-site compile test package install site-deploy Der Aufruf mvn <phase> führt alle Phasen einschließlich der angegebenen aus. Beispiel: mvn test Auch kombinierbar: mvn clean test deploy Plugins und Goals Die Durchführung der Arbeit wird an Goals von Plugins delegiert. Diese Goals sind auch direkt aufrufbar: mvn plugin:goal Beispiel ausführen dss Gompile-goal des Compiler-Plugins: mvn compiler:compile mvn help:describe -Dplugin=compiler -Dfull Direktes Ausführen von Plugins prüft keine Vorbedingungen, wie bei Verwendung der Phasen. Deklaration von Abhängigkeiten (Dependencies) <project> <groupId>edu.hm.se2</groupId> <artifactId>demo</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.8</version> <scope>test</scope> </dependency> </dependencies> Dependencies werden rekursiv aufgelöst. mvn dependency:resolve zeigt alle Abhängigkeiten an. Repositories Remote: Maven central, oder konfigurierbar Onsite: Nexus oder Artifactory-Server (für externe Dependencies als Proxies) In lokalem Verzeichnis ~/user/.m2/... Deployment lokal oder onsite möglich. Maven central local 3rd-party on-site Das Programm make I I Sehr mächtiges Build-Management-Werkzeug Ursprünglich 1977 für UNIX entwickelt I I Heute verschiedene Varianten, zum Beispiel: I I I Standard Build-Werkzeug für sehr viele Projekte, auch heute noch! nmake (Microsoft) gmake (GNU make, beispielsweise in Linux) Kommandozeilenbasiert I Typischer Aufruf: make Programmname I Ohne Argument erzeugt make meist das gesamte Programmpaket Das Makefile I make sucht standardmäßig eine Datei namens Makefile oder makefile I Bei OpenSource-Projekten wird das Makefile mit dem Quellcode ausgeliefert Das Makefile enthät die komplette Beschreibung, wie make die einzelnen Dateien eines Projektes verarbeiten soll: I I I I Welche Ergebnisdateien (targets) sollen erzeugt werden? Beispiel: Eine .class-Datei Von welchen Ausgansdateien (dependencies) hängen die jeweiligen targets ab? Beispiel: Eine oder mehrere .java-Quelldatei(en) Wie sollen die jeweiligen Ergebnisdatein erzeugt werden (commands)? Beispiel: Compilieren der enstprechenden .class-Dateien mit javac Eine Regel im Makefile I Das Erstellen einer Datei wird durch eine Rule (Regel) festgelegt: target [target ...]: [dependency ...] command ... I Beispiel für eine Rule: editor.class: editor.java javac -g editor.java I Die Regel besagt: Wenn editor.class (das target) nicht vorhanden ist oder editor.java (eine dependency) neuer ist als editor.class, dann führe den Befehl (command) javac -g editor.java aus! I Achtung: Vor jedem command muss ein Tabulator -Zeichen stehen! Makefile für ein kleines Projekt I ’#’ am Zeilenanfang: Kommentar I # Makefile fuer ein kleines Projekt # JAR-Datei aus zwei Klassen erstellen project.jar: editor.class utility.class jar cf project.jar editor.class utility.class # Java-Quellcode compilieren editor.class: editor.java javac -g editor.java utility.class: utility.java javac -g utility.java Variablen im Makefile I Variablen werden mit Zuweisungsausdruck definiert und belegt I Verwendung einer Variablen mit $(VARIABLE): reine Textersetzung I Beispiel: # Makefile fuer ein kleines Projekt JFLAGS = -g JAVAC = /absoluter/pfad/zu/meiner/version/von/javac ... editor.class: editor.java $(JAVAC) $(JFLAGS) editor.java I Vorteile: Leichter lesbar und wartbar Pattern Rules und automatische Variablen Eine Pattern Rule enthält das %-Zeichen. Eine Regel %.class : %.java gibt an, wie ein beliebiges stem.class aus stem.java zu bauen ist. $@ Name von target $< Name der ersten dependency $? Name aller Dependencies, die aktueller sind als das Target, mit Leerschritten getrennt $∗ Der Stamm (engl.: stem) (bei %.ext der Dateiname ohne Extension) Beispiel: %.class: %.java javac -g $< ant I In Java geschriebenes Werkzeug I Besonders für die Entwicklung im Java-Umfeld geeignet I XML-basiertes Build-File (build.xml) I Viele Built-in Tasks: jar, javac, javadoc, chmod, copy, cvs, ant, ... Grundsätzliche Struktur der Build-Files <project name="myproject" default="dist" basedir="."> <target name="init"> ... </target> <target name="compile" depends="init"> ... </target> <target name="dist" depends="compile,init"> ... </target> </project> Eigene ant-Tasks I Eigene Tasks erben von org.apache.tools.ant.Task. I Implementierung der Methode void execute() I Ggf. auch init() redefinieren I Übergabe der Build-Parameter über Getter und Setter, deren Namen zu XML-Attributen passen müssen <target name="mmix-test" depends="declare" description="bla <echo message="MMIX assembly:"/> <mmixal expand="yes" buffer="250" listfile="xxx.mml"/> </target> Erfordert setBuffer(...) und setListfile(...) ant vs. make ant: I Besser lesbar; intuitiver (aber mehr Schreibarbeit). I Java-zentriert. Alle Tasks sind in Java geschrieben I Abhängigkeiten werden beschrieben in Form von Arbeitsschritten; z.B. entscheidet die Compile-Task, was zu übersetzen ist. Bei make angegeben durch Zeitstempel von Dateien. (Dadurch bei Ant manchmal mehr Doppelarbeit). make: I Eingeschränkt portierbar I Beliebige Shell-Kommandos in Tasks integrierbar (Verhalten ändert sich aber, wenn sich externe Programme ändern) I Sehr mächtig; Tendenz zur Unlesbarkeit. I Problem, wenn Abhängigkeiten zu beschreiben vergessen werden. Eclipse-Integration I ant wird von Eclipse direkt unterstützt (Editor, Ausführung über Kontextmenü, Code-Assist) I Die Plugin-Sammlung zur Entwicklung in C/C++ (CDT) bietet ähnliche Unterstützung für Makefiles