Dieser Abschnitt behandelt ausschließlich den GNU
Compiler für C und C++, da dieser bereits im Basissystem
von FreeBSD enthalten ist. Er kann mittels cc
oder gcc
aufgerufen werden. Die Details zur
Erstellung einer Anwendung mit einem Interpreter variieren
zwischen verschiedenen Interpretern mehr oder weniger stark, und
werden meist ausführlich in der zugehörigen
Dokumentation oder Online-Hilfe beschrieben.
Sobald Sie Ihr Meisterwerk fertig geschrieben haben besteht der nächste Schritt darin, dieses (hoffentlich!) unter FreeBSD zum Laufen zu bekommen. Dies beinhaltet üblicherweise mehrere Schritte, wobei jeder einzelne Schritt von einem separaten Programm durchgeführt wird.
Aufbereiten Ihres Quelltextes durch Entfernen von Kommentaren, sowie weiteren Tricks wie das Ersetzen von Macros in C.
Überprüfen der Syntax Ihres Quelltextes, um die Einhaltung der Sprachregeln sicherzustellen. Wenn Sie diese verletzt haben werden entsprechende Fehlermeldungen Ihnen dies mitteilen!
Übersetzen des Quelltextes in Assemblersprache —diese ist dem eigentlichen Maschinencode schon sehr nahe, jedoch immer noch für Menschen lesbar. Angeblich. [2]
Übersetzen der Assemblersprache in Maschinencode—genau, wir sprechen hier von Bits und Bytes, Einsen und Nullen.
Überprüfen, ob Sie Dinge wie Funktionen und globale Variablen in einheitlicher Weise verwendet haben. Wenn Sie z.B. eine nicht existierende Funktion aufgerufen haben, wird eine entsprechende Fehlermeldung Ihnen dies mitteilen.
Wenn aus mehreren Quelltextdateien eine ausführbare Datei erstellt werden soll wird herausgefunden, wie die einzelnen Codeteile zusammengefügt werden müssen.
Ausarbeiten, wie das Programm aussehen muss, damit der Lader zur Laufzeit des Systems dieses in den Speicher laden und ausführen kann.
Endgültiges Schreiben der ausführbaren Datei in das Dateisystem.
Das Wort kompilieren wird häufig für die Schritte 1 bis 4 verwendet—die anderen werden mit dem Wort verlinken zusammengefasst. Manchmal wird Schritt 1 auch als Pre-Processing und die Schritte 3-4 als assemblieren bezeichnet.
Glücklicherweise werden alle diese Details vor Ihnen
verborgen, da cc
ein Frontend ist, welches
sich um die Ausführung all dieser Programme mit den
richtigen Argumenten für Sie kümmert; einfaches
eingeben von
%
cc foobar.c
führt zur Übersetzung von
foobar.c
durch alle bereits erwähnten
Schritte. Wenn Sie mehr als eine Datei übersetzen wollen
müssen Sie etwas wie folgt eingeben
%
cc foo.c bar.c
Beachten Sie, daß die Überprüfung der Syntax genau dies tut—das reine Überprüfen der Syntax. Es findet keine Überprüfung bzgl. logischer Fehler statt, die Sie vielleicht gemacht haben, wie z.B. das Programm in eine Endlosschleife zu versetzen, oder Bubble Sort zu verwenden, wenn Sie eigentlich Binary Sort benutzen wollten. [3]
Es gibt haufenweise Optionen für cc
,
die alle in der zugehörigen Manualpage beschrieben werden.
Im Folgenden werden ein paar der wichtigsten Optionen mit
Beispielen ihrer Anwendung gezeigt.
-o filename
Die Name der Ausgabedatei. Wenn Sie diese Option nicht
verwenden erstellt cc
eine Datei mit
dem Namen a.out
.
[4]
%
cc foobar.c
executable is a.out
%
cc -o foobar foobar.c
executable is foobar
-c
Dies kompiliert die Datei nur, verlinkt sie jedoch
nicht. Nützlich für Spielereien, um die Syntax
auf Korrektheit zu überprüfen, oder falls Sie
ein Makefile
verwenden.
%
cc -c foobar.c
Dieser Befehl erzeugt eine
Objektdatei (nicht ausführbar)
mit den Namen foobar.o
. Diese kann
mit anderen Objektdateien zusammen zu einer
ausführbaren Datei verlinkt werden.
-g
Diese Option erzeugt die Debug-Version einer
ausführbaren Datei. Dabei fügt der Compiler
zusätzliche Informationen darüber, welcher
Funktionsaufruf zu welcher Zeile im Quelltext gehört,
der ausführbaren Datei hinzu. Ein Debugger kann Ihnen
mit Hilfe dieser Information den zugehörigen
Quelltext anzeigen, während Sie den Programmverlauf
schrittweise verfolgen, was sehr
hilfreich sein kann; der Nachteil dabei ist, daß
durch die zusätzlichen Informationen das Programm
viel größer wird. Normalerweise verwendet man
die Option -g
während der
Entwicklung eines Programms, und für die
„Release-Version“, wenn man von der
Korrektheit des Programms überzeugt ist, kompiliert
man das Programm dann ohne diese Option.
%
cc -g foobar.c
Mit diesem Befehl wird eine Debug-Version des Programms erzeugt. [5]
-O
Diese Option erzeugt eine optimierte Version der
ausführbaren Datei. Der Compiler verwendet einige
clevere Tricks, um das erzeugte Programm schneller zu
machen. Sie können hinter der Option
-O
eine Zahl angeben, um eine
höheres Level der Optimierung festzulegen. Dadurch
wird jedoch häufig eine fehlerhafte Optimierung
seitens des Compilers aufgedeckt. Zum Beispiel erzeugte
die Version des cc
, welche mit dem
FreeBSD Release 2.1.0 mitgeliefert wurde, bei Verwendung
der Option -O2
unter bestimmten
Umständen falschen Code.
Optimierungen werden normalerweise nur beim Kompilieren von Release-Versionen aktiviert.
%
cc -O -o foobar foobar.c
Durch diesen Befehl wird eine optimierte Version von
foobar
erzeugt.
Die folgenden drei Flags zwingen den cc
dazu, Ihren Code auf die Einhaltung der internationalen
Standards hin zu überprüfen, welche häufig als
ANSI Standards bezeichnet werden, obwohl sie
streng genommen zum ISO Standard
gehören.
-Wall
Aktivieren aller Warnmeldungen, die die Autoren des
cc
für wichtig halten. Trotz des
Namens dieser Option werden dadurch nicht sämtliche
Warnungen ausgegeben, die der cc
ausgeben könnte.
-ansi
Deaktivieren der meisten, jedoch nicht aller,
nicht-ANSI C Eigenschaften, die
der cc
bietet. Trotz des Namens ist
durch diese Option nicht sichergestellt, daß Ihr
Code diese Standards auch vollständig
einhält.
-pedantic
Deaktivieren aller Eigenschaften
des cc
, welche nicht konform zu
ANSI C sind.
Ohne diese Flags wird Ihnen der cc
die
Verwendung eigener Erweiterungen des Standards erlauben. Einige
dieser Erweiterungen sind zwar sehr nützlich, werden jedoch
nicht von anderen Compilern unterstützt—eigentlich
ist eines der Hauptziele des Standards, das Leute Code so
schreiben können, daß dieser mit jedem Compiler auf
beliebigen Systemen funktioniert. Dies wird häufig als
portabler Code bezeichnet.
Im Allgemeinen sollten Sie versuchen, Ihren Code so portabel wie möglich zu schreiben, da Sie ansonsten eventuell das gesamte Programm noch einmal neu schreiben müssen, falls dieser in einer anderen Umgebung laufen soll—und wer weiß schon was er in ein paar Jahren verwenden wird?
%
cc -Wall -ansi -pedantic -o foobar foobar.c
Durch diesen Befehl wird eine ausführbare Datei namens
foobar
erzeugt, nachdem
foobar.c
auf die Einhaltung der Standards
überprüft wurde.
-llibrary
Mit dieser Option kann eine Bibliothek mit Funktionen angegeben werden, die während des Verlinkens verwendet wird.
Das am häufigsten auftretende Beispiel dieser Option ist die Übersetzung eines Programmes, welches einige der mathematischen Funktionen in C verwendet. Im Gegensatz zu den meisten anderen Plattformen befinden sich diese Funktionen in einer separaten Bibliothek, deren Verwendung Sie dem Compiler explizit mitteilen müssen.
Angenommen eine Bibliothek heißt
lib
,
dann müssen Sie dem irgendwas
.acc
als
Argument
-l
übergeben. Zum Beispiel heißt die
Mathematik-Bibliothek irgendwas
libm.a
, und
daher müssen Sie dem cc
als
Argument -lm
übergeben. Ein
typisches „Manko“ der Mathematik-Bibliothek
ist, daß diese immer die letzte Bibliothek auf der
Kommandozeile sein muß.
%
cc -o foobar foobar.c -lm
Durch diesen Befehl werden die Funktionen aus der
Mathematik-Bibliothek in foobar
gelinkt.
Wenn Sie C++-Code kompilieren wollen, müssen Sie
-lg++
, bzw. -lstdc++
falls Sie FreeBSD 2.2 oder neuer verwenden, zu Ihrer
Kommandozeile hinzufügen, um Ihr Programm gegen die
Funktionen der C++ Bibliothek zu linken. Alternativ
können Sie anstatt cc
auch
c++
aufrufen, welcher dies für Sie
erledigt. c++
kann unter FreeBSD auch
als g++
aufgerufen werden.
%
cc -o foobar foobar.cc -lg++
Bei FreeBSD 2.1.6 oder älter
%
cc -o foobar foobar.cc -lstdc++
Bei FreeBSD 2.2 und neuer
%
c++ -o foobar foobar.cc
Beide Varianten erzeugen eine ausführbare
foobar
aus der C++ Quelltextdatei
foobar.cc
. Beachten Sie bitte,
daß auf UNIX® Systemen C++ Quelltextdateien
üblicherweise auf .C
,
.cxx
oder .cc
enden, und nicht wie bei MS-DOS® auf
.cpp
(welche schon anderweitig
benutzt wurde). Der gcc
hat
normalerweise anhand dieser Information entschieden,
welcher Compiler für die Quelltextdatei zum Einsatz
kommen soll; allerdings gilt diese Einschränkung
jetzt nicht mehr, und Sie können Ihre C++-Dateien
ungestraft auf .cpp
enden
lassen!
2.4.1.1. | Ich versuche ein Programm zu schreiben, welches die
Funktion /var/tmp/cc0143941.o: Undefined symbol `_sin' referenced from text segment
|
Wenn Sie mathematische Funktionen wie
% cc -o foobar foobar.c -lm
| |
2.4.1.2. | So, ich habe jetzt dieses einfache Programm als
Übung für #include <stdio.h>
int main() {
float f;
f = pow(2.1, 6);
printf("2.1 ^ 6 = %f\n", f);
return 0;
}
und ich habe es wie folgt kompiliert: % cc temp.c -lm
wie mir gesagt wurde. Allerdings bekomme ich jetzt bei der Ausführung die folgende Ausgabe: % ./a.out
2.1 ^ 6 = 1023.000000
Das ist nicht die richtige Antwort! Was ist hier los? |
Wenn der Compiler Ihren Funktionsaufruf sieht, überprüft er, ob er schon einmal einen Prototypen für diese gesehen hat. Wenn nicht nimmt er als Rückgabewert den Typ int an, was sicherlich nicht das ist, was Sie an dieser Stelle wollen. | |
2.4.1.3. | Wie kann ich das korrigieren? |
Die Prototypen der mathematischen Funktionen
befinden sich in der Datei #include <math.h>
#include <stdio.h>
int main() {
...
Nach erneutem Compilieren sollte das Folgende bei der Ausführung ausgegeben werden: % ./a.out
2.1 ^ 6 = 85.766121
Wenn Sie irgendwelche mathematischen Funktionen
verwenden sollten Sie immer die
Datei | |
2.4.1.4. | Ich habe eine Datei mit dem Namen
|
Denken Sie daran, daß der
% cc -o foobar foobar.c
| |
2.4.1.5. | OK, ich habe eine ausführbare Datei namens
|
Im Gegensatz zu MS-DOS® sucht UNIX® nicht im
aktuellen Verzeichnis nach einem ausführbaren
Programm, das Sie versuchen auszuführen, solange
Sie dies nicht explizit mit angeben. Sie können
entweder bin:/usr/bin:/usr/local/bin:.
Der Punkt am Ende bedeutet „siehe im aktuellen Verzeichnis nach, wenn es in keinem der anderen zu finden war“. | |
2.4.1.6. | Ich habe meine ausführbare Datei
|
Bei den meisten UNIX®-Systeme existiert bereits
ein Programm mit dem Namen % ./test
oder Sie können einen geeigneteren Namen für Ihr Programm wählen! | |
2.4.1.7. | Ich habe mein Programm kompiliert und bei dessen Aufruf sah zuerst alles gut aus. Jedoch gab es dann eine Fehlermeldung, welche irgendetwas mit core dumped lautete. Was bedeutet das? |
Der Name core dump stammt
noch aus sehr frühen Zeiten von UNIX®, als die
Maschinen noch Kernspeicher zum Speichern von Daten
verwendeten. Einfach ausgedrückt, wenn bei einem
Programm unter bestimmen Bedingungen ein Fehler auftrat,
hat das System den Inhalt des Kernspeichers auf der
Festplatte in eine Datei namens
| |
2.4.1.8. | Faszinierendes Zeugs, aber was soll ich jetzt machen? |
Verwenden Sie den | |
2.4.1.9. | Als mein Programm den core dump erzeugt hat, sagte es etwas von einem segmentation fault. Was ist das? |
Diese Meldung heißt im Prinzip, daß Ihr Programm eine illegale Operation mit dem Speicher durchführen wollte; UNIX® wurde so entworfen, daß es das andere Programme und das Betriebssystem selbst vor wildgewordenen Programmen schützt. Häufige Ursachen hierfür sind:
Einzelne solcher Fehler führen zwar nicht immer zu einem Fehlverhalten des Programms, stellen jedoch immer eine falsche Verwendung dar. Manche Systeme und Compiler sind toleranter als andere, weshalb Programme auf dem einen System einwandfrei laufen, auf dem anderen System jedoch abstürzen. | |
2.4.1.10. | Wenn ich einen core dump erhalte erscheint manchmal die Meldung bus error. In meinem UNIX®-Buch steht, daß die Ursache ein Hardwareproblem sei. Der Computer scheint aber weiterhin zu funktionieren. Ist dies wahr? |
Nein, glücklicherweise nicht (es sei denn Sie haben wirklich ein Hardwareproblem…). Üblicherweise ist dies ein Weg Ihnen mitzuteilen, daß Sie auf Speicher in einer Weise zugegriffen haben, in der Sie dies nicht tun sollten. | |
2.4.1.11. | Diese Sache mit den core dumps hört sich sehr nützlich an, wenn ich so etwas selber an beliebiger Stelle bewirken könnte. Kann ich das tun, oder muß ich warten bis ein Fehler auftritt? |
Ja, nehmen sie einfach eine andere Konsole oder XTerm und führen Sie % ps
aus, um die Prozess-ID Ihres Programms herauszufinden. Führen Sie anschließend % kill -ABRT
aus, wobei
Dies ist nützlich, wenn sich Ihr Programm z.B. in einer Endlosschleife verfangen hat. Sollte Ihr Programm das Signal SIGABRT abfangen, gibt es noch andere Möglichkeiten, die denselben Effekt haben. Alternativ können Sie einen core dump aus
Ihrem Programm heraus erstellen, indem Sie die Funktion
Wenn Sie einen core dump von außerhalb Ihres
Programms erzeugen wollen, ohne dabei den Prozess
abzubrechen, können Sie das Programm
|
[2] Um genau zu sein übersetzt der
cc
den Quelltext an dieser Stelle
nicht in Assemblersprache, sondern in seine eigene,
maschinenunabhängige Sprache namens
p-code.
[3] Falls Sie es nicht wußten, Binary Sort ist, im Gegensatz zu Bubble Sort, eine effektive Möglichkeit, Dinge zu sortieren.
[4] Der Grund dafür ist im Haufen der Geschichte begraben.
[5] Beachten Sie, daß an dieser Stelle die
Option -o
zum Festlegen des Namens
der ausführbaren Datei nicht verwendet wurde,
weswegen an dieser Stelle die erzeugte Datei
a.out
heißt. Die Erzeugung
einer Debug-Version namens foobar
ist als Übung dem Leser überlassen!
Wenn Sie Fragen zu FreeBSD haben, schicken Sie eine E-Mail an
<de-bsd-questions@de.FreeBSD.org>.
Wenn Sie Fragen zu dieser Dokumentation haben, schicken Sie eine E-Mail an
<de-bsd-translators@de.FreeBSD.org>.