Ubuntu 16.04 Xenial Xerus
Die Gnu Compiler Collection, kurz GCC, ist eine Sammlung von Compilern und bietet eine einheitliche Schnittstelle zur Erstellung von Programmen in C, C++, Java, Objective-C, Fortran, Ada, Assembler und Go (ab Ubuntu 11.10) an. Die Sprachen D (gdc), Eiffel (smarteiffel), Lisp (gcl), Pascal (gpc) und Prolog (gprolog) sind nicht Teil der GCC, sondern sind eigenständige Programme des GNU-Projekts.
Die ursprüngliche Bedeutung von GCC war GNU C Compiler, aber weil seither noch eine Reihe weiterer Sprachen hinzugefügt wurde, hat sich die Bedeutung nach GNU Compiler Collection gewandelt. Heute wird der C-Compiler kleinbuchstabig als gcc bezeichnet, um eine Unterscheidung vom Ganzen zu ermöglichen.
Dieser Artikel soll helfen, Programme mithilfe der GCC unter Ubuntu zu kompilieren. Er hat nicht die Absicht, eine Einführung in die von ihr unterstützen Sprachen zu geben. Hierzu sollte man die entsprechenden Webseiten, Online-Tutorien oder auch ein gutes Buch lesen.
Wer Pakete irgendwelcher Art schon einmal selbst erstellt hat, der wird sich das Paket build-essential schon installiert haben. Es enthält neben je einem Compiler für C und C++ auch noch zahlreiche hilfreiche Werkzeuge, die unter den Entwicklern so regen Gebrauch finden (z.Bsp. Makefiles), dass sie unter jedem System, das etwas kompilieren möchte, als gegeben vorausgesetzt werden können. [1]
build-essential
mit apturl
Paketliste zum Kopieren:
sudo apt-get install build-essential
sudo aptitude install build-essential
Für andere Sprachen als C und C++ sind folgende Pakete notwendig [1]:
gcj (Java)
gobjc (Objective-C)
gfortran (Fortran)
gnat (universe, Ada)
mit apturl
Paketliste zum Kopieren:
sudo apt-get install gcj gobjc gfortran gnat
sudo aptitude install gcj gobjc gfortran gnat
Die grobe Struktur, wie mithilfe der GCC Projekte verschiedener Sprachen erstellt werden, gleicht derjenigen anderer Compiler. Erst wird die Quelldatei vorkompiliert, was dabei genau passiert, ist sprachabhängig. Meist läuft das Ganze so ab, dass zuerst ein Präprozessor aufgerufen wird, der unter anderem weitere Dateien einbindet, Makros ersetzt und Kommentare entfernt, also die Vorarbeit leistet. Danach wird die eigentliche Sprache angeschaut, optimiert und in Assemblerbefehle umgewandelt, die danach meist in Form von Objektdateien vorliegen.
Schlussendlich werden diese zusammengefasst, wobei man zumindest die Wahl zwischen einer grösseren Objektdatei, einer statischen Bibliothek, einer Programmbibliothek oder natürlich einem ausführbaren Programm selber.
Folgende Dateien [2] geben, nachdem sie kompiliert wurden [3], "Hello World" aus:
C++ (main.cc) | C (main.c) | Assembler (main.S) | Ada (main.adb) | ||||||||
|
|
|
| ||||||||
g++ main.cc | gcc main.c | gcc main.S | gcc -c main.adb (-c ist Voraussetzung) |
Wird nichts anderes angegeben, versucht der Compiler ein ausführbares Programm zu erstellen, das standardmäßig a.out heißt. Führt man dieses im Terminal [3] aus [4], so wird wie erwartet "Hello World" ausgegeben.
Es fällt auf, dass das "Hello World" von C++ nicht mit dem gcc, sondern mit dem g++ kompiliert wird. Der gcc erkennt zwar die Eingabesprache anhand der Endung (.cpp, .cc und .cxx wären alle korrekt), aber er verzichtet darauf, die Standardbibliothek von C++ zu verlinken. Der g++ macht dies automatisch und erspart so einiges an Aufwand.
Eine Erwähnung wert ist, dass diese drei Sprachen oder deren Objektdateien beliebig zusammengelinkt werden können. Es ist sogar möglich, dies alles in einem Befehl zu tun. Man muss nur an alle Standardbibliotheken denken.
Der GNU Java Compiler stellt eine zum offiziellen Compiler übereinstimmende Schnittstelle zur Verfügung und hat nichts mehr spezifisch für die GCC zu tun. Da auch die anderen Sprachen nur sporadisch vorkommen, sei auf die Dokumentation verwiesen, ein kurzer Blick gibt alles Nötige zu erkennen.
Es wird allgemein empfohlen, Programme ausschließlich mit folgenden Parametern zu erstellen (Erklärung weiter unten):
gcc -g -Wall -Wextra -pedantic-errors foo.c -o foo
Oft kommt noch entweder -O0 -ggdb3
für das Debugging oder -march=native -O3
für eine schnelle Ausführung hinzu.
Es gibt aber auch noch viele andere nützliche Parameter, die wichtigsten sind hier in der Tabelle zusammengefasst:
Parameter | Erklärung |
-o | Bestimmt den Namen der Ausgabedatei (Standard: „a.out“) |
-c | Der Quellcode wird nur kompiliert, aber noch nicht gelinkt (neue Endung oft „.o“) |
-OX | Optimiert den Quellcode; der Grad der Optimierung (Platzhalter X) kann 0 (nichts), 1 (Größe und Geschwindigkeit), 2 (Geschwindigkeit), 3 (Geschwindigkeit, aggressiv) oder s (Größe) sein) |
-march=nativ | Optimiert speziell für den vorhandenen Prozessor und wird auf anderen Architekturen nicht laufen. Ist für distcc nicht geeignet |
-lXXX | Bindet weitere Bibliotheken ein (z.B. -lncurses für libncurses) |
-std=XXX | Legt den Sprachstandard fest (XXX kann z.B. c99, c1x, c11, gnu++98, c++98, c++0x oder c++11 sein) |
-ansi | Erlaubt nur ANSI-C-konforme Konstrukte |
-Wall | Aktiviert sinnvolle Warnungen, die vom gcc-Compiler unterstützt werden. |
-Wextra | Aktiviert noch mehr Warnungen, die vom gcc-Compiler unterstützt werden. |
-pedantic | Weist auf nicht ISO-konforme Konstrukte mit einer Warnung hin (-pedantic-errors erzwingt Fehler) |
-v | Gibt die Kommandos und Schritte aus, die der Compiler gerade ausführt (Präprozessor, Compiler, Assembler, Linker...) |
-g | Fügt Debugging-Symbole in die Binärdatei ein |
-ggdb | Fügt weitere Debugging-Symbole für den GDB hinzu. Mit -ggdb3 wird alles mögliche unterstützt. |
So wichtig die Kenntnis der Kommandozeilenoptionen auch ist, um Programme zu kompilieren, gibt niemand den ganzen GCC-Aufruf in einer Shell ein – dafür sind Buildsysteme da. Wer etwas auf der Basis von Makefiles benutzt, der unterscheidet zwischen Optionen, die den Quelltext betreffen (CFLAGS
bzw. CCFLAGS
), und solchen, die das Linken betreffen (LDFLAGS
). Von den in der Tabelle aufgelisteten Optionen gehört nur -l
nicht in CFLAGS
.
Es kann vorkommen, dass es zu Fehlern kommt, wenn der "-l"-Parameter vor der Angabe der Quelldatei angegeben wird, daher hilft es, diesen Parameter zum Schluss anzugeben.
Diese Revision wurde am 11. November 2016 11:11 von Bugrider erstellt.