CI/CD & Build-Tools – was ist das eigentlich?

Jeder Programmierer hat irgendwann mal irgendwie angefangen zu coden. Viele haben vermutlich einfach eine Entwicklungsumgebung installiert, ein wenig Code – möglicherweise aus einem Tutorial stammend – geschrieben und dann nach einiger Zeit in der IDE auf Start gedrückt. Daraufhin hat sich wenig später entweder ein Terminal, eine grafische Oberfläche oder eine Website im Browser geöffnet. Doch was ist in der Zwischenzeit eigentlich passiert? Was macht dieser Start-Button?

So läuft ein Build-Prozess ab

Häufig wird für diesen Vorgang allgemein der Begriff Kompilieren verwendet. Doch zum einen ist dieser Begriff nicht für jede Sprache korrekt und zum anderen übersteigt der Prozess auch sonst meist die reine Kompilierung. Aus diesem Grund wird der Vorgang als Build bezeichnet, die Software wird also “gebaut”.
Die einzelnen Schritte dieses Prozesses sind vielfältig und von den eingesetzten Technologien und Programmiersprachen abhängig. Bei der Arbeit mit C++ beispielsweise wandern die Quelldateien durch den Preprocessor, den Compiler, den Assembler und den Linker.
All diese Werkzeuge können einzeln aufgerufen und parametriert werden.
In JVM-Sprachen wie Java werden die .java-Quelldateien zunächst zu .class-Binärdateien kompiliert und daraufhin, gegebenenfalls mit Resourcen wie Bildern oder Konfigurationsdateien, in die bekannten .jar-Dateien verpackt.
Für interpretierte Sprachen wie Python oder JavaScript sind solche oder ähnliche Schritte grundsätzlich nicht notwendig, jedoch werden zum Beispiel in der letzten Zeit in der Webentwicklung immer häufiger Sprachen und Technologien wie TypeScript oder LESS bzw. SASS eingesetzt, die erst in JavaScript respektive CSS transformiert werden müssen, bevor sie vom Browser umgesetzt werden können.
Auch die Verkleinerung von Dateien, oft minification oder minifying genannt, ist ein möglicher Build-Schritt in der Webentwicklung.
Ein weiterer wichtiger sprachübergreifender Aspekt ist die Beschaffung und Verwaltung von Projektabhängigkeiten über Repository-Dienste.

IDEs und Build-Tools

Neben IDEs können solche Aufgaben auch mit sogenannten Build-Tools durchgeführt werden, also mit Kommandozeilenprogrammen für ausschließlich diesen Zweck.
Aber warum sollte man Build-Tools verwenden, wenn doch Entwicklungsumgebungen, gerade auch durch Plugins, all die Aufgaben ebenfalls problemlos erledigen? Der Grund lautet schlichtweg Automatisierung. Builds sollen nicht nur vom Entwickler selbst, also von einem Menschen, ausgeführt werden können, sondern auch von technischen Systemen wie Build-Servern. Ein Build-Server ist eine Software, die zu bestimmten Zeitpunkten oder Ereignissen den jeweils aktuellen Projektstand aus der Versionsverwaltung auscheckt und dann einen Build durchführt. Ein Beispiel für einen Build zu einem bestimmten Zeitpunkt ist der sogenannte Nightly Build. Für den Fall, dass der Build-Server auf jedes Einchecken in die Versionsverwaltung reagiert, spricht man von Continuous Integration (CI). Build-Server führen meist noch weitere Aufgaben als den reinen Bau der Software aus, zum Beispiel Codeanalyse oder automatisierte Tests, um Probleme bei der Ausführung oder der Qualität frühzeitig zu erkennen. Für bestimmte Builds kann der Build-Server auch eine Veröffentlichung vornehmen. Wenn der Auslöser zur Veröffentlichung ebenfalls automatisiert ausgewertet wird, spricht man von Continuous Delivery.

Noch einmal die Definitionen auf einen Blick:

Nightly Build: Ein Build, der zu einem bestimmten Zeitpunkt, hier z.B. jede Nacht, läuft.
Continuous Integration: Wenn der Build-Server bei jedem Einchecken in der Versionsverwaltung reagiert und einen Build anstößt.
Continuous Delivery: Wenn ein Auslöser automatisiert nach dem Build eine Veröffentlichung anstößt, spricht man von Continuous Delivery.

Nun, als einfacher Hobby-Programmierer braucht bzw. hat man häufig keinen Build-Server, warum also sich mit Build-Tools beschäftigen, wenn doch in der IDE alles möglich ist?
Zum einen sind Build-Tools häufig schneller zu bedienen, da sie nur korrekt konfiguriert und dann unkompliziert aufgerufen werden müssen. Bis man all die Schritte, die das Build-Tool durch nur einen Aufruf ausführt, in einer grafischen Oberfläche gefunden und auch betätigt hat, ist meist viel Zeit vergangen, die sich immer weiter summiert. Zum anderen sind Build-Tools ohnehin schon in vielen IDEs verbaut, häufig werden die Aktionen in der grafischen Oberfläche einfach an das Build-Tool weitergeleitet. Ein Beispiel für eine solch enge Verzahnung sind Android Studio und das Build-Tool Gradle.

Der Build-Prozess sollte unabhängig von Plattform und Umgebung sein

Außerdem sollte der Build-Prozess allgemein unabhängig von Plattform und Umgebung sein, um Probleme, die man unter “It works on my machine!” zusammenfassen könnte, zu vermeiden. Dieses Ziel ist mit einem schlanken Build-Tool einfacher zu erreichen ist als mit einer komplex zu konfigurierenden IDE. Bei einem gut konfigurierten Build-Tool ist zudem die weitere Wahl des Werkzeuges, also ob und welche IDE oder welcher Editor eingesetzt werden soll, sogar innerhalb von Projekten komplett frei möglich. Jeder kann seine Arbeitsumgebung frei gestalten, solange eine Ausführung des Build-Tools möglich ist.

Welche Tools gibt es?

Für beinahe jede Sprache existiert inzwischen ein eigenes Build-Tool oder zumindest ein Plugin für ein bereits bestehendes Build-Tool. Daher gibt es bei der Wahl des Build-Tools viele Möglichkeiten und ähnlich wie bei Betriebssystemen, Programmiersprachen und Editoren sind bereits kleine Glaubenskriege ausgebrochen, welches Build-Tool nun für eine Technologie “das Beste” sei. Aus diesem Grund seien hier nur einige wenige Build-Tools und ihre Kernfunktionalität aufgeführt:

  • make – die Mutter aller Build-Tools, es existieren diverse Derivate, noch immer sehr relevant für die Sprachen C und C++
  • Maven – lange Zeit der Quasi-Standard für Java und andere JVM-Sprachen, wird inzwischen zumindest stark herausgefordert von …
  • Gradle – Standard für die Android-Entwicklung, durch Plugins geht der Funktionsumfang inzwischen weit über die JVM-Welt hinaus
  • Webpack / Browserify – sogenannte Module Bundler für das Web, transformieren in erster Linie Dateien
  • Grunt / Gulp – sogenannte Task Runner in JavaScript / Node.js, somit eher Build-Tools im klassischen Sinne, da sie eine größere Bandbreite an Aufgaben umsetzen können

Konfiguration von Build-Tools

Wie die einzelnen Build-Tools konfiguriert werden, ist stark unterschiedlich und reicht von statischen Formaten wie XML über domänenspezifische Sprachen bis hin zu Skript- oder gar Hochsprachen, bei denen dann zusätzlich zur Entwicklung der eigentlichen Software eine parallele Entwicklung des Build-Skriptes stattfindet. Dies sorgt zwar für die höchstmögliche Flexibilität, kann aber je nach Umsetzung auch für einen sehr komplexen Buildprozess sorgen. Im schlimmsten Fall muss jeder am Projekt beteiligte Entwickler neben seinen eigentlichen Stärken ein Experte für das genutzte Build-Tool sein.

Ein Großteil der Build-Tools ist über Plugins erweiterbar, bei manchen ist sogar sämtliche Funktionalität in Plugins verpackt, so dass das Build-Tool selbst nur noch eine Umgebung bereitstellt, in der die einzelnen Aufgaben umgesetzt werden können. Einige jüngere Build-Tools verwenden den Grundsatz Convention over Configuration. Das bedeutet, dass es nicht notwendig ist, das Build-Tool zu konfigurieren, wenn man sich an gewisse Konventionen hält. Beispielsweise reicht in Gradle die Zeile apply plugin: 'java' aus, um einen vollständigen Java-Buildprozess mit Kompilierung, Tests und Verpacken nutzen zu können. In diesem Fall sucht Gradle die Quelldateien für den Produktiveinsatz unter der Ordnerstruktur src/main/java und die Quelldateien für Tests unter src/test/java, so wie es der Konvention der Java-Welt entspricht. Möchte man diese Konvention brechen, muss man in Kauf nehmen, Gradle die Orte explizit zu nennen, an denen nach Quelldateien gesucht werden soll.

Dieser Artikel sollte einen allgemeinen Überblick über die Funktionsweise und Bedeutung von Build-Tools bieten und dabei möglicherweise auch ein wenig die Furcht vor ihrem Einsatz nehmen. Selbst wenn die ausschließliche Verwendung einer IDE oder ähnlicher grafischer Werkzeuge zunächst bequemer erscheinen mag, lohnt sich die Nutzung eines Build-Tools mit steigendem Projektumfang und zunehmendem Zeitaufwand (fast) immer. Ab einem gewissen Grad an Professionalisierung, also beispielsweise bei der Arbeit, muss man sich als Entwickler ohnehin irgendwann mit dem Thema beschäftigen, also lohnt es sich, sich frühzeitig einzuarbeiten.

Rückmeldungen