13.4. Kompilation

Jetzt, da die Software korrekt konfiguriert worden ist, muss sie noch kompiliert werden. Diese Stufe sollte normalerweise kein großes Problem mehr darstellen.

13.4.1. make

make ist das Standard-Werkzeug zur Kompilation freier Software. Es hat zwei Vorteile:

Die Anweisungen für make werden meist in der Datei Makefile oder einer anderen namens GNUMakefile gespeichert. make sucht bei Aufruf von selbst nach einer solchen Datei im aktuellen Verzeichnis. Befindet sich diese Datei in einem anderen Verzeichnis, müssen Sie make mittels der Option -f die entsprechende Datei samt Pfad übergeben.

13.4.2. Regeln

make arbeitet mit einem System von Abhängigkeiten. So erfordert die Kompilation einer Binärdatei (der ,,Zieldatei``) den erfolgreichen Abschluss mehrerer Stufen, eben der ,,Abhängigkeiten``. So müssen etwa die notwendigen Objektdateien main.o und init.o erzeugt, kompiliert und gelinkt werden um glloq übersetzen zu können. Diese Objektdateien sind ebenfalls Zieldateien, welche von den Quelldateien abhängen.

Dieser Absatz bietet nur einen kleinen Einblick in die Welt von make. Weitere Informationen erhalten Sie mit info make (Sie erinnern sich? :-)) oder im Software-Building-HOWTO. Noch mehr erfahren Sie in dem Buch Managing Projects with Make, 2nd edition, O'Reilly, von Andrew Oram und Steve Talbott.

13.4.3. Jetzt geht's los!

Der Gebrauch von make folgt einigen Konventionen:

Zuerst muss also das Programm mittels make kompiliert werden. Sie erhalten dann eine Ausgabe wie die Folgende (imaginäres Beispiel, es handelt sich hier um ein sehr kleines Programm):

$ make
gcc -c glloq.c -o glloq.o
gcc -c init.c -o init.o
gcc -c main.c -o main.o
gcc -lgtk -lgdk -lglib -lXext -lX11 -lm \
        glloq.o init.o main.o -o glloq

Erscheint der Prompt ohne eine Fehlermeldung von make, wurde das Programm korrekt kompiliert und kann nun installiert werden (siehe Abschnitt 13.5).

13.4.4. Erklärungen

Wenn Sie mal einen Blick in das Makefile werfen, werden Sie bekannte Kommandos wie rm, mv, cp usw. entdecken, aber auch unbekannte Zeichenfolgen wie $(CFLAGS).

Hierbei handelt es sich um Variablen, das heißt Zeichenfolgen, deren Inhalt für gewöhnlich am Beginn des Makefiles definiert wird. Das ist recht nützlich, wenn Sie die selben Optionen des Öfteren verwenden wollen.

Dieses Makefile etwa bildet – in Verbindung mit make all – die Zeichenfolge ,,bla`` ab:

TEST = bla
all:
        echo $(TEST)

Es folgen die häufigsten Variablen:

  1. CC: Das ist der Kompilierer. Für gewöhnlich ist es cc, der wiede­rum auf den gcc verweist. Falls Sie unsicher sind, ob dies auch bei Ihnen der Fall ist, sollten Sie hier gcc verwenden.

  2. LD: Dieses Programm ist für die letzte Kompilationsstufe zuständig (siehe Absatz Abschnitt 13.1.2.2). Für gewöhnlich ist dies ld.

  3. CFLAGS: Hier können dem Kompilierer zusätzliche Argumente für die ersten Kompilationsstufen übergeben werden, wie zum Beispiel:

    • -I<path>: Gibt zusätzliche Verzeichnisse für Kopfdateien an (Beispiel: -I/usr/X11R6/include sagt dem Kompilierer auch in diesem Verzeichnis nach Kopfdateien zu suchen).

    • -D<symbol>: Definiert ein zusätzliches Symbol. Das ist nützlich für Programme, deren Kompilation auf definierte Symbole angewiesen ist (Beispiel: Benutze die Datei string.h wenn HAVE_STRING_H definiert ist).

    Oft sehen Sie Zeilen wie diese:

    $(CC) $(CFLAGS) -c foo.c -o foo.o
  4. LDFLAGS (oder LFLAGS): Werden während der letzten Kompilationsphase benutzt. Unter ihnen befinden sich:

    • -L<path>: Spezifiziert einen zusätzlichen Bibliothekspfad (z.B.: -L/usr/X11R6/lib).

    • -l<library>: Spezifiziert eine weitere zu benutzende Bibliothek.

13.4.5. Was, wenn... es nicht klappt?

Keine Panik, das kann schon mal vorkommen. Einige häufige Ursachen sind:

  1. glloq.c:16: decl.h: No such file or directory                             . (glloq.c:16: decl.h: Keine Datei oder Verzeichnis solchen Namens)

    Der Kompilierer konnte die entsprechende Kopfdatei nicht finden obwohl die Konfigurationsstufe dem eigentlich hätte vorbeugen sollen. Sie können dieses Problem so lösen:

    • Überprüfen Sie, ob die Kopfdatei sich in einem dieser Ver­zeichnisse befindet: /usr/local/include, /usr/include, oder /usr/X11R6/include. Möglicherweise befindet sie sich auch in einer deren Unterverzeichnisse. Wenn nicht, benutzen Sie find oder locate, um festzustellen, wo sich diese Datei befin­det. Finden Sie sie nicht, überprüfen Sie, ob die passende Bibliothek überhaupt installiert ist. Beispiele zum Gebrauch von find und locate finden Sie in den Handbuchauzügen dieser Befehle.

    • Überprüfen Sie, ob die Kopfdatei lesbar ist (tippen Sie less <pfad>/<dateiname>.h, um das zu testen).

    • Befindet sich die Kopfdatei in einem Verzeichnis wie /usr/local/include oder /usr/X11R6/include, müssen Sie die­se dem Kompilierer manchmal als zusätzliches Argument über­geben. Öffnen Sie das entsprechende Makefile aus dem Ver­zeichnis, in dem die Kompilation fehlschlug mit einem Editor.

      (Schauen Sie sich die Fehlermeldung von make an. Überlicherweise geben die letzten Zeilen ein Verzeichnis an:

      make[1]: Leaving directory `/home/franz/Projekt/bla'

      Sind mehrere angegeben, wählen Sie das mit der höchsten [Nummer]. Sie können ihre Wahl überprüfen, indem Sie make in diesem Verzeichnis ein weiteres Mal starten. Sie sollten dann die selbe Fehlermeldung erhalten.)

      Fügen Sie die Option -I<Pfad> hinzu, wobei <Pfad> den Pfad der Kopfdatei bezeichnet. Häufig verfügt das Makefile bereits über einen solchen ,,Includepfad``, sodass Sie den Pfad lediglich dort hinzufügen müssen.

      Andernfalls fügen Sie die Zeichenkette direkt nach der Definition des Kompilierers (CC=<irgendetwas>) in das Makefile ein.

    • Starten Sie make erneut und überprüfen Sie, ob der zusätzliche Pfad verwendet wird.

    • Sollte es noch immer nicht funktionieren, bitten Sie am besten andere Benutzer um Hilfe (siehe Abschnitt 13.6.2).

  2. glloq.c:28: `struct bla' undeclared (first use                             . this function) (glloq.c:28: ,,struct bla`` ist nicht dekla­riert (erste Verwendung in dieser Funktion))

    Selbstdefinierte Datenstrukturen werden von den meisten Programmen verwendet. Normalerweise werden sie in Kopfdateien definiert. Diese Fehlermeldung deutet auf eine fehlende oder fehlerhafte Kopfdatei hin. In diesem Fall tun Sie bitte Folgendes:

    • Versuchen Sie herauszufinden, ob die fragliche Struktur in einer Datei deklariert wurde, die zum Paket gehört, das Sie durchbauen wollen, oder ob sie anderweitig von Ihrem Linux-Sys­tem definiert wird. Dazu bietet sich das Programm grep an.

      Angenommen, Sie befinden sich im Wurzelverzeichnis des Pakets:

      $ find . -name '*.h'| xargs grep 'struct foo' | less

      Möglicherweise erscheinen Dutzende Zeilen auf dem Schirm (z.B. immer wenn eine Funktion, die diesen Strukturtyp benutzt, definiert wird). Existiert der Strukturtyp, machen Sie die Zeile aus, wo die Struktur definiert wird, indem Sie die durch grep gewonnen Daten untersuchen.

      Eine Strukturdefinition sieht so aus:

      struct foo {
            <Inhalt der Struktur>
      };

      Vergleichen Sie, ob es dem entspricht, was Sie haben. Wenn das der Fall ist, verweist die .c-Datei nicht auf die Kopfdatei. Sie haben zwei Möglichkeiten:

      • Fügen Sie der .c-Datei folgende Zeile hinzu (möglichst am Anfang der Datei):

        #include "<filename>.h"
      • oder fügen Sie die Definition der Struktur durch Kopieren und Einfügen an den Anfang dieser Datei ein (nicht sehr schön, aber praktisch).

    • Ist dies nicht der Fall, tun Sie das selbe mit den Kopfdateien des Systems (diese befinden sich für gewöhnlich in den Ver­zeichnissen /usr/include, /usr/X11R6/include und /usr/local/include). Doch verwenden Sie nun die Zeile:

      #include <<filename>.h>
    • Können Sie die fragliche Struktur noch immer nicht finden, versuchen Sie herauszufinden, in welcher Bibliothek (d.h. Funktionssammlung) sie definiert sein sollte (lesen Sie in den Datei­en INSTALL oder README nach, ob dort irgendetwas über Bibliotheken und deren Versionen steht). Verlangt das Programm nach einer anderen Bibliotheksversion, sollten Sie diese installieren (solange nicht andere Programme gerade auf die installierte Version angewiesen sind... RPM wird Sie darauf hinweisen).

    • Sollte es noch immer nicht klappen, lesen Sie nach, ob das Programm überhaupt unter Linux laufen kann (manche Programme laufen nicht auf allen Varianten von Unix). Schauen Sie sich auch noch mal config.log genau an, manchmal ge­hen configure-Fehler ,,unter``.

  3. parse error (Syntaxanalysefehler)

    Dieses Problem kann sehr hinterhältig sein, da der Kompilierer den auslösenden Fehler bereits passiert haben kann. Manchmal handelt es sich aber auch ganz einfach nur um einen nicht definierten Datentyp. Eine Fehlermeldung wie diese:

    main.c:1: parse error before `glloq_t
    main.c:1: warning: data definition has no type or storage class

    weist darauf hin, dass der glloq_t-Typ nicht definiert worden ist. Die Lösung für dieses Problem ist ähnlich der für das vorhergehende.

    Anmerkung

    Alte curses-Bibliotheken können parse error aufweisen.

  4. no space left on device (Gerät voll)

    Sie haben nicht mehr genug Platz auf der aktuellen Partition, um die Kompilierung abzuschließen. Löschen Sie unnütze Daten oder setzen Sie die Kompilation auf einer anderen Partition fort.

  5. /usr/bin/ld: cannot open -lglloq: No such file or                     . directory (/usr/bin/ld: kann -lglloq nicht öffnen: kein solches Verzeichnis oder Datei)

    ld kann eine bestimmte Bibliothek nicht finden. Bibliotheken werden mittels -l<lib> (kurz für lib<lib>.so) in die Kompilation einbezogen. Sie können dieses Problem wie folgt lösen:

    1. Benutzen Sie locate, um festzustellen, ob sich die Bibliotheksdatei auf Ihrer Festplatte befindet. Grafische Bibliothe­ken befinden sich normalerweise in /usr/X11R6/lib. Zum Beispiel:

      $ locate libglloq

      Sollten Sie mit locate keinen Erfolg haben, versuchen Sie es mit find (z.B.: find /usr -name libglloq.so*). Sollten Sie die Bibliothek noch immer nicht finden, müssen Sie sie wohl installieren.

    2. Haben Sie die Bibliothek gefunden, prüfen Sie, ob sie sich in einem von ld erreichbaren Verzeichnis befindet. Die Konfi­gurationsdatei heißt ld.so.conf und befindet sich im Ver­zeichnis /etc. Fügen Sie das Verzeichnis hinzu und starten Sie ldconfig. Sie können auch die Variable LD_LIBRARY_PATH in LD_LIBRARY_PATH=$LD_LIBRARY_PATH:<lib> ändern, wo­bei <lib> der Pfad ist, den Sie hinzufügen wollen. Das dann mit export LD_LIBRARY_PATH dem System bekannt machen. Letztere Möglichkeit funktioniert in dieser Syntax ausschließlich für die Bash.

    3. Sollte auch dies fehlschlagen, überprüfen Sie mittels dem Kommando file, ob die Bibliothek im ELF-Format vorliegt. Sollte es sich um einen symbolischen Verweis handeln, überprüfen Sie, ob die dazugehörige Datei noch existiert (mittels nm).

  6. glloq.c(.text+0x34): undefined reference to                             . `glloq_init' (glloq.c(.text+0x34): nicht definierte Refe­renz zu ,glloq_init`)

    Hierbei handelt es sich um ein nicht aufgelöstes Symbol, normalerweise weist das auf ein Problem mit einer Bibliotheksdatei hin. Prüfen Sie Folgendes:

    • Zuerst einmal sollten Sie wissen, ob sich das Symbol überhaupt in einer bestimmten Bibliothek befinden soll. Ein Symbol, das mit gtk beginnt, gehört zur gtk-Bibliothek. Hat die Bibliothek einen sehr komplizierten Namen, können Sie ihre Symbole mit Hilfe des nm-Kommandos auflisten. Ein Beispiel:

      $ nm libglloq.so
      0000000000109df0 d glloq_message_func
      000000000010a984 b glloq_msg
      0000000000008a58 t glloq_nearest_pow
      0000000000109dd8 d glloq_free_list
      0000000000109cf8 d glloq_mem_chunk

      Wenn Sie nm zusammen mit der Option -o verwenden, wird der Name der Bibliothek auf jeder Zeile ausgegeben, was die Suche einfacher macht. Angenommen, Sie suchen nach einem Symbol wie bulgroz_max. Ein kruder Lösungsansatz wäre:

      $ nm /usr/lib/lib*.so | grep bulgroz_max
      $ nm /usr/X11R6/lib/lib*.so | grep bulgroz_max
      $ nm /usr/local/lib/lib*.so | grep bulgroz_max
      /usr/local/lib/libfrobnicate.so:000000000004d848 T bulgroz_max

      Offensichtlich ist das Symbol bulgroz_max in der Bibliothek frobnicate definiert (angezeigt durch das große T vor dem Namen). Jetzt müssen Sie den String -lfrobnicate nur noch dem Makefile hinzufügen, und zwar entweder zu den Variablen LDFLAGS, LFLAGS oder (schlimmstenfalls) CC oder direkt in der Zeile, die für die Erstellung der Binärdatei zuständig ist.

    • es liegt ein Versionskonflikt vor: die Software braucht eine andere Version der Bibliothek als die, die bei Ihnen installiert ist. Lesen Sie die README oder INSTALL-Datei für mehr Informationen. Manchmal kann Ihnen auch der Autor der Software weiterhelfen.

    • nicht alle Objektdateien des Pakets sind korrekt gelinkt. Die Datei, die diese Funktion definiert, ist nicht angegeben. Tippen Sie nm -o *.o, um die entsprechende Datei zu finden und fügen Sie sie der Kompilationszeile hinzu.

    • die fragliche Funktion oder Variable ist exotisch. Editieren Sie die verantwortliche Quelldatei, um den Aufruf zu verhindern. Dies ist allerdings eine verzweifelte Maßnahme und kann zu schweren Laufzeitanomalien der Software führen (Segmentier­ungsfehler u.ä.)

  7. Segmentation fault (core dumped) (Segmentierungsfehler (Speicherauszug erstellt))

    Sehr seltener Fehler des Kompilierers. Erwägen Sie, ihn durch eine neuere Version zu ersetzen.

  8. No space on /tmp (Kein Platz in /tmp)

    Die Kompilation braucht einiges an Festplattenspeicher während der verschiedenen Phasen. Schaffen Sie mehr Platz auf der Partition, aber löschen Sie dabei nur Dateien, von denen Sie wissen, dass Sie sie nicht mehr brauchen! Einige Programme werden es Ihnen übel nehmen, wenn Sie ihnen ihre Dateien in /tmp einfach weglöschen...

     

     

  9. make/configure in Endlosschleife

    Hierbei handelt es sich meistens um ein Problem mit der Systemzeit. make muss die Systemzeit kennen und das Zugriffsdatum vieler Dateien. Es vergleicht Zugriffsdaten, um zu bestimmen, ob eine Zieldatei jünger ist als ihre Abhängigkeiten.

    Probleme mit der Systemzeit können make dazu bringen, bereits abgeschlossene Kompilationsprozesse endlos zu wiederholen. In solchen Fällen hilft meist das Kommando touch, welches den Zeitstempel von Dateien aktualisiert.

    Zum Beispiel:

    $ touch *

    Oder auch (nicht schön, aber effektiv):

    $ find . | xargs touch

Tux on Star from MandrakeSoft Linux ist ein eingetragenes Warenzeichen von Linus Torvalds. Alle anderen Warenzeichen und Copyrights sind das Eigentum ihrer Inhaber.
Sofern nichts anderes Angaben ist, unterliegen die Inhalte der Seiten sowie alle Bilder dem Copyright von MandrakeSoft S.A. und MandrakeSoft Inc. 2000.
http://www.linux-mandrake.com/