So beheben Sie Fehler bei der Ausführung von make

Aus LinuxUser 06/2004

So beheben Sie Fehler bei der Ausführung von make

Handgemacht

Wenn das configure-Skript fehlerfrei durchgelaufen ist, stehen nur noch make und make install zwischen dem Anwender und der neuen Software. Auch hier steckt der Teufel bisweilen im Detail.

Fehler bei make und make install sind ein Kuriosum, das es eigentlich gar nicht geben dürfte. Denn was das Programm make beim Kompilieren und Installieren einer Software tut, steht im Makefile, das das configure-Skript erstellt hat: Ermittelt es z. B., dass eine benötigte Bibliothek im Verzeichnis /usr/local/multimedia/lib liegt, landet diese Information als Aufrufparameter für den Compiler im Makefile.

Oberflächlich geprüft

Eigentlich sollte diese Datei daher perfekt auf Ihr System zugeschnitten sein und make fehlerfrei durchlaufen. Klappt das nicht, enthält im schlimmsten Fall der Quelltext des Programms einen Fehler. Dann sind Sie auf die Hilfe des Entwicklers angewiesen.

Manche Probleme bekommen Sie jedoch selbst in den Griff, z. B. das Problem schlampiger configure-Skripte, die nicht alle Voraussetzungen für einen erfolgreichen make-Aufruf abklären (Listing 1).

Geht für make etwas schief, gibt das Programm oft mehrere Dutzend Fehlermeldungen aus. Entscheidend ist die erste, bei allen weiteren handelt es sich um Folgefehler. In Listing 1 bricht make ab, weil der Compiler mimepp.h nicht findet. Dieser Fehler tritt auf, während er die Datei decodeRFC2047.cpp übersetzt: In Zeile 21 bemerkt er das Problem.

Bei einer eindeutigen Fehlermeldung wie mimelib/mimepp.h: No such file or directory muss Sie der zugehörige Quelltext nicht kümmern. Schauen Sie einfach mit urpmf mimepp.h (Mandrake Linux), pin mimepp.h (Suse Linux) oder der Dateisuche unter http://www.rpmseek.com/ nach dem Päckchen, in dem die vermisste Datei steckt.

Unter Mandrake Linux liefert die Suche kdenetwork-devel als Treffer. Nachdem Sie dieses Paket installiert haben, rufen Sie erneut make auf. Nun findet der gcc die Datei mimepp.h, und make bricht nicht mehr ab.

Listing 1

Abbruch wegen fehlender Prüfung im

configure

-Skript

[andi@doomtrain kshowmail-3.1.0-pre1]$ make[…]
decodeRFC2047.cpp:21:28: mimelib/mimepp.h: No such file or directory
decodeRFC2047.cpp: In function `QCString decodeQuotedPrintable(const QCString&)':
decodeRFC2047.cpp:40: error: `DwString' undeclared (first use this function)[…]
make[2]:  * [decodeRFC2047.o] Fehler 1
make[2]: Leaving directory `/home/andi/test/kshowmail-3.1.0-pre1/kshowmail'
make[1]:  * [all-recursive] Fehler 1
make[1]: Leaving directory `/home/andi/test/kshowmail-3.1.0-pre1'
make:  * [all] Fehler 2

Sehr selten “übersieht” make Dateien, obwohl sie auf dem System vorhanden sind. Ein Beispiel dafür finden Sie im Artikel “Knopfleiste” auf Seite 56.

Vergessliche Entwickler

Wer es sich zutraut, selbst etwas in den Programmcode einzufügen, beseitigt auch Fehler wie in Listing 2. Was so kryptisch daherkommt, pflücken Sie Stück für Stück auseinander: Der Compiler übersetzt gerade die Datei legacyimport.cpp, die am Anfang jeder Zeile auftaucht. In Zeile 143 steht KInputDialog, womit der Compiler nichts anzufangen weiß (undeclared (first use this function)). Undeclared (“nicht deklariert”) bedeutet, dass die Klasse KInputDialog, die hier das erste Mal in einer Funktion zum Einsatz kommt, nirgendwo definiert ist, wo der Compiler nachschaut. Dadurch fehlt ein Teil Code, den er zum Übersetzen braucht: Er vermisst die Anweisungen, wie er ein Fenster mit Eingabezeile und Ok-Button erzeugt.

Um die vielen Arbeitsschritte, die ein solch komplexes Objekt erzeugen, nicht jedes Mal neu schreiben zu müssen, legen Programmierer sie in wiederverwertbaren Klassen ab. Brauchen sie ein Objekt dieser Klasse, rufen sie einfach den jeweiligen Konstruktor auf.

Klassen gehören zu den Schnittstellen eines Programms und werden bei C- und C++-Programmen daher normalerweise in den auf .h endenden Header-Dateien aus den Dev(el)-Paketen (siehe Seite 28) abgelegt. Damit alle an der Übersetzung beteiligten Programme diese Klassen finden, schreibt der Entwickler so genannte Include-Zeilen in den Quelltext:

#include <kmessagebox.h>

weist den Compiler an, Code einzubinden, der in der Datei kmessagebox.h in einem der Include-Verzeichnisse steht. Das sind die Verzeichnisse, die das Makefile dem Compiler als Option in der Form -I/hier/liegen/die/Includes mitgibt. Lautet die Zeile hingegen

#include "meininclude.h"

fehlen also die spitzen Klammern, verwendet der Compiler die Datei meininclude.h, die im selben Verzeichnis wie die zu übersetzende Datei liegt.

Da Sie in Listing 2 keine Meldung bekommen, dass eine Datei fehlt, hat der Programmierer wahrscheinlich vergessen, die Datei, die die Klasse enthält, einzubinden. Um dieses Missgeschick auszubügeln, gilt es, sie zu finden.

Das erledigt der Befehl grep, der Dateien nach einem Suchbegriff durchforstet. Den Anfang machen Sie im Quellcode-Verzeichnis bzw. in dessen Unterverzeichnis src. grep KInputDialog *.h sucht in allen auf .h endenden Dateien nach der Zeichenfolge KInputDialog. Im Beispiel führt das nicht zum Erfolg, denn KInputDialog ist eine allgemeine KDE-Klasse, die sich in den Include-Verzeichnissen des Systems befindet. Das sind gewöhnlich /usr/include und /usr/local/include, bei KDE manchmal aber auch /opt/kde3/include.

grep -r KInputDialog /usr/local/include/*

(-r für rekursiv) liefert auf unserem Beispielsystem gleich zwei Treffer: die Dateien kinputdialog.h und klineeditdlg.h. Der passende Eintrag in der zweiten ist nur ein Kommentar, aber die Zeilen aus kinputdialog.h sehen eindeutig so kompliziert aus, wie man sich eine Klasse (class) vorstellt:

/usr/local/include/kinputdialog.h:class KInputDialog : public KDialogBase
/usr/local/include/kinputdialog.h:    KInputDialog( const QString &caption, const QString &label,

Außerdem, auch das ist bei der Suche nach Klassendefinitionen ein gutes Omen, heißt die Datei wie die Klasse – nur kleingeschrieben. Um herauszufinden, ob wir richtig liegen, tragen wir in die Datei legacyimport.cpp unter alle anderen Include-Zeilen

#include <kinputdialog.h>

ein (Abbildung 1). make meldet danach keine Fehler mehr. Die beschriebene Methode führt natürlich nur zum Ziel, wenn die Include-Datei mit der passenden Definition bereits auf Ihrem System installiert ist.

Abbildung 1: Hinzugefügte Include-Zeile in <code srcset=

legacyimport.cpp.” width=”300″ height=”160″ /> Abbildung 1: Hinzugefügte Include-Zeile in legacyimport.cpp.

Listing 2

Fehlermeldung wegen vergessener Include-Zeile

[andi@doomtrain]$ make[…]
legacyimport.cpp: In member function `void KLegacyImport::finished()':
legacyimport.cpp:143: `KInputDialog' undeclared (first use this function)
legacyimport.cpp:143: (Each undeclared identifier is reported only once for each
function it appears in.)
legacyimport.cpp:143: parse error before `::' token
make:  * [legacyimport.o] Error 1

Installation mit Hinternissen

Fehler beim Aufruf von make install gibt es fast nie. Meistens treten sie auf, wenn Sie ein Programm in ein anderes Verzeichnis installieren als nach /usr/local. Soll eine Anwendung in /usr/local/test landen, scheitert manchmal das Kopieren der Dateien daran, dass der Programmierer vergessen hat, im Makefile die Befehle einzutragen, die die Zielverzeichnisse erstellen.

Solange /usr/local/test/bin noch nicht existiert, schlägt jeder Versuch fehl, eine Datei dorthin zu kopieren. Am schnellsten beseitigen Sie solche Fehler, indem Sie die Zielverzeichnisse, die Sie aus der Fehlermeldung ersehen, mit mkdir selbst erstellen.

Ärger nach der Installation

Ist das Selbstkompilat erst installiert, folgt beim Start einer neuen KDE-Anwendung oft Ernüchterung: Das Programm findet seine Plugins nicht, präsentiert sich mit nackter Werkzeugleiste ohne Icons und spricht natürlich auch kein Deutsch (Abbildung 2). Per Default suchen KDE-Anwendungen nämlich nur unterhalb des Verzeichnisses, in dem die KDE-Kernanwendungen samt Zubehör liegen, nach ihren Daten. Unter Suse Linux heißt dieses KDE-Verzeichnis /opt/kde3, unter Red Hat und Mandrake Linux /usr. Bei selbst übersetzten KDE-Anwendungen wandern die Icons, Plugins und Hilfe-Dateien jedoch nach /usr/local.

In Web-Foren erhalten Fragesteller bei diesem Problem meistens den Rat, die Anwendung erneut zu übersetzen und dieses Mal beim ./configure-Aufruf das KDE-Verzeichnis als Installationsziel anzugeben, z. B. mit ./configure --prefix=/opt/kde3.

Obwohl die Anwendungen danach wie erwartet funktionieren, ist diese Lösung nicht ideal, sondern mitunter sogar gefährlich. Das Verzeichnis /opt/kde3 gehört bei Suse ebenso wie /usr unter Red Hat und Mandrake Linux der Paketverwaltung. Eigenkompilate haben dort nichts zu suchen, denn die Paketverwaltung kann selbst übersetzte Software nicht entfernen. Bei einem Distributions- oder KDE-Update können diese Dateien zu einem instabilen KDE führen. An die selbstkompilierten Anwendungen erinnert man sich zu diesem Zeitpunkt meistens nicht, und selbst wenn, hat man kaum eine Chance, den Störenfried aufzuspüren.

Die saubere Lösung besteht darin, seinen KDE-Programmen mitzuteilen, dass es noch ein weiteres Datenverzeichnis gibt. Das geht über die Umgebungsvariable KDEDIRS. Der Befehl

export KDEDIRS=/usr/local:/opt/kde3

setzt sie auf die beiden für Suse Linux relevanten Verzeichnisse: /usr/local, wo selbst kompilierte Software landet, und /opt/kde3, wo das Distributions-KDE liegt. Der passende Befehl unter Red Hat und Mandrake Linux lautet export KDEDIRS=/usr/local:/usr.

Aus dem so präparierten Kommandozeilenfenster gestartet, halten KDE-Anwendungen nun auch unterhalb von /usr/local nach ihren Daten Ausschau. Wollen Sie die Umgebungsvariable dauerhaft setzen, ist die Datei .bash_profile in Ihrem /home-Verzeichnis der richtige Ort. Befehle, die Sie dort eintragen, führt die Bash aus, sobald Sie sich am System anmelden.

Ein wenig mehr Arbeit wartet auf Suse-Linux-Nutzer, da dort der Befehl

unset KDEDIRS

in der Datei /opt/kde3/bin/startkde steht. Dieses Shell-Skript startet den KDE-Desktop. unset löscht den Inhalt von Umgebungsvariablen und ist damit ein Gegenstück zu export. Da das Skript ~/.bash_profile vor dem Start des Desktops ausgeführt wird, erfährt KDE gar nicht, dass es noch ein weiteres Datenverzeichnis gibt.

Um auch unter Suse Linux die Variable zu setzen, öffnen Sie die Datei /opt/kde3/bin/startkde als root mit einem Editor und setzen vor die Zeile unset KDEDIRS eine Raute (#). Sie gilt als Kommentarzeichen, so dass die Shell den Rest der Zeile nicht ausführt. Wollen Sie die Änderung später einmal rückgängig machen, entfernen Sie das Zeichen einfach.

Abbildung 2: Ein nach <code srcset=

/usr/local installiertes K3b findet weder seine Icons noch die Plugins.” width=”300″ height=”227″ /> Abbildung 2: Ein nach /usr/local installiertes K3b findet weder seine Icons noch die Plugins.

Glossar

Makefile

Diese Regeldatei enthält alle Befehle und Informationen, die zum Übersetzen eines Programms nötig sind, z. B. den Speicherort von Bibliotheken und Include-Dateien, die nötigen Compiler-Aufrufe und die Kopierbefehle, die die fertig übersetzte Anwendung ins Zielverzeichnis installieren.

LinuxUser 06/2004 KAUFEN
EINZELNE AUSGABE
ABONNEMENTS
TABLET & SMARTPHONE APPS
E-Mail Benachrichtigung
Benachrichtige mich zu:

Hinweis: Dieser Artikel ist älter als ein Jahr, enthaltene Informationen sind möglicherweise veraltet.

0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben