1.5 Der Compiler GCC – eine kurze Einführung
Da in diesem Buch Vorkenntnisse in C erforderlich sind, wissen Sie ja, womit ein Programm geschrieben, übersetzt und ausgeführt wird. Welchen Editor oder gar welche Entwicklungsumgebung Sie dazu verwenden, bleibt letztendlich Ihnen selbst überlassen. Der eine wird seine Programme vielleicht gerne mit vi oder dem emacs schreiben, und der andere verwendet vielleicht lieber gleich eine Entwicklungsumgebung wie Kdevelop oder Anjuta – dies ist wohl eher Sache des guten Geschmacks.
Umsteiger von MS Windows werden beim Anblick und der Verwendung von vi denken, ihre Tastatur sei kaputt, und echte Linux- bzw. UNIX-Puristen werden sich von der überfüllten Entwicklungsumgebung schnell wieder verabschieden.
Je nachdem, wie Sie den Quellcode erstellen, zum Übersetzen reicht in diesem Buch auch die Kommandozeile aus. Daher werde ich gerade für Umsteiger oder Einsteiger hier eine kurze Einführung mit den wichtigsten Optionen des GNU C-Compilers (GCC) beschreiben. Für mehr Informationen sollten Sie die Manual Pages (bzw. Info-Pages) von GCC lesen (man gcc) – oder das Ende des Buchs, wo neben dem Compiler noch einige Werkzeuge erklärt werden.
1.5.1 GCC erhöre uns – der Aufruf
Generell gibt es vier mir bekannte Aufrufmöglichkeiten des GCC, wobei nicht alle funktionieren müssen. Gewöhnlich wird als Aufruf gcc verwendet, aber es sind auch noch folgende Syntaxen vorhanden:
cc
g++
c++
In Wahrheit ist der GCC eigentlich nur ein Frontend für die verschiedenen Tools (Preprocessor cpp, Compiler cc1 oder cc1plus, Assembler as, Linker collect2, ld). GCC bestimmt in der Regel anhand der Dateiendung selbst, welchen Compiler er anzuwenden hat. Daher lässt sich GCC sowohl für C, C++ als auch für Assembler-Dateien anwenden. Das ist sogar manchmal sinnvoller, als nur den Assembler as oder den Linker ld aufzurufen, denn das GCC-Frontend übergibt noch weitere Flags, die in der Regel dazu führen, dass man keine Fehlermeldung(en) beim Ausführen bekommt.
Die Frontends g++/c++ weisen den Linker ld noch an, die STL usw. (libstdc++.so) mitzulinken, was beim GCC trotz der Dateiendung nicht passiert und daher immer wieder bei Anfängern in C++ unter Linux zur Verwirrung führt.
Meistens sind cc und c++ bzw. posix_cc und posix_c++ (SUSE-Sonderpakete) nur Alias für gcc und g++. Wohlgemerkt sind /usr/bin/gcc und /usr/bin/g++ zwei verschiedene Dateien!
1.5.2 Was befiehlst du – Meister?
Wenn Sie den GCC aufrufen, erwartet dieser erst einmal Befehle (Optionen), was er mit dem Quellcode tun soll. Dabei kennt gcc unzählige Optionen. Die wichtigsten finden Sie in der folgenden Tabelle zusammengefasst.
Tabelle 1.1
gcc-Kommandozeilen-Optionen
Option
|
Bedeutung
|
-o
|
(Output) Wollen Sie, dass der Compiler die ausführbare Datei anders benennt als a.out, dann sollten Sie mit dieser Option den Namen der Ausgabedatei angeben.
|
-c
|
(Compile) Kompilieren ohne zu linken
|
-Dname=value
|
(Define) Definiert ein Präprozessor-Makro mit dem Namen name und dem Wert value in der Kommandozeile.
|
-Idirname
|
(Include-directory) Fügt dirname zur Liste der Include-Dateien hinzu, in denen danach gesucht werden soll.
|
-Ldirname
|
(Library) Fügt dirname zur Liste der Verzeichnisse hinzu, in denen nach Bibliotheksdateien gesucht werden soll (-L gilt für .so und .a).
|
-static
|
Es werden nur statische Bibliotheken zum Linken verwendet.
|
-lname
|
(Library) Gibt die Bibliothek an, die hinzugelinkt werden soll. Hier die Bibliothek name (wird eine .so-Datei gefunden, wird diese benutzt, andernfalls .a, sollte diese existieren).
|
-O
|
(Optimize) Den kompilierten Quellcode optimieren
|
-On
|
(Optimize) Wie das Flag –O, nur kann mit n die Optimierungsstufe angegeben werden. Mindestens ist 1 und maximal 3 möglich. Mit der Angabe von 0 wird die Optimierung ausgeschaltet. Es sind auch Level oberhalb 3 möglich, die haben aber keinen Effekt.
|
-g
|
(Debug) Fügt Standard-Debug-Informationen zum Debuggen hinzu.
|
-ggdb
|
(Debug gdb) Fügt Debug-Informationen hinzu, die nur der Debugger gdb versteht (auch hier gibt es wieder verschiedene Stufen; wer in der Welt der vielen –g-Möglichkeiten einfach nur »alles« will, gibt am besten -ggdb3 an; da hat man alles (laut Manpage).
|
-ansi
|
Erlaubt nur ANSI C-konforme Konstrukte.
|
-pedantic
|
Gibt alle Warnungen aus, die vom ANSI C-Standard gefordert werden.
|
-pedantic-errors
|
Gibt alle Fehler aus, die vom ANSI C-Standard gefordert werden.
|
-Wall
|
Aktiviert allgemeine sinnvolle Warnungen, die vom gcc-Compiler unterstützt werden.
|
-p, -pg
|
(Profiling) Fügt dem Objektcode Profiling-Informationen hinzu, die vom Profiler gprof ausgewertet werden können. –pg gibt Profiling-Informationen für gprof aus.
|
-v
|
Zeigt alle Schritte und Kommandos in der Kommandozeile an, die der Compiler gerade ausführt (siehe da: cpp, cc1, as und ld).
|
Um jetzt den Aufruf einiger Befehle zu demonstrieren, sei folgendes Listing mit dem Namen test.c gegeben:
#include <stdio.h>
int main(int argc, char **argv) {
printf("Hallo Linux!\n");
return 0;
}
Damit aus dem Listing eine ausführbare Datei wird, können Sie diese folgendermaßen übersetzen (kompilieren und linken):
$ gcc test.c
Allerdings finden Sie dann in Ihrem Verzeichnis standardmäßig die Datei a.out (kurz für »Assembler Output«), was die ausführbare Datei sein soll. In der Regel werden Sie Ihrem Programm auch einen Namen geben wollen. Dies können Sie mit der Option –o machen:
$ gcc –o test test.c
$ ./test
Hallo Linux!
FAQ[1] Hilfe, ich kann mein übersetztes Programm nicht starten? Setzen Sie einen Punkt und ein Slash vor den Programmnamen (./programmname).
|
Ein weiteres Beispiel, eine Kokosnuss, die es zu knacken gilt. Versuchen Sie mal selbst herauszufinden, wie Sie dieses Listing übersetzen können:
#include <stdio.h>
#define SECRET 1234
int main(int argc, char **argv) {
if(HALLO + 1233 == SECRET) {
printf("Sie haben die Kokosnuss geknackt!\n");
}
else {
printf("Was auch immer?\n");
}
return 0;
}
Wenn Sie das Listing wie gewöhnlich übersetzen, wird Ihnen der Compiler nicht freundlich gesinnt sein. Das HALLO ist hier syntaktisch falsch, und dennoch kann man das Listing übersetzen. Versuchen Sie es folgendermaßen:
$ gcc –o test test.c –DHALLO=1
$ ./test
Sie haben die Kokosnuss geknackt!
Mit der Option -D haben Sie hier ein eigenes Define-Makro für HALLO hinzugefügt. In diesem Fall wird beim Präprozessordurchlauf das Makro HALLO durch den Wert 1 ersetzt. Solch ein Beispiel soll aber nicht die Runde machen.
Im nächsten Beispiel sei nochmals ein anderes Listing gegeben:
#include <stdio.h>
int main(int argc, char **argv) {
// Eine Legende ...
printf("Struuuunnz ...\n");
return 0;
}
Wenn Sie dieses Listing gewöhnlich übersetzen, sollten keine Probleme damit auftreten.
$ gcc –o test test.c
$ ./test
Struuuuuunnnz ...
Jetzt wollen Sie aber wissen, was der ANSI/ISO-Standard dazu zu sagen hat:
$ gcc –o test test.c –ansi
$ ./test
test.c(5):parse error before ‘/’ token
Der Slash ist also gemäß dem ANSI/ISO C-Standard (C89, um genau zu sein) hier fehl am Platz. Das wollen Sie aber jetzt genauer wissen:
$ gcc –o test test.c –pedantic
test.c(5):warning: C++ style comments are not allowed in ISO C89
Aha, der Compiler verwendet hier anscheinend den ISO C89-Standard. Wir haben aber mittlerweile den ISO C99-Standard. Auch das können Sie dem Compiler mit dem Flag -std beibringen:
$ gcc –o test test.c –pedantic –std=c99
Es gibt noch mehrere -stds, Standard ist hierbei -std=gnu99.
Noch ein weiteres Beispiel, und dann will ich es damit belassen. Sollten im Verlaufe des Buches noch weitere Optionen verwendet werden, lasse ich Sie nicht im Stich, versprochen.
#include <stdio.h>
#include <math.h>
int main(int argc, char **argv) {
printf("%lf\n", sqrt(3.123));
return 0;
}
Das Programm verwendet eine mathematische Bibliothek, die Sie häufig unter Linux extra hinzulinken müssen. Eine Bibliothek können Sie mit dem Flag -l (kleines L) hinzufügen. Im Beispiel wäre dies:
$ gcc -o test test.c -lm
FAQ[2] Wenn ich mathematische Funktionen der Headerdatei math.h verwenden will, lässt sich der Quellcode nicht übersetzen. Linken Sie die entsprechende Bibliothek hinzu. Im Fall von math.h wäre dies –lm.
|
1.5.3 Klassifikation der Dateitypen
Der GCC akzeptiert eine Menge Dateitypen, die über die Dateiendung klassifiziert werden. Hierzu eine Tabelle zu den gängigen Dateiendungen:
Tabelle 1.2
Die wichtigsten Dateiendungen für den gcc
Extension
|
Dateityp
|
.c
|
C-Quelldatei
|
.c,.cc,.cpp,.cxx
|
C++-Quelldatei
|
.i
|
vom Präprozessor vorverarbeitete C-Quelldatei
|
.ii
|
vom Präprozessor vorverarbeitete C++-Quelldatei
|
.s
|
vom Präprozessor vorverarbeitete Assembler-Datei
|
.S
|
Assembler-Quelldatei
|
.o
|
Kompilierter Objektcode
|
.a, .so
|
Kompilierter Bibliothekscode
|
|