De c compiler

Een simpel programma

We zullen beginnen met het compileren van de simpele versie van het historische algoritme van "B. W. Kernighan and D. M. Ritchie" gepubliceerd in "The C Programming Language"
#include <stdio.h>

int main (int argc, char *argv[]) {
        printf ("Hello world\n");
        return (0);
}
We kunnen hier een programma van maken met behulp van de C compiler. Die zorgt er dan voor dat deze door mensen leesbare tekst omgezet wordt in computer instructies die met een redelijk grote efficientie uit gevoerd kunnen worden. Het commando daar voor is "cc -o hello hello.c". Hierna hebben we een programma dat we kunnen draaien.

Eigenlijk pakken we hier zelfs 2 stappen samen. Wat we eigenlijk doen met deze opdracht is het compileren van "hello.c tot een objectfile. Daarna gebruiken we de link editor ld om de initialisatie code, de libaries en onze code aan elkaar te plakken tot een programma.

Meerdere c files

Grote programma's worden vaak verdeeld over meerdere c files. Deze c files kunnen dan afzonderlijk gecompileerd worden en later aan elkaar gelinkt worden.

Libaries

Binnen de taal C kunnen we een hoop functies aanroepen die we gelijk kunnnen gebruiken zonder dat we hoeven te vertellen wat er in die functies moet gebeuren. Dat komt omdat er een hoop functies in de diverse libries zitten. De standaard librie libc wordt altijd mee gelinkt. Daar zitten functies zoals printf in die tekst naar het scherm schrijven.

Een groot aantal libries worden echter niet automatisch mee gelinkt. Als je gebruik van die libries wilt maken dan moet je dat expleciet opgeven. Het gaat daarbij bij voorbeeld om libaries die iets doen met X zoals libX11. Je kunt deze extra libries mee linken tijdens de link slag.

Headers

Omdat de c compiler moet weten welke functies er in een librarie zitten worden deze beschreven in de zogenaamde header files. In deze header files staan de beschrijvingen van de functies die gebruikt kunnen worden binnen een librarie. Voor de rest worden er macro's en constanten gedefineerd die het gebruik van de librarie gemakelijk moeten maken.

compileren

Bij compileren worden de C files om gezet in zogenaamde object files. Het compileren van afzonderlijke 'c' files gaat via de -c optie van de meeste compilers.

In de eerste slag van de compilatie word de pre processing gedaan. Dat wil zeggen dat de 'c' files samengevoegt worden met de header files en eventueele extra defines. Daarna worden de defines ingevult en de macros geexpandeerd.

In dit stadium wordt vaak de selectie gemaakt welk stuk code tussen de diverse #ifdef doorlopen worden. Een voorbeeld hiervan is:

#ifdef LINUX
        printf ("Yep it's linux\n");
#else
        printf ("Nop it's some stupid OS\n");
#endif
Als nu ergens in de header files (of op de commandline met -DLINUX) linux gedefineerd wordt dan zal deze code braaf "Yep it's linux" printen. Op deze manier wordt vaak os depend code effient opgelost want de overige code wordt gewoon genegeerd.

Linken

In de link slag worden alle object files samen gevoegt met de libries tot een programma. Het kan zowel om shared als archive libries gaan. De default is om de shared libries te gebruiken. Dat wil zeggen dat het programma runtime de functies haalt uit librarie die dan op het systeem staat. Het voordeel hiervan is dat die librarie dan maar een keer in het geheugen hoeft te zitten voor alle programma's.

De archive libries zijn libries waar alle functies in zitten die vervolgens tijdens het linken naar het programma gecopieerd worden. Hierdoor wordt het programma aanzienlijk groter (zowel op disk als tijdens het draaien). Het heeft echter als voordeel dat het programma niet afhankelijk is van de aanwezigheid van correcte shared libries.

Een voorbeeld

Hier zien we hoe eerst een c file gecompileerd wordt waarna dit c file gelinkt wordt aan de diverse X Libries.
# gcc -O -c Xexit.c
# gcc -o Xexit Xexit.o -L/usr/X11R6/lib -lXt -lXaw -lX11
Uiteraard is het mogenlijk om eerst meerdere c files te compileren en dan op de link regel ook meerdere object files aan elkaar te linken.

De belangrijkste vlaggen

De compilatie vlaggen

-g
Compileer debug informatie mee. Hierdoor kun je het programma eventueel regel voor regel tracen met b.v. gcc.
-O[0-6]
Optimaliseer de c code. Met deze optie wordt geprobeerd Het programma sneller te laten lopen door het te optimaliseren.
-D<MACRO>=<WAARDE>
Defineer dat een macro een bepaalde waarde heeft. Vaak wordt Dit gebruikt om aan te geven welk systeem het is. Dan zie je b.v. -DLINUX. Daarmee is linux gedefineerd en loopt de compilatie goed door de diverse #ifdef.
-I<path>
Zoek in het opgegeven path naar de include files.

De link vlaggen

-l<librarie naam>
Link deze librarie mee
-L<path>
Zoek in het opgegeven path naar de libries.