coldwa.st
Alle LeitfädenProgrammierungWebDatenWerkzeugeDatenbankenHaskellKonzepteCabal & BuildsToolchainCompilerPerformanceEditor & HLS

Programmierung · Konzepte · Compiler

Was ist ein Compiler?

Von ColdwastAktualisiert am 23. Juni 20268 Min. Lesezeit#compiler#concepts#haskell
Hervorgehobener C++-Quellcode mit Zeilennummern in einem dunklen Editor
Quellcode wie dieser — Variablen, Schleifen und Bedingungen, von einem Menschen geschrieben — ist die Eingabe, die der Compiler liest und in ein lauffähiges Programm verwandelt.

Du schreibst ein Programm in einer Sprache, die du lesen kannst: Wörter, Einrückung, sinnvolle Namen. Der Prozessor deiner Maschine versteht davon nichts — er führt rohe Binärbefehle aus. Das Werkzeug, das die Lücke überbrückt, ist der Compiler. Dieser Leitfaden erklärt, was ein Compiler ist, welche Stufen er durchläuft, wie er sich von einem Interpreter unterscheidet und wo ein Compiler wie GHC einzuordnen ist, wenn du Haskell schreibst.

Die kurze Definition

Ein Compiler ist ein Programm, das Quellcode aus einer Sprache in eine andere Form übersetzt — meist in den Maschinencode, den ein Computer direkt ausführen kann. Du gibst ihm die Textdateien, die du geschrieben hast, und er erzeugt eine ausführbare Datei (oder ein Zwischenformat), die die Maschine oder eine Laufzeitumgebung ausführen kann. Die Übersetzung geschieht einmal, im Voraus, und das Ergebnis läuft allein, ohne dass der Compiler anwesend sein muss.

Wie ein Compiler arbeitet, Stufe für Stufe

Ein Compiler übersetzt nicht in einem Sprung. Er durchläuft eine Kette von Stufen, von denen jede ihr Ergebnis an die nächste weitergibt:

  • Lexikalische Analyse (Tokenisierung): der Quelltext wird in kleine Einheiten zerlegt — Schlüsselwörter, Namen, Zahlen, Symbole — genannt Token.
  • Syntaktische Analyse (Parsing): die Token werden zu einem Baum angeordnet, der die Struktur des Programms gemäß der Grammatik der Sprache widerspiegelt.
  • Semantische Analyse: der Compiler prüft, ob das Programm Sinn ergibt — ob Namen definiert sind, Typen zusammenpassen, die Regeln der Sprache gelten. Hier werden viele deiner Fehler gefunden.
  • Optimierung: der Compiler schreibt das Programm in ein schnelleres oder kleineres Äquivalent um, ohne zu ändern, was es tut.
  • Codeerzeugung: zuletzt gibt er die Zielausgabe aus — Maschinencode oder eine Zwischendarstellung, die ein anderes Werkzeug fertigstellt.

Findet eine Stufe ein Problem, bekommst du einen Kompilierfehler und es wird kein Programm erzeugt. Das ist der Handel des Compilers: Er weigert sich, fehlerhaften Code zu bauen, sodass eine ganze Klasse von Fehlern abgefangen wird, bevor das Programm überhaupt läuft.

Ein Entwickler mit Kopfhörern am Schreibtisch mit Monitor und Laptop, die Code zeigen, in einem dunkelblauen Raum
Ein Entwickler bei der Arbeit: Du schreibst und bearbeitest den Quellcode, dann startest du den Compiler, der deine Dateien liest und das lauffähige Programm erzeugt.

Compiler vs Interpreter

Der andere gängige Ansatz ist der Interpreter, der deinen Quellcode liest und ihn bei jeder Ausführung direkt Zeile für Zeile ausführt — es wird keine separate ausführbare Datei im Voraus gebaut. Ein Compiler übersetzt das ganze Programm einmal, vorab, in eine Form, die die Maschine allein ausführt.

Der praktische Unterschied: Kompilierte Programme starten und laufen meist schneller, weil Übersetzung und Optimierung schon geschehen sind, und Fehler zeigen sich zur Kompilierzeit. Interpretierte Programme sind schneller auszuprobieren und flexibler, machen die Übersetzungsarbeit aber bei jeder Ausführung neu. Viele echte Toolchains mischen beides — sie kompilieren zu einer Zwischenform und führen diese dann auf einer virtuellen Maschine aus.

Wo GHC und Haskell einzuordnen sind

Wenn du Haskell schreibst, ist der Compiler, zu dem du greifst, GHC (der Glasgow Haskell Compiler). Er liest deine .hs-Quelldateien, prüft sie gründlich auf Typen, optimiert das Ergebnis und erzeugt eine native ausführbare Datei, die du allein starten kannst. Haskells starkes Typsystem sorgt dafür, dass die semantische Analyse von GHC viel für dich erledigt: Viele Fehler werden als Kompilierfehler gemeldet, statt zur Laufzeit abzustürzen. Für die vollständige Anleitung siehe unseren GHC-Compiler-Leitfaden und wie man Haskell mit GHCup installiert.

Die Befehle, denen du wirklich begegnest

  • Eine einzelne Datei kompilieren: ein Werkzeug wie ghc Main.hs liest deinen Quellcode und erzeugt eine ausführbare Datei.
  • Ein Projekt bauen: Build-Werkzeuge wie Cabal oder Stack steuern den Compiler für dich über viele Dateien und Abhängigkeiten.
  • Typen ohne vollständigen Build prüfen: viele Compiler bieten einen schnelleren Modus, der nach Fehlern sucht, ohne eine Binärdatei zu erzeugen.

Meistens rufst du den Compiler nicht von Hand auf — dein Build-Werkzeug oder Editor tut es und zeigt dir die Fehler. Aber zu wissen, was er darunter tut, macht diese Fehler weit leichter zu lesen.

Die ehrlichen Kompromisse

Compiler fügen einen Schritt hinzu: Du änderst Code, wartest auf den Build und führst dann aus. Bei einem großen Projekt kann diese Wartezeit spürbar sein, weshalb schnelle Compiler und inkrementelle Builds wichtig sind. Der Lohn ist real: früh abgefangene Fehler, optimierte Ausgabe und eine einzelne ausführbare Datei, die du ausliefern kannst, ohne deine Toolchain mitzuliefern. Für eine stark typisierte Sprache wie Haskell ist diese Prüfung im Voraus ein großer Teil des Reizes — der Compiler ist ein Sicherheitsnetz, nicht nur ein Übersetzer.

Häufige Fragen

Was ist ein Compiler einfach erklärt?

Ein Compiler ist ein Programm, das den Quellcode, den du schreibst, in eine Form übersetzt, die der Computer ausführen kann — meist Maschinencode. Du gibst ihm deine Textdateien und er erzeugt eine ausführbare Datei, die allein läuft, ohne dass der Compiler anwesend ist. Die Übersetzung geschieht einmal, im Voraus.

Was ist der Unterschied zwischen Compiler und Interpreter?

Ein Compiler übersetzt dein ganzes Programm einmal, vorab, in eine lauffähige Form, sodass das Ergebnis schnell startet und läuft. Ein Interpreter liest und führt deinen Quellcode bei jeder Ausführung direkt aus, ohne separaten Build-Schritt. Kompilierte Programme sind meist schneller; interpretierte sind schneller auszuprobieren und flexibler.

Welche Stufen hat ein Compiler?

Ein Compiler durchläuft typischerweise lexikalische Analyse (Text in Token zerlegen), syntaktische Analyse (einen Strukturbaum bauen), semantische Analyse (Namen und Typen prüfen), Optimierung (das Programm schneller oder kleiner machen) und Codeerzeugung (den finalen Maschinencode oder eine Zwischenform ausgeben). Ein Fehler in irgendeiner Stufe stoppt den Build.

Ist GHC ein Compiler?

Ja. GHC, der Glasgow Haskell Compiler, ist der Standard-Compiler für Haskell. Er liest deine .hs-Quelldateien, prüft sie auf Typen und optimiert sie und erzeugt eine native ausführbare Datei, die du allein starten kannst. Haskells starkes Typsystem sorgt dafür, dass GHC viele Fehler als Kompilierfehler abfängt, bevor das Programm überhaupt läuft.

Unabhängiger, von der Community gepflegter Leitfaden. coldwa.st ist eine Website mit Programmier-Ressourcen; dieser Artikel ist neuer, origineller erklärender Text darüber, wie Compiler funktionieren. Die beschriebenen Stufen sind in gängigen Compilern Standard; konsultiere die Dokumentation deines Compilers für sein genaues Verhalten.
Empfohlen

Eine Linux-Maschine zum Bauen und Ausführen deines Codes

Ein echtes Projekt zu kompilieren — GHC zu bauen, eine große Haskell-Codebasis auf Typen zu prüfen und dann die ausführbare Datei zu starten — ist auf einer richtigen Linux-Maschine viel einfacher als auf einem Laptop. Ein Cloud-Server gibt dir Root-Zugriff, um eine Compiler-Toolchain zu installieren und deine App in einer sauberen Umgebung zu bauen. Infomaniak — ein schweizer, datenschutzfreundlicher Anbieter — bietet Cloud-Server, die du einrichten und per SSH erreichen kannst.

Infomaniak Cloud ansehen →

Affiliate-Link — er unterstützt diese kostenlosen Leitfäden.

Stöbere durch weitere klare Erklärungen in unserem Leitfaden-Index.