Getrennte Übersetzung
Da Quelltext von einem Prozessor oft nicht direkt ausgeführt werden kann, muß er in eine Zielsprache übersetzt werden, also in eine Sprache, die der verwendete Prozessor versteht, und in das Format gebracht werden, das das Zielsystem (Betriebssystem) für ausführbare Dateien vorschreibt, wenn ein ausführbares Programm (Endprodukt) erzeugt werden soll.
Bei der Herstellung eines Software-Produktes werden oft mehrere Übersetzungseinheiten verwendet. Diese werden dann getrennt (also jeweils einzeln) kompiliert (übersetzt) werden. Der Übersetzungsvorgang einer einzelnen Übersetzungseinheit erzeugt dann noch nicht das Endprodukt, sondern ein Zwischenprodukt (eine Zwischendatei oder Zwischeneinheit ), das manchmal auch als Montageobjekt, Objektdatei oder als Klassendatei bezeichnet wird. Diese Zwischeneinheiten können dann schließlich durch ein weiteres Programm, den Verbinder (auch: Binder, engl.: “linker ”) zu einem verwendbaren Endprodukt verbunden werden.
Die Aufteilung eines Programmes in mehrere Übersetzungsdateien ist besonders bei größeren Programmen hilfreich. In einführenden Lehrgängen zu einer Programmiersprache werden aber anfangs zunächst nur kleinere Programme geschrieben. Daher können Techniken zur Bewältigung größerer Projekte in Lehrgängen nicht immer durch entsprechende Beispiele motiviert werden. Die Kenntnis dieser Techniken ist jedoch für die Praxis nötig, da das Hauptproblem bei der Software-Erstellung gerade die Bewältigung der Komplexität größerer Projekte ist.
Eine Zwischendatei ist schon weitgehend in die ausführbare Zielsprache übersetzt, ist aber alleine noch nicht ausführbar, da ihr noch Programmteile fehlen, die an anderen Stellen definiert wurden, und auch ihr Format noch nicht den Vorgaben des Zielsystems für ausführbare Dateien entsprechen muß.
getrennte Uebersetzung [Datenflußplan]_____ _____ _____
.-' '-. .-' '-. .-' '-.
.' '. .' '. .' '.
/ \ / \ / \
; Uebersetzungs- ; ; Uebersetzungs- ; ; Uebersetzungs- ;
| Einheit | | Einheit | | Einheit |
; 0 ; ; 1 ; ; 2 ;
\ / \ / \ /
'. .' '. .' '. .'
'-._____.-' '-._____.-' '-._____.-'
| | |
V V V
.-------------------. .-------------------. .-------------------.
| | | | | |
| Uebersetzer | | Uebersetzer | | Uebersetzer |
| | | | | |
'-------------------' '-------------------' '-------------------'
| | |
__V__ __V__ __V__
.-' '-. .-' '-. .-' '-.
.' '. .' '. .' '.
/ \ / \ / \
; Zwischen- ; ; Zwischen- ; ; Zwischen- ;
| Produkt | | Produkt | | Produkt |
; 0 ; ; 1 ; ; 2 ;
\ / \ / \ /
'. .' '. .' '. .'
'-._____.-' '-._____.-' '-._____.-'
| | |
'---------------------. | .---------------------'
| | |
| | |
V V V
.-------------------.
| |
| Verbinder |
| |
'-------------------'
|
__V__
.-' '-.
.' '.
/ \
; End- ;
| Produkt |
; ;
\ /
'. .'
'-._____.-'
Statt mehrerer Übersetzungseinheiten (Quellen, Quelldateien) könnte auch eine einzige großen Übersetzungseinheit verwendet werden. Doch die Aufteilung einer großen Übersetzungseinheit in mehrere getrennte kleinere Übersetzungseinheiten hat verschiedene Vorteile.
- Die Aufteilung in verschiedene Übersetzungseinheiten verbessert die Übersichtlichkeit, wenn sie so erfolgt, daß zusammengehörige Entitäten in einer Übersetzungseinheit zusammengefaßt werden (so wie es übersichtlicher ist, wenn alle Hemden in einer Schublade liegen und alle Hosen in einer anderen, anstatt alles in einer großen Schublade zu vermischen). Jede Übersetzungseinheit versinnbildlicht dann einen bestimmten Teil eines Produktes und enthält Entitäten, die zusammen für ein bestimmtes Gebiet zuständig sind. Beispielsweise könnte in einem größeren Programm eine Übersetzungseinheit alle Entitäten enthalten, die für die Ausgabe zuständig sind und dann auch entsprechend benannt werden. Wenn dann eine Entität gesucht wird, die mit der Ausgabe zu tun hat, ist es klar, in welcher Übersetzungseinheit sie zu finden ist. Solch ein Teil (Übersetzungseinheit) eines Programmes wird in manchen Programmiersprachen auch besonders unterstützt und dann oft als ein Modul bezeichnet.
- Die Aufteilung in verschiedene Übersetzungseinheiten verbessert die Übersichtlichkeit aber auch dadurch, daß die einzelnen Übersetzungseinheiten dann kleiner sind. Dadurch sind sie natürlich leichter handzuhaben und zu überblicken.
- Eine nützliche Übersetzungseinheit (oder das aus ihr erzeugte Zwischenprodukt) kann, wen sie allgemein genug geschriebn wurde, in verschiedenen Endprodukten verwendet werden und macht sich somit mehrfach nützlich, obwohl sie nur einmal erstellt werden muß.
- Nach einer Veränderung an einer einzigen Übersetzungseinheit müssen andere Übersetzungseinheiten zur Herstellung des Produktes oft nicht erneut übersetzt werden, denn wenn sich an einer Übersetzungseinheit nichts geändert hat, dann bleibt auch ihr Zwischenprodukt gleich, so daß die Herstellung schneller erfolgen kann: Es ist dann nur nötig, die geänderte Übersetzungseinheit neu zu übersetzen und alles Zwischendateien neu zu verbinden. Die nicht geänderten Übersetzungseinheiten brauchen nicht erneut übersetzt zu werden. (Es gibt Programme, wie das Programm "make", die solche Abhängigkeiten erkennen und automatisch nur das Minimum an Vorgängen erledigen, das zur Herstellung eines Produktes nötig ist.)
Bezüge
Eine Entität, die in einer Übersetzungseinheit definiert wurde, kann oft von einer anderen Übersetzungseinheit verwendet werden. Dabei wird die Verwendung den Bezug in der Regel über den öffentlichen Namen der Entität herstellen. Ein öffentlicher Name kann von anderen Übersetzungseinheiten aus verwendet werden, während ein privater Name (interner Name ) nur innerhalb seiner Übersetzungseinheit definiert ist und von anderen Übersetzungseinheiten aus nicht bemerkt wird, so daß er dort beispielsweise auch wieder mit einer ganz anderen Bedeutung als interner Name verwendet werden könnte. Insofern sind Übersetzungseinheiten Namensräume ihrer privaten Namen.
In einer Übersetzungseinheit kann also ein öffentlicher Name für eine Entität definiert werden und in anderen Einheiten kann dann dieser öffentlicher Name verwendet werden, um sich auf diese Entität zu beziehen. Innerhalb eines Projektes aus mehreren Übersetzungseinheiten, darf ein öffentlicher Name im allgemeinen nur einmal in einer einzigen Übersetzungseinheit definiert werden (one definition rule ), aber er darf beliebig oft in allen Übersetzungseinheiten verwendet werden, um sich auf seine Definition zu beziehen.
Im dem durch die Übersetzung erzeugten Zwischenprodukt wird dann ebenfalls noch die Bezugnahme des Quelltextes auf die Entität vorhanden sein, die in einem anderen Zwischenprodukt definiert sein kann. Solange die beiden Zwischenprodukte noch getrennt voneinander sind, spricht man von einer unaufgelösten Bezugnahme (Referenz), da in dem Zwischenprodukt mit der Referenz die referenzierte Entität noch fehlt.
Bezug in einem Zwischenprodukt.------------------------.
| Zwischenprodukt 0 |
|------------------------|
| |
| ... | .------------------------.
| | | Zwischenprodukt 1 |
| | |------------------------|
| | | |
| | | ... |
| | | |
|------------------------| |------------------------|
| Bezug auf "kuckuck" -------> | Definition von |
|------------------------| | "kuckuck" |
| ... | |------------------------|
'------------------------' | ... |
| |
| |
| |
'------------------------'
Durch das Verbinden der beiden Zwischenprodukte gelangen die Bezüge auf eine Entität und die Definition der Entität dann in eine einzige Datei (Einheit). Der Namensbezug wird dabei oft durch einen effizienteren Bezug, wie einen Adreßbezug, ersetzt. Das heißt, daß statt des Namens die Entität nun durch ihre Position (Adresse ) in dem Produkt bestimmt wird und auch Bezugnahmen über diese Position erfolgt. Der Verbinder ersetzt die Namen also überall durch Adressen. Solche Adreßbezüge können dann von der ausführbaren Zielsprache direkt verarbeitet werden und dies ist auch schneller möglich als bei Namensbezügen, da die Adressen sofort verwendet werden können, während zu einem Namen erst die passende Adresse gesucht werden müßte. So entsteht schließlich eine Datei, die keine Bezüge auf externe Definitionen mehr enthält.
Bezug im Endprodukt.------------------------.
| Endprodukt |
|------------------------|
| |
| ... |
| |
|------------------------|
| Bezug auf Entität |
| bei Adresse 4321 |
|----------|-------------|
| | |
| ... | |
| V |
|------------------------|
| 4321: Implementation |
|------------------------|
| |
| ... |
| |
'------------------------'
Die Namen von Entitäten des Quelltextes, wie beispielsweise Routinen, sind in dem erzeugten Endprodukt daher oft gar nicht mehr enthalten. Das erklärt, warum beispielsweise eine Routine, die die Namen aller Routinen eines Programmes ausgibt, in vielen Programmiersprachen nicht geschrieben werden kann (es sei denn alle Namen werden noch einmal getrennt erfaßt): Diese Namen sind in dem fertigen Programm nicht mehr enthalten. Es wird auch verständlich, warum es nicht möglich ist, aus einem ausführbaren Programm den Quellcode wiederzugewinnen: Bestimmte Informationen, wie die Namen der Entitäten, sind nicht mehr im Endprodukt enthalten und können deswegen daraus auch nicht wiederhergestellt werden.
Ein Verbinder kennt auch das Format, in dem ein Betriebssystem ausführbare Dateien erwartet, und kann das Endprodukt entsprechend so erzeugen, daß es auf dem Zielsystem direkt als Programm gestartet werden kann.
Wie ein Verbinder genau bedient wird, hängt vom verwendeten Programm ab und wird nicht in dieser Lektion behandelt. Unter vielen Entwicklungsumgebungen reicht es aber, zusammengehörige Quelldateien als ein Projekt zu kennzeichnen und den Typ des gewünschten Endproduktes anzugeben, damit die aus ihnen erzeugten Zwischenprodukte zu dem gewünschten Endprodukt verbunden werden.
Bibliotheken
Ein großer Vorteil der getrennten Kompilierung ist es ja, daß eine nützliche Übersetzungseinheit zur Herstellung verschiedener Projekte verwendet werden kann. Man kann hierbei noch einen Schritt weitergehen und daran denken, eine nützliche Übersetzungseinheit sogar an verschiedene andere Personen weiterzugeben, so daß auch andere diese nutzen können.
Solch eine Sammlung nützlicher Entitäten wird auch als eine Bibliothek (engl. library ) bezeichnet. Eine Bibliothek kann aus mehreren Zwischenprodukten bestehen, die dabei sozusagen die Rolle der „Bücher“ spielen. In einer Übersetzungseinheit können dann die Entitäten der Bibliothek so verwendet werden, wie auch in einer anderen Übersetzungseinheit definierte Entitäten.
Nicht immer müssen zum Lieferumfang einer Bibliothek auch die Quelldatei (Übersetzungseinheiten) gehören, es reicht ja wenn die Zwischendateien und eine Erklärung (Dokumentation) der in ihnen definierten Entitäten ausgeliefert wird. So hat der Hersteller einer Bibliothek auch einen gewissen Schutz seines Quellcodes vor ungewünschten Analysen durch Verwender der Bibliothek.
Eine bestimmte Bibliothek gehört zu den meisten Programmiersprachen und umfaßt eine Sammlung vordefinierter Standardentitäten. Weitere Bibliotheken können aus verschiedenen Quellen bezogen werden, manche sind kostenlos erhältlich, andere müssen gekauft werden, zu manchen ist der Quellcode kostenlos erhältlich, zu anderen ist es gegen eine Aufpreis oder gar nicht lieferbar.
Dadurch, daß die Bibliotheken dann mit den Zwischendateien eines Projektes verbunden werden, entsteht schließlich das fertige Endprodukt. Dabei werden die Teile der Bibliothek, die in den Zwischendateien verwendet wurden, dann in das Endprodukt übernommen, welches damit alleine (ohne die Bibliothek) lauffähig ist.
getrennte Uebersetzung [Datenflußplan]_____ _____
.-' '-. .-' '-.
.' '. .' '.
/ \ / \
; Uebersetzungs- ; ; Uebersetzungs- ;
| Einheit | | Einheit |
; 0 ; ; 1 ;
\ / \ /
'. .' '. .'
'-._____.-' '-._____.-'
| |
V V
.-------------------. .-------------------.
| | | |
| Uebersetzer | | Uebersetzer |
| | | |
'-------------------' '-------------------'
| |
__V__ __V__ _____
.-' '-. .-' '-. .-' '-.
.' '. .' '. .' '.
/ \ / \ / \
; Zwischen- ; ; Zwischen- ; ; Bibliothek ;
| Produkt | | Produkt | | 0 |
; 0 ; ; 1 ; ; ;
\ / \ / \ /
'. .' '. .' '. .'
'-._____.-' '-._____.-' '-._____.-'
| | |
'---------------------. | .---------------------'
| | |
| | |
V V V
.-------------------.
| |
| Verbinder |
| |
'-------------------'
|
__V__
.-' '-.
.' '.
/ \
; End- ;
| Produkt |
; ;
\ /
'. .'
'-._____.-'
Nichtdefinierende Deklarationen
Wenn ein Übersetzer eine Übersetzungseinheit verarbeitet, die eine Entität verwendet, die in einer anderen Übersetzungseinheit definiert ist, dann kann der Übersetzer in vielen Fällen zunächst nichts über diese Entität wissen. Er verarbeitet die Übersetzungseinheit, in der die verwendete Entität definiert wird, ja nicht. Der Übersetzer kann dann nicht einmal prüfen, ob die Entität in der gerade übersetzten Einheit überhaupt richtig verwendet wird und kann auch nicht immer wissen, wie ein Bezug auf diese Entität richtig herzustellen ist.
Eine Entität, die in einer anderen Übersetzungseinheit definiert ist, als der gerade übersetzten, wird auch eine externe Entität genannt. Eine Übersetzungseinheit mit Bezügen auf externe Entitäten einer anderen Übersetzungseinheit oder eines Zwischenproduktes oder einer Bibliothek, nennt man auch einen Klienten dieser anderen Übersetzungseinheit, bzw. dieses Zwischenprodukts oder der Bibliothek. Man sagt, daß eine Übersetzungseinheit, ein Zwischenprodukt oder eine Bibliothek diejenigen Entitäten, auf welche sich andere Übersetzungseinheiten beziehen können, exportiert.
Damit der Übersetzer seine Arbeit erledigen kann, wird der Verwendung einer externen Entität oft eine nichtdefinierende Deklaration eines Bezeichners vorangestellt. Solch eine Deklaration erfüllt zwei Aufgaben:
- Sie erklärt den Typ der externen Entität als Typ des verwendeten Bezeichners
- Sie sichert dem Übersetzer zu, daß es unter dem Namen des angegebenen Bezeichners tatsächlich eine Entität gibt.
Anders als eine vollständige Definition wird durch eine nichtdefinierende Deklaration aber keine neue Entität angelegt.
Damit nicht jeder Klient immer wieder die nötigen nichtdefinierenden Deklarationen enthalten muß, wird zu einer Bibliothek oft eine für den Übersetzer verständlich Bibliotheksbeschreibung mitgeliefert, in der alle exportierten Entitäten nichtdefinierend Deklariert sind. So kann der Übersetzer alles nötige über Namen und Typ der exportierten Entitäten erfahren.
getrennte Uebersetzung mit Bibliotheksbeschreibung [Datenflußplan]_____ _____
.-' '-. .-' '-.
.' '. .' '.
/ \ / \
; Uebersetzungs- ; ; Bibliotheks- ;
| Einheit | | beschreibung |
; 0 ; ; 0 ;
\ / \ /
'. .' '. .'
'-._____.-' '-._____.-'
| |
V |
.-------------------. |
| | |
| Uebersetzer |<-------------'
| |
'-------------------'
|
__V__ _____
.-' '-. .-' '-.
.' '. .' '.
/ \ / \
; Zwischen- ; ; Bibliothek ;
| Produkt | | 0 |
; 0 ; ; ;
\ / \ /
'. .' '. .'
'-._____.-' '-._____.-'
| |
'---------------------. |
| |
| |
V V
.-------------------.
| |
| Verbinder |
| |
'-------------------'
|
__V__
.-' '-.
.' '.
/ \
; End- ;
| Produkt |
; ;
\ /
'. .'
'-._____.-'
Bibliotheksdienste
Ein vollständiger, nützlicher Bibliotheksdienst besteht also aus zwei Teilen: Einer Beschreibung der Bibliothek für den Übersetzer, in der Name und Typ der exportierten Entitäten deklariert wird und der eigentlichen Bibliothek für den Verbinder, welche die nutzbaren Entität in bereits übersetzter Form enthält.
Anstelle eines Bibliotheksdienstes könnte der Dienst auch durch einen Quelltext bereitgestellt werden, der bei Bedarf jedesmal mit dem Klienten zusammen übersetzt wird. Die Verwendung eines Bibliotheksdienstes bietet demgegenüber jedoch den Vorteil, daß der Herstellungsprozeß schneller durchlaufen werden kann, weil die Übersetzung der Bibliothek nicht mehr nötig ist, da diese schon in einer übersetzten Form vorliegt. Außerdem muß der Hersteller eines Bibliotheksdienst so den Quelltext seiner Bibliothek nicht mit ausliefern und kann so sein geistiges Eigentum besser geheimhalten, falls dies gewünscht wird.
Ein Bibliotheksdienst.--------------------------------.
| |
| Bibliotheksdienst 0 |
| |
| _____ |
| .-' '-. |
| .' '. |
| / \ |
| ; Bibliotheks- ; |
| | beschreibung | |
| ; 0 ; |
| \ / |
| '. .' |
| '-._____.-' |
| |
| |
| |
| _____ |
| .-' '-. |
| .' '. |
| / \ |
| ; Bibliothek ; |
| | 0 | |
| ; ; |
| \ / |
| '. .' |
| '-._____.-' |
'--------------------------------'