Bisher haben Sie neben der Sprache C++ auch eine Reihe von Werkzeugen kennen gelernt, mit denen Sie eigentlich alle Entwicklungsaufgaben erledigen könnten. Das ist jedoch zuweilen etwas mühsam; während Freaks auf ihre Kommandozeilentools schwören, mutet Ihnen die Arbeitsweise vielleicht ein wenig archaisch an. Wesentlich bequemer und damit auch produktiver wird die Programmierung mit integrierten Entwicklungsumgebungen, Integrated Development Environments oder kurz IDEs. Wenn Sie schon Programme unter Windows oder auf dem Mac geschrieben haben, kennen Sie sicher Umgebungen wie Microsoft Visual Studio, Borland Delphi oder Metrowerks CodeWarrior.
Diese verfügen alle über folgende Merkmale:
werden wir uns ausführlich damit beschäftigen.
Doch zunächst will ich Ihnen zeigen, dass auch der bereits vorgestellte XEmacs
zu einer fast vollwertigen IDE werden kann. Abschließend werde ich Sie ab Seite
noch auf einige weitere interessante IDEs hinweisen.
Bereits als wir ab Seite
den XEmacs näher
betrachteten, habe ich Sie darauf aufmerksam gemacht, dass er eigentlich viel mehr
als nur ein Editor ist. Es gibt für ihn so viele Erweiterungen, dass Sie nichts
anderes mehr benötigen. Natürlich gilt das auch im Hinblick auf die Programmierung.
Wir wollen uns nun die wichtigsten Funktionen ansehen, die Sie bei der Verwendung
des XEmacs als IDE brauchen werden.
Obwohl ich hier nur vom XEmacs rede, funktionieren die meisten der vorgestellten Merkmale auch beim GNU Emacs.
Dass der Editor Syntaxeinfärbung, Markierung von Klammern und automatisches Einrücken
beherrscht, habe ich Ihnen schon auf Seite
gezeigt.
Anhand der Dateiendung (.cc, .C, .cpp, .cxx, .hh
oder .hxx) erkennt er automatisch, dass es sich dabei um einen C++-Quelltext
handelt und passt seinen Modus entsprechend an. Auch die Navigationsmöglichkeiten
ergeben sich daraus.
Liegt die Dokumentation zu einer Funktion im UNIX-man-Format vor, so können Sie diese direkt im XEmacs aufrufen. Das ist zum Beispiel für die C-Standardbibliothek und einige sonstige Bibliotheken der Fall.
Angenommen, Sie möchten die Bedeutung der Parameter der Funktion strstr()
wissen. Dann klicken Sie doppelt darauf, um sie zu markieren. Dann wählen Sie
aus dem Menü HELP | MANUALS | UNIX MANUAL und erhalten in der
Echo-Zeile, also der untersten Zeile des Fensters, die Meldung:
Manual entry (default strstr):
Wenn Sie mit dem XEmacs Programme entwickeln, ist es am sinnvollsten, mit Makefiles zu arbeiten. Natürlich können Sie auch hier die Quelldateien einzeln übersetzen und linken lassen, aber das ist genauso mühselig wie über die Kommandozeile. Gehen wir also davon aus, Sie hätten bereits ein Makefile (diese lassen sich ja auch sehr komfortabel mit XEmacs erstellen und bearbeiten).
Um den Compiler zu starten, gibt es wieder viele Wege: die Schaltfläche COMPILE,
der Menüpunkt TOOLS | COMPILE oder ganz klassisch über die Tastatur:
Alt+X und dann compile eingeben. Dann werden Sie
noch gefragt, wie Sie make aufrufen wollen. Die Vorgabe enthält die
Option -k, die dafür sorgt, dass der Übersetzungsvorgang nicht bei einer
fehlerhaften Datei abgebrochen wird, sondern dass andere Dateien, die von dieser unabhängig
sind, auch noch kompiliert werden.
Treten bei der Übersetzung Fehler auf, so werden die entsprechenden Meldungen im unteren
Teil des Fensters angezeigt. Mit einem Klick darauf gelangen Sie sofort an die
angegebene Stelle im Quelltext und können nach der Ursache suchen. Im Programm
in Abbildung
fehlt einfach das Semikolon nach der Anweisung
innerhalb der Schleife.
Ebenso leicht ist es, das erfolgreich erzeugte Programm aus dem XEmacs zu starten.
Da es ja auch einem Shell-Kommando entspricht, müssen Sie nur noch darauf achten,
den richtigen Pfad zu verwenden. Als lokales Verzeichnis sieht der XEmacs immer
das Verzeichnis an, aus dem er gestartet wurde. Liegt Ihr Programm nicht dort,
müssen Sie einen relativen oder absoluten Pfad mit angeben. Rufen Sie also TOOLS
| SHELL COMMAND oder Alt+! auf und geben Sie den Namen Ihres
Programms und gegebenenfalls weitere Argumente ein. Wie Sie wissen, müssen Sie
das nur das erste Mal tun; der XEmacs merkt sich solche Eingaben und lässt Sie
mittels der Tasten
und
auf frühere zugreifen.
Die Ausgaben Ihres Programms erscheinen dann in einem Fenster des XEmacs.
Wenn Sie Ihr Programm debuggen wollen, gehen Sie ähnlich vor. Standardmäßig ist
der XEmacs mit dem gdb integriert, also dem textorientierten Debugger,
den Sie von Seite
kennen. Wenn Sie nun TOOLS | DEBUG
(GDB) wählen, werden Sie noch nach dem Namen der ausführbaren Datei gefragt
und los geht's. Nun ändert sich auch die Leiste der Schaltflächen und es erscheinen
solche, die für das Debuggen gebraucht werden (Abbildung
);
wenn Sie den Mauszeiger über eine davon bewegen, können Sie deren Bedeutung
in der Echo-Zeile lesen.
Nun können Sie entweder über die Schaltflächen oder direkt an der Eingabeaufforderung des gdb alle bekannten Befehle aufrufen und auf diese Weise Schritt für Schritt die Fehler in Ihrem Programm suchen.
Auch die Funktionen zur Versionskontrolle sind direkt
in den XEmacs integriert. Unter Linux wird dabei standardmäßig RCS
verwendet (siehe Seite
). Aber auch CVS
(siehe Seite
)
und andere werden unterstützt. Die entsprechenden Funktionen sind hinter dem
Menüpunkt TOOLS | VC verborgen - aber natürlich gibt es für alles
auch wieder Tastenkürzel. Wenn Sie sie nicht standardmäßig aktiviert
haben, müssen Sie die Unterstützung für die Versionsverwaltung vor dem
ersten Aufruf mit TOOLS | VC | LOAD VC laden.
Jede Versionsverwaltung legt eine Reihe von Dateien zur eigenen Buchhaltung an. XEmacs orientiert sich an diesen und versucht, das System, das jeweils für die aktuelle Datei passt, auch zu unterstützen. Gibt es also beispielsweise ein Unterverzeichnis RCS, so werden die RCS-Funktionen aktiviert und so weiter. Die Aktionen, die XEmacs unter TOOLS | VC bietet, beziehen sich vorwiegend auf die Datei im aktuellen Puffer.
Die wichtigsten Funktionen für RCS sind:
Die wichtigsten Funktionen für CVS sind:
Ein sehr hilfreiches Werkzeug zum Vergleich von Dateien, Verzeichnissen und anderem ist Ediff. Sie erreichen es über das Menü TOOLS | COMPARE des XEmacs. Wenn Sie das Untermenü öffnen, sehen Sie bereits die Möglichkeiten, die Ihnen Ediff bietet. Wir wollen hier zwei Dateien miteinander vergleichen, genauer zwei Versionen einer Datei.
Dazu rufen Sie TOOLS | COMPARE | FILE WITH REVISION auf. Um die Fragen, die XEmacs stellt, müssen Sie sich nicht weiter kümmern; Sie möchten ja ohnehin nur den Standardfall bearbeiten, nämlich den aktuellen Puffer mit seiner letzten archivierten Version vergleichen.
Anschließend öffnet sich ein kleines zusätzliches Steuerfenster, über das Sie Ihre Ediff-Befehle geben können. Dabei müssen Sie beachten, dass die Ediff-Tastenkombinationen nur dann funktionieren, wenn das Steuerfenster das aktive ist. Gerade wenn Sie Ihre Oberfläche so eingestellt haben, dass die Aktivierung der Fenster schon bei der Positionierung des Mauszeigers darüber erfolgen soll, kann es immer wieder zu Problemen kommen, die Ediff mit einem Piepser quittiert.
Das Arbeitsfenster des XEmacs teilt sich nun in zwei Bereiche auf, die die beiden
miteinander zu vergleichenden Dateien (hier Versionen) enthalten (Abbildung
). Aus der jeweiligen Statuszeile erfahren Sie, welche welche
ist.
Mit Hilfe von Ediff navigieren Sie nun durch die sich unterscheidenden Bereiche der Dateien. Diese sind jeweils andersfarbig hervorgehoben. Abweichende Zeilen werden als Ganzes markiert; einzelne Abweichungen darin werden mit einer weiteren Farbe hervorgehoben. In Prosa klingt das alles sehr kompliziert, wird aber beim konkreten Einsatz schnell einsichtig.
Auch während des Vergleiches können Sie beide Fenster noch editieren (sofern nicht eines davon schreibgeschützt ist). Die meisten Aktionen geben Sie aber durch einfache Tasten über das Ediff-Fenster an. Die wichtigsten davon sind:
Sie haben gesehen, dass der XEmacs sich durchaus gut für die Programmierung eignet. Viele der bekannten Open-Source-Programmpakete wurden mit ihm geschrieben. Er enthält einen komfortablen Editor mit Syntaxeinfärbung und Einrückung, erlaubt das Starten des Compilers und das Springen zu Fehlerstellen, integriert den Debugger und die Versionsverwaltung und bietet mit Ediff ein äußerst praktisches Werkzeug zum Vergleich von Dateien und Versionen.
Von den Kriterien für IDEs, die wir am Anfang des Kapitels aufgestellt haben, erfüllt er die Punkte 3 und 6 nicht. Gerade die Verwaltung größerer Projekte mit mehreren Abhängigkeiten wird daher schwierig. Für Umsteiger aus der Windows-Welt sind vielleicht gerade diese Aspekte entscheidend, da sie den Umgang mit Make-Dateien nicht gewohnt sind. Aber auch diese Funktionen wird der XEmacs früher oder später beherrschen.
Auch das KDE-Projekt hat mit KDevelop eine eigene integrierte Entwicklungsumgebung hervorgebracht. Wie alles in KDE steht auch diese unter GPL und ist frei im Quelltext verfügbar. Die aktuellste Version erhalten Sie stets von www.kdevelop.org.
Das Programm erfüllt alle Kriterien vom Anfang dieses Kapitels, bringt einen komfortablen Editor mit, startet den Compiler (standardmäßig natürlich den GCC) direkt aus der IDE, lässt die Optionen für Kompilieren, Linken und make über Dialoge einstellen, springt aus der Fehlerausgabe direkt durch Doppelklick an die entsprechende Programmstelle, bindet einen Debugger ein, verwaltet automatisch die Makefiles und hat die Versionsverwaltung integriert.
Aber KDevelop geht noch sehr viel weiter, als nur diese Kriterien zu erfüllen. Die Erzeugung der Make-Dateien macht beispielsweise intensiv von autoconf Gebrauch, um die Generierung automatisch an die lokale Hard- und Softwareumgebung anzupassen. Außerdem ist mit KBabel ein zusätzliches Werkzeug direkt angebunden, um die Applikationen von Anfang an mehrsprachig zu entwickeln.
Und im Gegensatz zu allen anderen hier vorgestellten IDEs unterstützt KDevelop auch die Entwicklung von grafischen Benutzeroberflächen. Dazu nutzt es die in KDE verwendeten Prinzipien der Programmierung von grafischen Anwendungen auf der Basis der Klassenbibliothek Qt. Für die Gestaltung von Dialogen und fensterbasierten Applikationen bringt KDevelop kein eigenes Werkzeug mit, sondern setzt den Qt Designer ein, der vom Qt-Hersteller Trolltech stammt. Die dort erzeugten Dateien kann KDevelop in seine Projekte einbinden, daraus die nötigen Klassen generieren und übersetzen. Für andere Aufgaben gibt es wieder andere externe Werkzeuge, etwa KIconEdit für die Gestaltung von Icons.
Generell gilt auch auch bei KDevelop, was wir noch bei anderen IDEs feststellen werden und was im Gegensatz zu den unter Windows üblichen Gepflogenheiten steht: Die IDE ist in weiten Teilen nur ein Frontend, ein grafisch bedienbarer Zugriffsweg auf die darunter liegenden Werkzeuge. Compiler, Debugger etc. sind nicht im Lieferumfang enthalten, sondern als externe Tools vorausgesetzt und eingebunden. Auf diese Weise erreicht die IDE aber auch ein hohes Maß an Flexibilität, und die Entwicklung kann sich auf die eigene Funktionalität konzentrieren.
Außerdem sind die folgenden zusätzlichen Werkzeuge zwar optional, aber recht hilfreich und für bestimmte Funktionen erforderlich:
Wenn Sie nach der Installation des rpm-Paketes oder aus dem übersetzten Sourcecode
KDevelop das erste Mal aufrufen, müssen Sie noch einige Einstellungen festlegen.
So können Sie beispielsweise wählen, ob Sie für Syntaxhervorhebungen eher den Stil
von KDevelop, den des Emacs oder von KWrite (siehe auch Seite
) wünschen. Sie können außerdem festlegen, wie
sich die Fenster von KDevelop auf dem Bildschirm verteilen sollen
(MDI, Top-Frame, Reiter).
Anschließend
prüft die Installationsroutine Ihr System und weist Sie gegebenenfalls auf fehlende
Programme oder Dokumentationen hin, die Sie bei Ihrer Arbeit mit KDevelop brauchen
könnten. Zum Schluss erzeugt KDevelop wenn nötig noch einen
Suchindex für das von Ihnen installierte Dokumentationsmaterial zu
KDE und Qt, damit Sie bequemer mit Suchbegriffen darauf zugreifen können.
Ein Vorteil von KDevelop ist, dass Sie damit auch Applikationen für neuere Qt- und KDE-Versionen erstellen können. Dazu müssen Sie deren Bibliotheken lediglich an geeigneter Stelle ablegen und im Dialog OPTIONEN | KDEVELOP-EINRICHTUNG unter PFAD die jeweiligen Verzeichnisse eintragen. Auch andere Basiseinstellungen können Sie in diesem Dialog vornehmen.
Fig:KDevelop zeigt die Version 2.1) ist in vier Teile
gegliedert:
|
Der Editor hält sich an alle Konventionen, die Sie aus anderen Programmen für KDE kennen. So können Sie mit Strg+X ausschneiden, mit Strg+Z die letzte Aktion rückgängig machen, mit Strg+S speichern und so fort. Die Syntaxeinfärbung ist übersichtlich, ein automatisches Einrücken ist ebenso möglich wie das automatische Einfügen von schließenden Klammern beim Tippen oder das vertikale Selektieren (zu aktivieren unter EINSTELLUNGEN | EDITOR). Zudem können Sie auch bei KDevelop Lesezeichen in den Quelltexten setzen, zu denen Sie dann später springen können.
Und noch eine nette Funktion bei KDevelop: Wenn Sie eine Datei geändert haben, die Änderungen aber noch nicht gespeichert sind, so kommt zu dem kugelartigen grünen Symbol in der KDE-Kontrollleiste noch ein zweites hinzu: eine Diskette. Auf diese Weise erkennen Sie sofort, wenn Sie irgendwo das Speichern vergessen haben - auch wenn Sie gerade in einem anderen Programm arbeiten.
Apropos suchen: Natürlich können Sie auch in Ihrem Editor nach einem Begriff suchen. KDevelop hat zusätzlich das kleine Werkzeug grep eingebunden, mit dem Sie in verschiedenen Dateien gleichzeitig suchen können. Markieren Sie einfach den gewünschten Ausdruck und wählen Sie GREP aus dem Kontextmenü.
Im selben Kontextmenü darunter gibt es noch zwei andere praktische Funktionen: SUCHEN und MANPAGE. Die erste sucht nach dem markierten Begriff in der eingerichteten Dokumentation (mittels der durch htDig eingerichteten Volltextsuche), die zweite versucht, eine mögliche zugehörige man-Seite zu öffnen.
KDevelop
orientiert
sich immer mehr an den großen IDEs unter Windows
wie Microsoft Visual Studio oder Borland C++Builder und versucht,
deren Funktionsmerkmale zum Teil nachzubilden. Dazu gehört auch die
Code-Vervollständigung, die aber derzeit noch
als experimental gekennzeichnet ist. Nehmen wir an, Sie
haben ein Objekt
einer bestimmten Klasse definiert und tippen dieses in Ihrem Quelltext
wieder ein, um eine Methode davon aufzurufen. Dazu setzen Sie hinter
den Objektnamen einen . oder einen -> (je nachdem, ob
Referenz oder Zeiger). Schon klappt unterhalb der Eingabezeile ein
kleines Fenster auf, das Ihnen die vorhandenen Methoden dieser Klasse
auflistet (siehe Abbildung
)
- allerdings nur die der Klasse selbst, nicht die einer
Basisklasse. Wenn Sie nun die öffnende Klammer für die Parameter
eingeben, erhalten Sie ein weiteres Hilfefensterchen, das angibt,
welche Parameter diese Methode erwartet.
Auf der ersten Seite legen Sie fest, von welchem Typ Ihr Projekt sein soll.
Die nächste Seite dient der Festlegung von Projekteinstellungen. Neben Projektname, Pfad, Autor etc. können Sie auch wählen, welche zusätzlichen Dateien zu Ihrem Projekt hinzukopiert werden sollen. KDevelop geht davon aus, dass man damit nur GPL-Software entwickelt, und stellt die dafür typischen Dateien wie INSTALL, README, COPYING zur Verfügung. Falls Sie eine Benutzerdokumentation oder eine API-Dokumentation anlegen wollen, können Sie auch dafür Gerüste generieren lassen. Schließlich haben Sie an dieser Stelle noch die Möglichkeit, ein Icon für Ihre Applikation anzugeben.
Falls Sie auf eine
Versionsverwaltung mit CVS (siehe Seite
) verzichten,
können Sie nun sofort auf ERSTELLEN klicken. Anderenfalls
finden Sie auf der nächsten Seite die dafür nötigen Einstellungen vor,
zum Beispiel der Pfad zum
CVSROOT-Verzeichnis.
Der
letzte Schritt ist die eigentliche Erstellung des
Projekts. Hierbei nimmt KDevelop eine Vorlage für den von Ihnen
ausgewählten Projekttyp, kopiert die Dateien zunächst in das
Projektverzeichnis und passt sie anschließend sowohl an Ihre
Einstellungen aus den vorangegangenen Dialogen als auch an
Ihre lokale Hard- und Softwareumgebung (mittels autoconf
beziehungsweise configure)
an. Einen Teil der Ausgabe sehen Sie in Abbildung
Fig:KDevel-AppWizard.
Die ALLGEMEINEN EINSTELLUNGEN sind die einfachsten. Hier finden Sie die Angaben aus der ersten Seite des Anwendungsassistenten wieder, also Programmname, Name und E-Mail-Adresse des Autors, Versionsnummer sowie die Art der eingesetzten Versionsverwaltung.
Etwas kniffliger wird es bei den CONFIGURE-EINSTELLUNGEN. Hier können Sie ein paar der vordefinierten Einstellungen für das Programm configure ändern. Damit ist der autoconf-Mechanismus gemeint: Aus Ihren Angaben und einer automatischen Überprüfung Ihrer Systemumgebung erzeugt dieses Werkzeug die Make-Dateien, mit deren Hilfe KDevelop (beziehungsweise natürlich der GCC) Ihre Anwendung schließlich kompiliert. Zum Glück müssen Sie im Allgemeinen an diesen Einstellungen nichts ändern.
Unter
COMPILER-EINSTELLUNGEN (Abbildung
)
finden Sie einige Angaben vor, die Sie
normalerweise in Form von Compiler-Schaltern beim Aufruf des GCC
übergeben. KDevelop nimmt diese hier in etwas bequemerer Form für Sie
auf und erzeugt daraus dann die Parameter für das Kompilieren. Ganz
praktisch ist die Möglichkeit, einen Satz von Einstellungen komplett
mit einer Bezeichnung zu versehen und so schnell zwischen
verschiedenen Varianten (zum Beispiel für Debug- und
Release-Versionen) hin- und herschalten zu können. Ansonsten bietet
Ihnen dieser Dialog den Zugriff auf die gängigsten Einstellungen an:
Eine Reihe von
Warnungen können Sie ebenso an- und abschalten wie den
Optimierungsgrad oder die Debug-Informationen.
|
Die
LINKER-OPTIONEN legen fest, welche Bibliotheken zu einem Projekt
hinzugebunden werden sollen. Wenn Sie Ihr Projekt mit Hilfe des
Assistenten erzeugt haben, sorgt dieser bereits dafür, dass hier die
notwendigen Bibliotheken für das Grundgerüst
angekreuzt sind. Die weiteren hängen davon
ab, welche aus der Liste Sie tatsächlich verwenden. Wenn Sie eine
Bibliothek einsetzen, die nicht verzeichnet ist, so müssen Sie den dafür
nötigen Linker-Parameter angeben (also zum Beispiel -lxy für die
libxy.a, siehe auch Seite
und Seite
).
Ähnlich
sieht es auch bei den MAKE-OPTIONEN aus. Die Kontrollkästchen
im oberen Teil geben die wichtigsten Schalter an, die bei
make zur Verfügung stehen (siehe auch Seite
), zum Beispiel VORRANG FÜR
UMGEBUNGSVARIABLEN oder NACH FEHLERN FORTFAHREN. Zudem lässt
sich die Zahl der gleichzeitigen Compile-Jobs einstellen, die
ausgeführt werden sollen. Eine weitere Auswahlliste betrifft jedoch
mehr das Verhalten von KDevelop selbst: Sie können bei NEU
ERSTELLEN BEI AUSFÜHREN/DEBUG festlegen, ob die Umgebung Ihr
Programm neu erstellen soll, wenn Sie es ausführen oder im Debugger
starten.
Schließlich finden Sie unter der Rubrik AUSFÜHRBARE DATEI noch die Möglichkeit, einen anderen Namen für die ausführbare Datei, die vom Projekt erzeugt wird, zu vergeben und den Pfad zum libtool zu ändern.
READY lesen, können Sie den Dialog beruhigt über
BEENDEN schließen.
Die Vorgabe ist, dass sich die Funktion main() in einer Datei
namens main.cpp befindet. Bei kleineren Beispielen reicht
diese Datei bereits vollkommen aus. Wenn Sie weitere Dateien
benötigen, können Sie diese über DATEI | NEU erzeugen und auch
gleich dem Projekt hinzufügen.
Der Assistent hat bereits etwas Code in die Datei eingefügt: eine Ausgabe des berühmten Hello World! in der Form
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <iostream.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
cout << ``Hello, World!`` << endl;
return EXIT_SUCCESS;
}
Es genügt, die Zeile mit cout zu entfernen und an deren Stelle
Ihre Befehle einzusetzen. Den Rest können Sie im Allgemeinen
beibehalten, wenn das jeweilige Beispielprogramm nichts anderes sagt.
Mit ERSTELLEN | ERSTELLEN oder der entsprechenden Schaltfläche beziehungsweise der Taste F8 lässt sich Ihr Programm übersetzen. Wenn Sie einen Fehler gemacht haben, den der Compiler moniert, so erscheint diese Meldung im Ausgabefenster unterhalb des Editors. Ein Doppelklick darauf genügt, und Sie landen wieder im Editor an der Stelle, die den Fehler verursacht hat.
Die Anwendung starten Sie mit ERSTELLEN | AUSFÜHREN oder der Taste F9. KDevelop führt eine Konsolenapplikation auch in einer Konsole aus. Es erscheint also ein Terminalfenster, in dem die Ausgaben (oder auch Eingabeaufforderungen) Ihres Programms stehen. Damit dieses Fenster nicht nach Programmende sofort wieder verschwindet, ist eine Pausenfunktion eingebaut. Sie müssen zunächst die Eingabetaste drücken, bevor es sich schließt. (Es kann übrigens sein, dass es KDE dabei allzu gut mit Ihnen meint und bei jedem Start dieser Konsole seinen Tipp des Tages einblendet. Dies stellen Sie ab, in dem Sie das Kästchen BEIM START ANZEIGEN deaktivieren.)
Das Verzeichnis, in dem KDevelop die Quellen Ihrer Anwendung abgelegt hat, ist übrigens gut bevölkert. Der Assistent hat dort eine ganze Reihe von Dateien erzeugt, die alle mehr oder weniger wichtig sind, von denen Sie aber keine wirklich interessieren muss. Sie dienen alle dazu, die Automatismen, die Ihnen KDevelop bietet, zu unterstützen. Die eigentlichen Quellen Ihres Programms finden Sie in einem Unterverzeichnis, das denselben Namen wie das Projektverzeichnis trägt. Auch die ausführbare Datei wird dorthin erzeugt.
KDevelop setzt vollkommen auf offenen Standards auf. Wenn Sie also der
Ansicht sind, dass dieses Werkzeug doch nicht das richtige für Sie
ist, können Sie mit den generierten Dateien auch problemlos außerhalb
von KDevelop weiterarbeiten. Mehr als make (siehe Seite
) brauchen Sie dafür im Allgemeinen nicht.
Um ein Projekt unter die Fittiche von KDevelop zu stellen, gehen Sie folgendermaßen vor:
Fig:KDevel-Addproj).
Mit Hilfe des Ordner-Symbols öffnet sich für die
Kategorie QUELLDATEI(EN) ein Auswahldialog. Wählen Sie dort die
Dateien, die bisher zu Ihrem Projekt gehört haben und die Sie
künftig mit KDevelop bearbeiten möchten; im Allgemeinen sind dies
Header- und Implementierungsdateien sowie eine Make-Datei. Sie
können in diesem Dialog mehrere Dateien auf einmal auswählen, wenn
Sie beim Anklicken die Taste Strg gedrückt halten.
datum/.
Nach diesen Schritten können Sie Ihr Projekt mit KDevelop übersetzen, bei Fehlern an die richtigen Stellen im Quelltext springen und den Debugger verwenden.
Zwei
Aspekte sollten Sie jedoch von vornherein bei den Makefiles der Projekte
beachten, die Sie später mit KDevelop bearbeiten wollen:
all hinzu, das sämtliche Zieldateien
umfasst, mindestens aber die ausführbare Datei.
clean enthalten,
das die Objektdateien und die sonstigen generierten Dateien
löscht. Dieses Ziel verwendet KDevelop, wenn Sie NEU
ERSTELLEN aufrufen.
Außerdem kann es Probleme beim Aufruf des Debuggers geben, der die ausführbare Datei nicht finden kann. In diesem Fall wählen Sie mit dem Menüpunkt DEBUGGEN | START (SONSTIGE) | WEITERE AUSFÜHRBARE DATEI DEBUGGEN die in Ihrem Projekt erzeugte Datei aus. Dann lässt sich der Debugger problemlos starten. Eine andere Möglichkeit ist, in den PROJEKT-OPTIONEN unter AUSFÜHRBARE DATEI den richtigen Dateinamen anzugeben.
Hilfepunkte können Sie übrigens ganz einfach setzen, indem Sie für die jeweilige Zeile einmal auf den linken grauen Rand des Editorfensters klicken. Um sie zu bearbeiten, benutzen Sie das Kontextmenü des jeweiligen Haltepunktes im Ausgabefenster (normalerweise unterhalb des Editors, Karteireiter HALTEPUNKTE). Weitere Debugger-Kommandos können Sie über das Menü DEBUGGEN oder die entsprechenden Schaltflächen in der Werkzeugleiste geben.
Dennoch möchte ich in diesem Abschnitt versuchen, Ihnen den Start in die Welt der KDE-Anwendungen etwas zu erleichtern. Schritt für Schritt werden wir eine kleine Anwendung entwickeln, die Ihnen insbesondere die dafür nötigen Handgriffe mit KDevelop nahe bringen will.
Unpraktisch am BMI ist, dass er sich nicht so leicht im Kopf errechnen
lässt. Daher wollen wir in diesem Abschnitt ein Programm entwickeln,
das nach der Eingabe von Größe und Gewicht den BMI bestimmt und noch
ein paar Aussagen zu Risiken von Übergewicht macht. Letztere sollen
abhängig vom Geschlecht der Person sein, so dass wir auch noch dafür
eine Eingabemöglichkeit vorsehen müssen. Die Oberfläche der Anwendung
soll also ungefähr wie in Abbildung
aussehen.
Die dahinter stehende Logik ist sehr einfach: Nach Eingabe der Daten und einem Klick auf die Schaltfläche AUSWERTUNG STARTEN wird die Plausibilität der Daten geprüft (um unsinnige Ergebnisse bei Eingabefehlern zu vermeiden), der Wert berechnet und anschließend zusammen mit einem Kommentar angezeigt.
Grafische Benutzeroberflächen arbeiten in mancherlei Hinsicht deutlich anders als alle sonstigen Anwendungsprogramme. Bei unseren bisherigen Programmen gab es meistens eine mehr oder weniger klare Linie, die von der Eingabe der Daten über die Verarbeitung bis zur Ausgabe geführt hat. Bei der Benutzeroberfläche gibt es eine solche Linie nicht.
Eine solches Programm muss sich stets dem Willen des Benutzers unterwerfen. Das bedeutet praktisch, dass es so lange warten muss, bis der Benutzer eine bestimmte Aktion macht, und dann darauf prompt zu reagieren hat. Die Reaktion kann dabei sehr unterschiedlicher Art sein. Bei einem Klick auf eine Schaltfläche SCHLIESSEN soll sich beispielsweise ein Fenster schließen, bei der Selektion eines bestimmten Werts in einer Liste sollen nur die Inhalte einiger anderer Elemente aktualisert werden usw. Wir haben es also mit einer ereignisgesteuerten Programmierung zu tun. Das bedeutet, dass bei den Steuerelementen bestimmte Ereignisse eintreten (entweder durch die Interaktion des Benutzers oder intern als Folge eines anderen Ereignisses) und als Reaktion darauf entsprechende Behandlungsroutinen aufgerufen und abgearbeitet werden.
Im Sinne der Objektorientierung - denn in Qt sind alle Steuerelemente echte C++-Objekte - heißt das, dass ein Objekt ein Ereignis signalisiert, wenn es seinen Zustand so geändert hat, dass dies für andere von Interesse sein könnte. Wer auf dieses Ereignis reagiert und was daraufhin getan wird, ist für das Objekt selbst nicht von Bedeutung. Umgekehrt kann eine Behandlungsroutine auch durch verschiedene Arten von Ereignissen ausgelöst werden. Beispielsweise soll ja beim Klick auf ein Symbol der Werkzeugleiste und bei der Auswahl des entsprechenden Menüpunktes jeweils dieselbe Aktion ausgeführt werden.
Solche Ereignisse bezeichnet man in Qt als Signale. Ein Objekt sendet ein Signal aus, wenn sich bei ihm etwas ändert. Wenn sich ein anderes Objekt für dieses Signal angemeldet hat, wird dessen Behandlungsroutine aufgerufen. Gibt es keinen Interessenten, passiert auch nichts. Ein Signal ist eine Methode der Klasse, die auch Parameter haben kann. Zudem kann das aussendende Objekt noch zusätzliche Informationen über das Ereignis mitgeben. Viele Klassen in Qt haben bereits Signale vordefiniert; durch Ableiten können Sie aber jederzeit neue hinzufügen.
Eine
Methode zum Behandeln von Signalen bezeichnet man bei Qt
als Slot.
Ein Slot entspricht in der Signatur dem Ereignis, auf das er reagieren
soll (er darf genau genommen aber auch weniger Parameter haben). Er wird
dann aufgerufen, wenn das Ereignis eintritt, mit dem er verbunden
ist. Natürlich können Sie eine Slot-Methode auch wie jede andere
C++-Methode aufrufen. Meistens wird man solche Methoden als
public slots deklarieren, damit auch die Signale anderer Objekte
damit verbunden werden können. Es ist aber möglich, diese auf
protected slots oder gar private slots
einzuschränken. Jedes Qt-Objekt, das von einem Typ ist, der von
QObject abgeleitet ist (wie das alle grafischen Steuerelemente
sind), kann Signale und Slots beinhalten.
Wie findet nun das Signal seinen Slot? Anders als bei anderen GUI-Bibliotheken setzt Qt hierbei auf eine sehr lose Kopplung. Die Verbindung ist weder Teil des aussendenden noch des empfangenden Objekts, sondern wird separat festgelegt. Dadurch ist es aber sehr bequem möglich, einem Signal verschiedene Slots zuzuordnen oder aber einen Slot zur Behandlung mehrerer Signale zu verwenden. Die Objekte selbst wissen darüber nichts.
Wenn Sie sich jetzt fragen, ob Sie das alles auch so selbst programmieren müssen, kann ich Sie beruhigen. Der Qt-Designer, mit dem wir später die grafischen Elemente entwerfen werden, unterstützt Sie beim Setzen von Slots und beim Zuordnen zu Signalen durch entsprechende Dialoge. Mit ein paar Klicks sind die entsprechenden Verbindungen hergestellt. Der Rest wird automatisch erledigt.
Trotzdem möchte ich Ihnen zur Illustration etwas
vom generierten Code zeigen, damit Sie das Konzept besser
verstehen. Unser Dialog aus Abbildung
beinhaltet ein Objekt namens pbEval vom Typ
QPushButton. Diese Klasse hat keine eigenen Signale definiert;
sie stehen in ihrer Basisklasse QButton. Signale deklariert
man mit Hilfe des speziellen Schlüsselworts signals, Slots mit
public slot usw.
Qt-Klassen beginnt man
zudem im Allgemeinen mit dem Makro Q_OBJECT, das eine Reihe
von Standardmethoden deklariert. Die Klasse QButton sieht
damit etwa wie folgt aus (ich habe allerdings viele Bestandteile
gelöscht, um Ihnen die Übersicht zu erleichtern):
class QButton : public QWidget
{
Q_OBJECT
public:
QButton( QWidget* parent=0,
const char* name=0, WFlags f=0 );
~QButton();
QString text() const;
virtual void setText( const QString &);
signals:
void pressed();
void released();
void clicked();
protected:
virtual void drawButton( QPainter * );
void keyPressEvent( QKeyEvent *);
void keyReleaseEvent( QKeyEvent *);
private slots:
void animateTimeout();
void autoRepeatTimeout();
private:
QString btext;
friend class QButtonGroup;
// ...
};
Das Signal kommt also direkt vom Button; den Slot ordnen wir dem
Formular zu (also der Klasse für das Hauptfenster), da über dieses
die gesamte Interaktion abgewickelt werden soll. Meist ist es
sinnvoll, Slots, die Signale von Steuerelementen auf einem Formular
behandeln sollen, innerhalb der Formularklasse zu definieren. Wir
fügen also mit dem entsprechenden Hilfsmittel des Designers unserem Formular
BmiMainForm einen calcSlot() zur Auswertung der Eingaben
hinzu. Im Code schlägt sich das nieder als:
class BmiMainForm : public QMainWindow
{
Q_OBJECT
public:
BmiMainForm( QWidget* parent = 0,
const char* name = 0,
WFlags fl = WType_TopLevel );
~BmiMainForm();
QGroupBox* GroupBox2;
// Weitere Objekte
public slots:
virtual void calcSlot();
};
Die Verbindung zwischen Signal und Slot wird im Konstruktor des Formulars hergestellt, wo auch alle Steuerelemente angelegt und konfiguriert werden.
BmiMainForm::BmiMainForm( QWidget* parent,
const char* name, WFlags fl )
: QMainWindow( parent, name, fl )
{
// Initialisiere die Steuerelemente
// ...
// Verbinde Signale und Slots
connect( pbEval, SIGNAL( clicked() ),
this, SLOT( calcSlot() ) );
}
Bei
den Qt-spezifischen Schlüsselwörten wie signals
handelt es sich nicht um Spracherweiterungen von C++, sondern nur
um sehr geschickt angelegte Makros. Aus Gründen der Flexibilität und
Portabilität setzt Qt hierbei auf einen zusätzlichen Präprozessor, den
Meta-Object-Compiler
moc.
Dieser MOC wird auf alle Header-Dateien angewendet, die Klassen mit einer
Q_OBJECT-Deklaration enthalten. Er löst die Makros auf und
erzeugt daraus Standard-C++-Code. Die daraus entstandenen Dateien werden
mit den anderen Projektdateien übersetzt und zum Gesamtprogramm
verlinkt. Wenn Sie mit Entwicklungsumgebungen wie KDevelop
arbeiten, bleiben diese Vorgänge weitgehend vor Ihnen verborgen -
alles läuft automatisch ab. Sie merken nur, dass sich am Ende in Ihrem
Quellverzeichnis ein paar mehr C++-Dateien befinden, als Sie selbst
geschrieben haben.
).
Wenn Sie schon mit anderen Werkzeugen wie Visual Basic oder Delphi gearbeitet haben, wird Ihnen das Konzept bekannt vorkommen: eine Werkzeugleiste mit Komponenten, ein Editor für Eigenschaften und Ereignisbehandlungsroutinen sowie Möglichkeiten zur Formatierung und Vorschau.
PushButton1 lassen Sie sehr schnell den Überblick über die
eigentliche Bedeutung der Elemente verlieren.
GroupBoxes und
Ähnlichem. Um Ihnen einen Überblick über die Zugehörigkeiten und
andere Objekteigenschaften zu geben, bietet Qt-Designer den
Object Explorer an. (Sollte dieser nicht von Anfang an
sichtbar sein, können Sie ihn über WINDOW | VIEWS | OBJECT
EXPLORER zum Vorschein bringen.) Ein Objekt, das Sie dort
markieren, ist dann auch im Formular-Designer und im
Eigenschaftseditor ausgewählt.
Um die Oberfläche für ein Programm wie in unserem Beispiel mit KDevelop und dem Qt-Designer zu entwerfen, gehen Sie folgendermaßen vor:
) und
auch gleich einen eigenen Assistenten.
Nun
geht es an die Gestaltung des Formulars. Bevor Sie sich für diese
Aufgabe an den Rechner setzen, sollten Sie bereits eine möglichst
konkrete Vorstellung davon haben, welche Bedienelemente darauf
vorkommen und wie diese zueinander angeordnet werden
sollen. Achten Sie darauf, dass Ihre Dialoge nicht zu überladen sind,
denn dies kann für den Benutzer sehr schnell unübersichtlich und
undurchschaubar werden. Wenn Sie mehr Steuerelemente benötigen, als
auf Ihr Formular passen, verwenden Sie besser ein TabWidget,
mit dem sich zwischen verschiedenen Teil-Formularen blättern lässt.
Für das Fenster aus Abbildung
(Seite
) benötigen wir aber nur einige wenige
grafische Elemente. Ich möchte Ihnen hier nicht jeden Schritt im
Detail erläutern, sondern nur ein paar Eckpunkte geben, anhand derer
Sie ein solches Formular sicher schnell selbst erstellen können -
wenn Sie das möchten. Dabei verwende
ich sprachlich vorwiegend die englischen Ausdrücke für Ihre bessere
Orientierung im Qt-Designer; verzeihen Sie
mir also das etwas zu anglophile Deutsch hier.
sizePolicy Fixed bei einer maximumSize von
360, 385.
hAlign ist AlignRight) und heißen leHeight
beziehungsweise leWeight.
autoDefault als auch default auf true gesetzt.
hAlign steht
auf AlignHCenter und vAlign auf AlignVCenter).
Darunter ist ein Textedit-Feld mit dem Namen
teTextbox, das auf readOnly gesetzt ist; hier soll die
textuelle Auswertung angezeigt werden.
Aufgrund der fixierten Größe des Formulars benötigen wir eigentlich keine Hilfsmittel wie Spacer und Layoutrahmen. Versuchen Sie aber trotzdem schon bei einfachen Formularen wie hier diese Funktionen einzusetzen, damit Sie ein Gefühl für deren Wirkungsweise bekommen. Es handelt sich dabei um sehr effektive Gestaltungsmittel für die flexible Anpassung an Veränderungen der Fenstergröße. Generell sollten Sie dabei zunächst die horizontale Anordnung im Auge behalten, bevor Sie sich um die vertikale kümmern. Am besten ist es, wenn Sie die Wirkung von Spacern und Layout in verschiedenen Varianten mit Hilfe der PREVIEW-Funktion ausprobieren.
Nach Abschluss des Designs
müssen wir noch den Klick auf die AUSWERTUNG
STARTEN-Schaltfläche mit der eigentlichen Auswertung verbinden. Bei
einem Qt-Formular bedeutet das, das Signal clicked mit einem
entsprechenden Slot zu verbinden (siehe auch Seite
). Um eine solche Verbindung zu erstellen,
müssen Sie zunächst in den entsprechenden Modus wechseln, zum Beispiel
mit TOOLS | CONNECT SIGNALS/SLOTS oder einfach mit F3.
Dadurch wird der Mauszeiger zu einem Kreuz. Eine Verbindung stellen
Sie her, indem Sie auf das signalerzeugende Steuerelement (bei uns
der PushButton) klicken und die nun erscheinende Linie zum Widget
ziehen, das den Slot dafür beinhalten soll. Beim Herumfahren mit der
Maus werden Sie sehen, dass Letzteres durch einen violetten Rahmen
markiert wird. Bei Dialog- und Hauptprogrammfenstern definiert man die
Slots für die Reaktionen auf Schaltflächen und Ähnliches im
Allgemeinem in der Formularklasse. Das wollen wir auch hier tun.
Ziehen Sie also die Verbindungslinie über die freie Fläche des
Formulars aus diesem hinaus und lassen Sie die linke Maustaste dann
erst los.
Nun öffnet sich ein Dialog wie in Abbildung
, mit dem Sie die Details dieser Verbindung
festlegen können.
Wir
wollen eines der vordefinierten Signale des Pushbuttons verwenden,
nämlich clicked(). Dieses wird ausgelöst, wenn der Benutzer die
Schaltfläche einmal anklickt. Um aber flexibel zu bleiben, wollen wir
zur Behandlung selbst einen Slot definieren. Wählen Sie dazu zunächst
clicked() als das zu behandelnde Signal aus. Mit einem weiteren
Klick auf EDIT SLOTS öffnen Sie einen zusätzlichen Dialog, der
Ihnen alle definierten Slots der jeweiligen Formular- oder Steuerelementklasse
anzeigt. Im Augenblick ist die Liste noch leer. Mit NEW SLOT
fügen Sie einen neuen Slot hinzu, dem Sie im Eingabefeld SLOT
den Namen calcSlot() geben können (siehe
Abbildung
). Die übrigen Einstellungen
können Sie auf den Vorgabewerten belassen. Wenn Sie nun dieses Fenster
mit OK schließen, erscheint der neue Slot in der Liste oben
rechts im EDIT CONNECTIONS-Dialog.
Nun müssen Sie nur noch zuerst auf clicked() in der linken Liste
und dann auf calcSlot() in der rechten Liste klicken - schon
ist eine Verbindung des Signals mit dem Slot hergestellt und taucht
auch sofort in der Liste der Connections im unteren Bereich des
Fensters auf (wie in Abbildung
).
Damit können wir diesen Dialog schließen und sind mit dem Design unserer GUI fertig. Bei komplexeren Anwendungen werden Sie sicher weitere Steuerelemente haben, mehrere Signale behandeln und umfangreicherere Slots definieren - die Vorgehensweise, die ich Ihnen anhand dieses simplen Beispiels gezeigt habe, bleibt aber die gleiche.
Als Nächstes müssen wir die gerade entworfene Benutzerschnittstelle
mit dem bereits vorhandenen Gerüst unserer Anwendung zusammenbringen.
Fügen Sie zunächst bei den #include-Anweisungen die folgende Zeile ein:
#include "bmidlg.h"
Außerdem ist es erforderlich, dass die Klasse Bmi von BmiMainForm
abgeleitet ist und nicht von QWidget.
class Bmi : public BmiMainForm
Schließlich muss noch die Deklaration für den Slot eingefügt werden,
so dass die ganze Klasse Bmi dann die folgende Form hat:
#include <kapp.h>
#include <qwidget.h>
#include "bmidlg.h"
/** Bmi is the base class of the project */
class Bmi : public BmiMainForm
{
Q_OBJECT
public:
/** construtor */
Bmi(QWidget* parent=0, const char *name=0);
/** destructor */
~Bmi();
public:
virtual void calcSlot();
};
Da unsere Anwendung recht simpel ist, sind wir nun bereits beim letzten Arbeitsschritt
angelangt: der Implementierung von calcSlot(). Hier müssen wir erstmals
von einem Programm aus direkt auf die Steuerelemente auf dem Formular zugreifen,
denn wir wollen die Eingaben des Benutzers verarbeiten und Ausgaben erzeugen.
Dazu ein paar grundlegende Bemerkungen:
BmiMainForm eingegangen. Es ist dort ein Zeiger auf ein Objekt vom Typ
dieses Steuerelements. Beispielsweise ist die Eingabezeile für das Körpergewicht
deklariert als QLineEdit*, also Zeiger auf ein QLineEdit-Objekt,
mit dem Namen leWeight. Wenn Sie also auf seine Attribute und Methoden
zugreifen wollen, nehmen Sie dazu am besten den Pfeiloperator ->.
QLineEdit::text()
ein QString-Objekt zurück. Wenn wir dessen Inhalt in eine Fließkommazahl
umwandeln wollen, wie wir es bei der BMI-Berechnung etwa für das Gewicht benötigen,
müssen wir die Methode
QString::ToFloat()
dieses Objekts aufrufen. Zusammen
sieht das dann so aus:
float weight = (leWeight->text()).toFloat();
Q... beginnen).
Mit diesem Wissen im Hinterkopf ist die Fertigstellung der Implementierung unseres
Beispielprogramms nicht mehr schwierig. Zunächst wandeln wir wie gerade beschrieben
die Eingaben in float-Zahlen um und prüfen deren Plausibilität:
void Bmi::calcSlot()
{
float height = (leHeight->text()).toFloat();
float weight = (leWeight->text()).toFloat();
if (height < 50 || height > 300)
{
QMessageBox, ein Nachrichtenfenster,
darauf hin.
QMessageBox mb("Unzulässiger Wert",
"Bitte geben Sie die Größe in cm an!",
QMessageBox::Warning,
QMessageBox::Ok | QMessageBox::Default,
QMessageBox::NoButton,
QMessageBox::NoButton);
mb.exec();
return;
}
Analog wollen wir ein Gewicht von unter 20 kg und über 1000 kg nicht mehr als gültige Eingabe akzeptieren. Der Programmcode ist dabei fast der gleiche wie oben, so dass ich hier auf einen Abdruck verzichte.
Nun können wir den BMI berechnen und in das dafür vorgesehene Label schreiben.
Dabei leistet die Methode QString::sprintf() gute Dienste, die für die
formatierte Ausgabe dasselbe Format wie die C-Funktion sprintf() akzeptiert.
In diesem Fall wollen wir uns auf eine Nachkommastelle beschränken.
height /= 100;
float bmi = weight/(height*height);
QString s;
s.sprintf("Ihr BMI ist %.1f", bmi);
lBmi->setText(s);
QTextEdit-Feld in Abhängigkeit vom Geschlecht
ausgeben. Die verschachtelten if-Anweisungen sind programmiertechnisch
nicht so interessant, so dass es genügen sollte, wenn ich Ihnen hier die ersten
Zeilen vorstelle:
if (bmi < 18.5)
{
s = "Sie haben Untergewicht.";
}
else
if (bmi < 25)
{
s = "Sie haben Normalgewicht. ";
if (rbMale->isChecked())
s += "Keinerlei Risiko.";
else
{
s += "Keine Gefahr für Diabetes und Herz";
s += "krankheiten, außer bei zu viel Fett.";
}
}
else
// Weitere Fallunterscheidungen
// ...
teTextbox->setText(s);
return;
}
Jetzt
ist es an der Zeit, dass wir unsere Anwendung übersetzen. Dies
sollte eigentlich problemlos möglich sein. Bei der Version 2.1 von KDevelop
zu KDE 3.0, die beide auf Qt 3.0 aufbauen, sind bei mir jedoch einige Schwierigkeiten
aufgetreten, vor denen ich Sie gerne bewahren möchte.
Zunächst sollten Sie sicherstellen, dass Sie für die Kompilierung den GCC 2.95 verwenden. Qt ist noch nicht auf den GCC 3.0 ausgelegt, so dass es Probleme beim Linken der Bibliotheken geben kann.
Daneben scheint es noch ein paar Inkonsistenzen beim Konfigurationsskript zu geben,
das die Make-Dateien für die KDevelop-Projekte erzeugt. Wenn Sie KDE
nicht - wie es offenbar der Vorgabewert ist - im Pfad /usr/local/kde
installieren, sondern an einer anderen Stelle (SuSE legt es beispielsweise unter
/opt/kde3 ab), müssen Sie den prefix-Eintrag in der Make-Datei
ändern. Gehen Sie dazu in KDevelop in die Liste der Dateien, öffnen
Sie den Zweig mit den eigentlichen Quelldateien (im Beispiel ist das bmi/)
und laden Sie das dort enthaltene Makefile in den Editor. Bereits in
der sechsten Zeile wird das Makro prefix definiert; Sie sollten es auf
den Pfad setzen, unter dem KDE 3 in Ihrem Dateisystem zu finden ist, beispielsweise
prefix = /opt/kde3
In file included from bmidlg.cpp:164:
bmidlg.moc:29: syntax error before `('
bmidlg.moc:34: no `void BmiMainForm::initMetaObject()'
member function declared in class `BmiMainForm'
gmake[2]: /usr/lib/qt/bin/moc: Command not found
MOC in der oben genannten
Make-Datei Ihres Projekts entsprechend an, zum Beispiel auf
MOC = /usr/lib/qt3/bin/moc
(Seite
). Wie hoch
ist Ihr eigener BMI? Liegt er über 25, sollten Sie vielleicht dieses
Buch mal für eine Stunde weglegen und statt zu lesen (oder
programmieren) lieber joggen gehen ...
Sie sollten aber auf jeden Fall anhand dieses Beispiels die grundsätzliche Vorgehensweise beim Erstellen einer KDE/Qt-Anwendung mit KDevelop erkannt haben. Wenn Ihnen dann der Umgang mit der IDE keine Probleme mehr bereitet, können Sie sich voll und ganz auf die Entwicklung von Dialogen und komplexeren Applikationen mit den verschiedensten Qt-Objekten konzentrieren. Mit weiteren Büchern wie [] oder [] können Sie bei Interesse und Bedarf noch viel über Qt erfahren.
Alles in allem ist KDevelop eine umfangreiche und stabile Entwicklungsumgebung, die fast alles liefert, was man als Programmierer benötigt. Sie ist damit sowohl für den Anfänger als auch für den Profi sehr empfehlenswert. Da die Entwicklung daran aber immer noch mit Nachdruck weitergeht, werden wir sicher noch viele interessante neue Funktionselemente im Lauf der Zeit zu sehen bekommen.
Eine integrierte Entwicklungsumgebung mit vielerlei Vorzügen, ist SNiFF+ von Windriver (vormals von TakeFive). Sie hat eine gute Teamunterstützung, ist für vielerlei Plattformen und eine Reihe von Programmiersprachen (C/C++, Java, Fortran, Cobol, Python, Perl etc.) verfügbar und kann auch wirklich große Projekte effizient verwalten. Der einzige Nachteil war lange Zeit der relativ hohe Preis. Doch da gab es eine gute Nachricht - wenigstens für eine Zeit lang. Die Penguin Edition der Version 3.2, die die C++-Entwicklung unter Linux unterstützt, war kostenfrei erhältlich. Mittlerweile sah Windriver dadurch aber das Geschäft mit der kommerziellen Version beeinträchtigt und hat diese freie Version vom Markt genommen. SNiFF+ 4.x gibt es nur noch als kostenpflichtiges Paket.
Vielleicht haben Sie aber Glück und bei Ihrer Linux-Distribution befindet sich noch ein SNiFF-Pinguin. Wenn nicht, finden Sie alles Nötige auf beiliegender CD-ROM, da WindRiver dem dpunkt.verlag für dieses Buch die entsprechenden Rechte gewährt hat.
Projekte sind in SNiFF+ hierarchisch organisiert. Das bedeutet, dass jedes Projekt ein oder mehrere Unterprojekte haben kann, von denen es abhängt. Auch diese können wieder eigene Unterprojekte haben und so weiter. Dabei können Sie frei einstellen, welches Ergebnis ein Unterprojekt nach oben liefern soll: seine Objektdateien, eine Bibliothek oder eine eigene ausführbare Datei. SNiFF+ legt fest, dass ein Projekt denselben Namen tragen muss wie das Verzeichnis, in dem es sich befindet. Das ist im Allgemeinen keine Einschränkung, sondern fördert die Einfachheit und Übersichtlichkeit eines Projekts. Zusätzlich müssen alle verschiedenen Projekte in einer Hierarchie auch verschiedene Namen tragen (obwohl sie für das Dateisystem und den Compiler eigentlich durch ihren Pfad eindeutig bestimmt sind). Findet SNiFF+ beim Analysieren eines bestehenden Projekts ein solches Unterverzeichnis zum wiederholten Mal, so wird der Projektname aus dem Verzeichnisnamen des darüber liegenden Ordners und des aktuellen zusammengesetzt. In net/src und img/src werden beispielsweise net_src.proj und img_src.proj angelegt.
Als Beispiel betrachte ich in diesem Abschnitt vorwiegend die freie Bibliothek Qt, da unsere bisherigen Beispiele doch recht klein waren und die Funktionalität von SNiFF+ daher nicht so gut veranschaulichen konnten. Qt ist eine vorbildlich aufgebaute C++-Bibliothek, die vor allem als Basis für die Benutzeroberfläche KDE große Verbreitung erreicht hat. Die aktuelle Version erhalten Sie unter www.troll.no. Die über 420 Klassen in mehr als 800 Dateien sind mit einfachen Werkzeugen nur äußerst schwer zu überblicken.
Abbildung
zeigt etwa den Projekteditor beim Browsen
durch die Bibliothek. Im unteren Teil wird die Hierarchie der Projekte deutlich.
Wie Sie hieran sehen, ist SNiFF+ auch gut geeignet, um bestehende Programme
und Bibliotheken zu analysieren. Sie geben nur das oberste Verzeichnis an, unter
dem der Code der Software steht, und alles andere wird automatisch ermittelt.
|
Der etwas merkwürdige Name dieser Software kommt vom englischen Wort sniff, also schnüffeln. Als eine ihrer Hauptaufgaben versteht sie nämlich das selbstständige Analysieren von Quellcode. Dazu beinhaltet SNiFF+ eine Reihe von Werkzeugen, die ich kurz vorstellen will.
Das Besondere an SNiFF+ ist, dass es die für die Programmentwicklung grundlegenden Werkzeuge wie Compiler oder Debugger nicht selbst enthält, sondern lediglich die vorhandenen aufruft. Unter Linux ist das als Compiler standardmäßig der GCC; aber auch andere Compiler (mit ähnlichen Optionen) lassen sich benutzen. Überhaupt ist SNiFF+ im Hinblick auf die Integration von anderen Werkzeugen sehr vielseitig. Fast jedes Werkzeug lässt sich in die IDE integrieren. Sie können eigene Menüpunkte hinzufügen und komplette Abläufe umstellen. Die Programmierschnittstelle in Python macht SNiFF+ besonders offen; diese Schnittstelle wird auch intern benutzt, wobei die entsprechenden Skripte im Quelltext mitgeliefert werden und daher ebenfalls angepasst werden können - falls Sie das wollen.
Wenn Sie den Symbolbrowser aufrufen,
erhalten Sie eine alphabetisch geordnete Liste aller
Bezeichner, die im gesamten Projekt vorkommen. Durch Farben und Kürzel in der
ersten Spalte werden die verschiedenen Arten unterschieden; so ist beispielsweise
mit cl eine Klasse und mit mi eine inline implementierte
Methode gemeint. Durch einen Doppelklick auf den Begriff wird der Editor an
dessen Definitionsstelle geöffnet. Sie verwenden den Symbolbrowser vorwiegend,
um einen bestimmten Bezeichner, vom dem Sie nur den Namen wissen, schnell aufzufinden.
Ähnlich wie der Symbolbrowser dient der Klassenbrowser dazu, alle Elemente aufzulisten - dieses Mal alle, die zu einer Klasse gehören. Es gibt wie immer verschiedene Wege, diesen Browser zu starten; sie gelangen zum Beispiel dahin, wenn Sie im Symbolbrowser eine Klasse auswählen und dann den Menüpunkt CLASS | BROWSER <Klassenname> aufrufen.
Im Klassenbrowser sehen Sie alle Bestandteile, die eine Klasse enthält; neben
Datenelementen und Methoden können dies auch weitere Klassen oder Strukturen,
friend-Elemente oder Konstanten sein. Auch hier können Sie wieder die
Anzeige auf bestimmte Elemente wie Methoden oder Konstruktoren einschränken.
Zudem können Sie im unteren Fensterbereich entscheiden, ob Sie auch die ererbten
Elemente aus den Basisklassen sehen möchten oder nicht.
Zu jedem Analysewerkzeug für objektorientierten Code gehört auch eine Anzeigemöglichkeit
für Klassenhierarchien.
Der in SNiFF+ integrierte Hierarchiebrowser
bietet wieder einiges mehr. Neben der vollständigen Klassenhierarchie
haben Sie auch die Möglichkeit, sich nur die Nachbarn einer Klasse anzeigen
zu lassen, also die Basisklassen und die davon unmittelbar oder mittelbar abgeleiteten
Klassen. Sie erreichen diesen Browser, indem Sie in einem der genannten Werkzeuge
oder im Editor eine Klasse auswählen und entweder im Kontextmenü oder im CLASS-Menü
einen der beiden folgenden Punkte wählen:
SHOW <Klasse> IN ENTIRE HIERARCHY oder
SHOW <Klasse> RELATIVES.
Beim ersten Befehl erfahren Sie die Position dieser Klasse innerhalb der gesamten
Hierarchie aller Klassen, mit dem zweiten sehen Sie nur die Vorfahren und Nachkommen.
Beides kann zu verschiedenen Zwecken nützlich sein. Abbildung
zeigt die gesamte Hierarchie.
|
Ein weiteres hilfreiches Werkzeug dient der Anzeige der Abhängigkeiten zwischen Header-Dateien. Denn wenn eine Datei eine andere, diese wieder eine dritte usw. einbindet, geht die Übersicht, was in die Übersetzung eigentlich alles einfließt und was dazu nötig ist, schnell verloren. Dieser Browser ist fast genauso aufgebaut wie der für Klassenhierarchien. Sie erreichen ihn unter anderem aus dem Editor, wenn Sie einen der Menüpunkte INFO | <Dateiname> INCLUDES oder INFO | <Dateiname> IS INCLUDED-BY wählen. Im ersten Fall sehen Sie alle Header-Dateien, die diese Datei selbst einbindet, im zweiten Fall Dateien, von denen die aktuelle Datei eingebunden wird. Wollen Sie die Abhängigkeiten einer bestimmten Datei verfolgen, klicken Sie diese in der Grafik an und wählen entweder INCLUDES oder IS INCLUDED-BY aus ihrem Kontextmenü.
Die Kerntätigkeiten beim Programmieren sind Schreiben des Programms, Kompilieren und Debuggen - und das im Zyklus. Eine integrierte Entwicklungsumgebung muss also zuvorderst diese Abläufe unterstützen.
Der Editor von SNiFF+ ist sehr bequem zu bedienen, wenn auch am Anfang etwas
gewöhnungbedürftig. Auf der rechten Seiten finden Sie ein eingebettetes Fenster,
das alle Symbole dieser Datei enthält, also Klassen, Methoden und so weiter.
Der Auswahlknopf darüber schränkt die Anzeige auf bestimmte Klassen ein. Die
Symbole sind - wie auch schon in den anderen Browsern - durch verschiedene
Textfarben voneinander abgehoben, beispielsweise Klassen grün, normale Methoden
dunkelrot, inline-Methoden hellrot und Funktionen schwarz.
Viel Funktionalität ist hier über das Menü verfügbar, fast noch mehr über die jeweiligen Kontextmenüs. So können Sie beispielsweise aus der Liste der Bezeichner durch den entsprechenden Befehl sehr leicht zwischen Deklaration und Implementierung von Klassen und Methoden hin- und herspringen.
Achtung:
Die im Kontextmenü des Editors angebotenen Funktionen, zu
einem beliebigen Bezeichner alle Stellen zu ermitteln, auf die sich dieser Bezeichner
bezieht (zum Beispiel QTEXTBOX REFERS-TO), oder alle, wo er selbst
verwendet wird (etwa QTEXTBOX IS REFERRED BY), ist in der freien Penguin-Edition
von SNiFF+ nicht verfügbar. Dazu bedarf es dann doch der kommerziellen Variante.
Anfangs ungewohnt ist der Umgang mit mehreren Dateien. Anders als in den meisten Editoren (beispielsweise auch im XEmacs) ist in SNiFF+ keine Liste aller gerade offenen Dateien verfügbar. Dafür bietet das Menü HISTORY eine Liste aller zuletzt angesprungenen Codestellen, wie in einem Web-Browser. Entsprechend kommen Sie auch mit der ZURÜCK-Schaltfläche an die von Ihnen zuletzt bearbeitete beziehungsweise angesprungene Stelle; diese kann in der gleichen Datei wie Ihre aktuelle Position liegen oder in einer anderen.
Die Syntaxeinfärbung unterscheidet nach Kommentaren, Funktions- und Methodennamen, Präprozessor-Anweisungen und anderem. Sie wird nicht unmittelbar beim Tippen aktualisiert, sondern erst beim Abspeichern. Dafür ist der verwendete Parser sehr flexibel und kann auch mit unvollständigem und inkorrektem Code umgehen. Die Syntaxeinfärbung arbeitet übrigens nur für Dateien, die zum Projekt (oder einem seiner Unterprojekte) gehören. Wenn Sie eine andere C++-Datei über FILE | OPEN laden, erscheint dieses schwarz-weiß.
Die wichtigste Aktion beim Tippen ist meist das Abspeichern. Wenn Sie dafür nicht extra die Hände von der Tastatur nehmen wollen, um die Maus zu bedienen, können Sie auch mit Alt+s oder - wie beim XEmacs - mit Strg+x, Strg+s die aktuelle Datei speichern.
Andere Aktionen lassen sich mit Tastenkombinationen erledigen, die eher von Windows
vertraut sind: Alt+x oder
+Entf zum
Ausschneiden und Alt+c oder Strg+Einfg
zum Kopieren; weiterhin
Alt+v oder auch
+Einfg zum Einfügen, Alt+z
für Rückgängig. Mit etwas Übung gehen auch diese leicht von der Hand.
Auch der Zugang zum Konfigurationsmanagement ist in den Editor integriert. Wollen Sie eine Datei, die noch eingecheckt ist, bearbeiten, weist Sie SNiFF+ darauf hin und erledigt das Auschecken. Manuell können Sie diese Dienste auch über das FILE-Menü erreichen (CHECK IN, CHECK OUT, LOCK, UNLOCK). Möchten Sie zu einer Datei allerdings die komplette Versionsgeschichte sehen, müssen Sie den Projekteditor verwenden. Wählen Sie die Datei im mittleren Feld aus und klicken Sie dann auf das Kontrollkästchen HISTORY am unteren Rand; es erscheint ein zusätzliches Fenster, in dem Sie die Liste der Revisionen erkennen können.
Das Erzeugen von Programmen lässt sich in SNiFF+ von vielerlei Orten aus aufrufen. Meist verwenden Sie dazu das Menü TARGET, aus dem Sie dann entweder RECURSIVELY MAKE PROJECT oder MAKE | ALL aufrufen. Wenn ein solcher Punkt vorhanden ist, geht auch MAKE MAIN TARGET.
Daraufhin öffnet sich ein neues Fenster, die Local Shell. In Abbildung
sehen diese für unser Sender/Receiver-Projekt von Seite
.
|
Die Local Shell ist eine ganz normale Shell, in der Sie auch selbst alle üblichen Befehle eingeben können. (Der Name Local Shell rührt daher, dass SNiFF+ in der größeren Version auch die verteilte Entwicklung über remote shells unterstützt.) Die Shell übernimmt zudem die Voreinstellungen des jeweiligen Benutzers; wenn Sie also üblicherweise die C-Shell verwenden, wird diese auch hier gestartet und Ihre persönlichen Einstellungen aus .cshrc werden geladen.
Ein Unterschied besteht bei der Arbeit mit der Zwischenablage. Um etwas aus diesem Fenster zu kopieren, müssen Sie es erst markieren und dann zusätzlich über EDIT | COPY oder über das Kontextmenü in die Zwischenablage bringen.
Tritt ein Fehler beim Generieren auf, klicken Sie darauf und wählen dann aus dem Kontextmenü SHOW ERROR. (Ein einfacher Doppelklick oder Ähnliches genügt leider nicht.) SNiFF+ öffnet nun die entsprechende Datei im Editor und zeigt die fehlerbehaftete Zeile an.
Für besondere Aufgaben gibt es noch den Target-Dialog, den Sie über TARGET | TARGET DIALOG öffnen können. In ihm lassen sich die Ziele separat auswählen und gezielt durch einen Klick auf MAKE erzeugen. Wenn Sie MAKE WITH DEBUG aktivieren, gibt Ihnen SNiFF+ zudem etwas mehr interne Informationen über seinen Make-Prozess aus, so dass Sie Probleme damit leichter lokalisieren können.
Neben dem Generieren ist auch das Debuggen direkt aus der IDE möglich. Mit TARGET | RUN <Dateiname> können Sie das Programm in der lokalen Shell ausführen. Vor jedem Start erscheint noch ein kleines Fenster, in dem Sie mögliche Argumente für die Kommandozeile eintragen können.
Befürchten Sie Probleme in Ihrem Programm, können Sie mit TARGET | DEBUG <Dateiname>
den Debugger starten. Standardmäßig verwendet SNiFF+ unter Linux den gdb
(siehe Seite
, auch
zu den Begriffen und Konzepten des Debuggings). Im Debugger-Dialog (Abbildung
) erhalten Sie den Zugriff auf die gdb-Kommandozeile.
Allerdings können Sie die meisten Befehle auch über Menüs und Buttons erreichen.
Sobald Sie den Debugger aktivieren, erscheint im Editor eine zusätzliche Leiste mit Schaltflächen, über die Sie den Programmablauf steuern können. Neben RUN und CONT sind dies auch STEP, NEXT und BREAK AT (Letzteres zum Setzen eines Haltepunktes). Während des Ablaufs können Sie Ausgaben über Inhalte von Variablen über das Menü DEBUG erreichen. Die PRINT- und DISPLAY-Befehle beziehen sich dabei stets auf die aktuelle Markierung. Über die Schaltfläche Stack erfahren Sie den aktuellen Aufrufstack. Alle Ausgaben erscheinen dabei im Debugger-Dialog. Dort können Sie auch noch weitere Informationen beziehen.
Sie beenden den Debugger, indem Sie dessen Dialog schließen oder den Menüpunkt DEBUG | END DEBUG SESSION wählen.
Sie können auch den DDD unter SNiFF+ verwenden
(siehe Seite
). Im Installationsverzeichnis gibt es einen Unterordner
integrations/ddd, der die notwendigen Dateien sowie eine ausführliche
Erläuterung enthält. (Diese ist unglücklicherweise im Format Microsoft Word.)
Damit können Sie auch die grafischen Elemente des DDD von SNiFF+
aus einsetzen.
In diesem Abschnitt haben Sie einen ersten Überblick über die integrierte Entwicklungsumgebung SNiFF+ bekommen. Wir haben uns dabei eine ganze Reihe von Funktionsmerkmalen angesehen:
Ein Defizit von SNiFF+ bleibt die Onlinehilfe; sie ist (trotz der verschiedentlichen HELP-Schaltflächen) keineswegs kontextsensitiv und besteht vorwiegend aus einer HTML-Version der gedruckten Handbücher. Ein Index fehlt fast völlig, eine Stichwortsuche müsste man sich mit Werkzeugen wie htDig selbst erzeugen.
Es ist schade, dass Windriver die Programmierer, die nicht einfach mal mehrere Tausend Euro für eine IDE ausgeben können, nicht mehr unterstützt. Dadurch könnte SNiFF+ wieder in die Nische zurückfallen, in der es schon einmal war. Andere IDEs wie KDevelop können sich dadurch nur umso schneller und einfacher durchsetzen.
Auch wenn die traditionellen Programmierwerkzeuge unter Unix aus Editor, Make und Kommandozeilencompiler bestehen, sind KDevelop und SNiFF+ keineswegs die einzigen kompletten IDEs, die es unter Linux gibt. In diesem Abschnitt will ich Ihnen drei weitere vorstellen, die zumeist ähnliche Ansätze verfolgen und daher ebenso leicht erlernbar sind. Es sind dies:
)
Der Source Navigator bietet einen Großteil der Funktionalität von SNiFF+, ist allerdings etwas weniger bunt. Sie können ihn direkt bei Red Hat herunterladen (sources.redhat.com/sourcenav/) - oder von beiliegender CD-ROM installieren.
Die Arbeit damit findet vorwiegend in zwei Fenstern statt: Das erste ist ein Symbolbrowser, in dem wahlweise alle Dateien, Klassen, Funktionen oder Methoden des Projekts angezeigt werden können. Auch ein Filter steht zur Verfügung und die Elemente könen nach verschiedenen Kriterien sortiert werden. Wenn Sie darin eine Klasse auswählen, können Sie über einen Klick auf die entsprechende Schaltfläche der Werkzeugleiste zum Klassenbrowser, zum Hierarchiebrowser oder zum Include-Browser gelangen.
Das
zweite ist eine Kombination aus Editor und verschiedenen Browsern (Abbildung
). Durch Reiter über dem Eingabebereich können Sie von einer
Darstellung leicht zu einer anderen gelangen.
Zur Organisation der Projekte bietet der Source Navigator zudem einen eigenen Projekteditor, in dem sich die Abhängigkeiten in Baum-Ansicht darstellen und organisieren lassen. So wird schnell ersichtlich, welche Datei zu welchem Projekt gehört und wo Projekte ineinander greifen. Ein schönes Merkmal ist die Statistik. Durch einen Klick auf diese Schaltfläche erfahren Sie, wie viele Dateien, Klassen, Funktionen, Methoden usw. ein Projekt enthält.
Die Generierung findet hier in einem eigenen Dialog statt, der ähnlich wie beim XEmacs nur die Ausgaben von Make sammelt und keine Eingaben auf Shell-Ebene erlaubt. Bei Fehlern kann zurück zum Code gesprungen werden. Als Debugger ist standardmäßig der gdb integriert.
CodeWarrior von Metrowerks kam als Erstes für den Apple Macintosh auf den Markt und war lange Zeit die wichtigste IDE auf dieser Plattform. Mittlerweile gibt es auch Portierungen für andere Betriebssysteme, seit einiger Zeit auch für Linux (siehe www.metrowerks.com/desktop/linux/). Das Programm nicht allerdings kostenlos, sondern muss käuflich erworben werden!
Die Bedienparadigmen des Mac sind noch an ein paar Stellen des CodeWarrior offensichtlich. So erhalten Sie unmittelbar nach dem Start kein vollständiges Fenster, sondern lediglich ein Fensterchen, das nur aus einer Menüleiste besteht. Über diese lassen sich dann alle weiteren Kommandos aufrufen.
Wenn Sie über FILE | NEW PROJECT ein neues Projekt öffnen, haben Sie neben einem völlig leeren Projekt auch die Möglichkeit, über eine Vorlage schon ein (meist sehr einfaches) Gerüst erzeugen zu lassen.
Vorbildlich sind die Projekteinstellungen (Abbildung
):
Für jeden Dateityp lässt sich (prinzipiell) ein eigenes Übersetzungswerkzeug
definieren. Leider steht in dieser Version nur der GCC zur Verfügung. Auch Compiler-Optionen
und Pfade lassen sich damit sehr einfach setzen.
Oftmals hat die IDE aber das Problem, dass ihre Schrift auf einem Bildschirm höherer Auflösung sehr klein wirkt. Neben den Einstellungen sind auch der Projekteditor und der Klassenbrowser davon betroffen.
An höheren Werkzeugen verfügt der CodeWarrior über einen Hierarchiebrowser, einen Klassenbrowser und einen Symbolbrowser. Die Abhängigkeiten der Header-Dateien werden über eine kleine Schaltfläche im Projekteditor sichtbar gemacht.
Die Übersetzung erfolgt in der Shell, aus der man die IDE (übrigens mittels cwide)
gestartet hat. Die Ausgaben laufen dann allerdings wieder in ein eigenes ERROR
& WARNINGS-Fenster. Selbst Sonderfunktionen des GCC wie separater Syntaxcheck
oder alleiniges Preprocessing sind aus der IDE aufrufbar.
Der Editor erfüllt alle Anforderungen, die man beim Programmieren braucht, hat eine vernünftige Syntaxeinfärbung und erlaubt leichtes Navigieren. Unterstützt wird dieses besonders durch Lesezeichen, die man im Code anbringen kann. Auch der Sprung zwischen den Funktionen und Methoden wird durch ausklappbare Listen erleichtert. Eine Anbindung an die Versionsverwaltung gibt es ebenso. Wer darauf verzichten möchte, darf auch hier einen externen Editor verwenden.
Die Debugger-Anbindung glänzt durch eine ganze Reihe von Ausgabefenstern, etwa für Prozesse, Ausdrücke, globale Variablen oder Haltepunkte. Andererseits ist auch die Einbindung eines externen Debuggers wie des DDD ohne weiteres möglich.
Insgesamt unterscheidet sich der CodeWarrior in seinem Funktionsumfang nicht grundsätzlich vom Source Navigator oder von SNiFF+. Da er im Gegensatz zu den beiden anderen aber nicht kostenlos angeboten wird, ist er wohl eher für Entwickler geeignet, die damit schon einige Erfahrung haben und beim Plattformwechsel ihr Werkzeug weiterverwenden wollen.
Die neueste und viel beachtete integrierte Entwicklungsumgebung unter Linux ist Eclipse. Es handelt sich dabei um ein Produkt der ehemaligen Visual Age-Familie von IBM, das die Firma im November 2001 als Open Source freigegeben hat. Seitdem wird Eclipse von einer über 1200 Entwickler starken Community, zu der auch namhafte Firmen wie Merant, QSSL, Rational, Red Hat und TogetherSoft gehören, mit großem Nachdruck weiterentwickelt. Ausführliche Informationen und die neuesten Releases erhalten Sie von der Projekt-Website www.eclipse.org.
Eclipse möchte daher nicht einfach ein weiteres Tool sein, sondern eine universelle Plattform, über die die verschiedenen Werkzeuge benutzt werden können. Es handelt sich bei Eclipse also mehr um eine generische IDE, in die durch einen Plug-in-Mechanismus viele andere Werkzeuge eingebunden werden können, darunter auch eine IDE zur C++-Programmierung. Als Benutzer sollten Sie kaum merken, wie die verschiedenen Tools ineinander greifen (siehe dazu auch []).
Als echtes Open-Source-Projekt (unter einer Apache-ähnlichen Lizenz) verfügt Eclipse über völlig offene Schnittstellen, die es jedem ermöglichen, eigene Beiträge für die Plattform zu schaffen. Und wie bei vielen anderen Open-Source-Projekten dauert es auch etwas, bis ein Reifegrad erreicht ist, der einen tatsächlichen Einsatz in der Praxis möglich macht. Für die C++-Entwicklung war dies nach meiner Erfahrung zum augenblicklichen Zeitpunkt (April 2002) noch nicht der Fall. Generell machte Eclipse unter Windows einen deutlich stabileren Eindruck als unter Linux. Da sich die Situation aufgrund der großen Beteiligung an diesem Projekt jedoch bald ändern kann, möchte ich Ihnen die Grundzüge des aktuellen Eclipse schon einmal vorstellen. Es lohnt sich sicherlich, ab und zu einen Blick auf dieses Projekt zu werfen.
Die Eclipse-Plattform setzt sich aus folgenden Bestandteilen zusammen:
Die gesamte grafische Oberfläche von Eclipse ist mit Hilfe von SWT programmiert. Es handelt sich dabei um eine Bibliothek von grafischen Komponenten (den so genannten widgets, was für window gadgets, also Fensterelemente steht). Sie ist selbst in betriebssystemabhängiger Form entwickelt, das heißt, sie nutzt die Möglichkeiten des jeweiligen Fenstersystems (Windows, Motif etc.), bietet aber eine unabhängige Programmierschnittstelle (API) an. Entwickler können damit Benutzerschnittstellen schreiben, die genauso unter Linux wie unter Windows und anderen Betriebssystemen laufen. Anders als etwa das AWT-Toolkit von Java versucht SWT, eine große Vielfalt von Steuerelementen zur Verfügung zu stellen, wobei im Allgemeinen die Controls des jeweiligen Fenstersystems genutzt werden; ist ein solches jedoch nicht vorhanden, bietet SWT eine Emulation.
Um die Programmierung von GUIs unter Java noch weiter zu vereinfachen, bildet JFace noch eine Abstraktionsschicht über SWT. JFace enthält Komponenten für die Auswahl von Bildern und Zeichensätzen, Baukästen für Dialoge und Assistenten sowie Fortschrittanzeigen. Darüber hinaus stellt es Möglichkeiten für die Gestaltung interaktiver Betrachter (Viewer) zur Verfügung.
Die Installation von Eclipse ist sehr einfach. Sie müssen lediglich das
heruntergeladene Archiv in ein Verzeichnis auspacken (zum Beispiel
nach /opt/eclipse) und Ihre path-Variable darauf
setzen. Die Unterstützung für C++ befindet sich in einem separaten
Plug-in, das Sie ebenfalls herunterladen und auspacken müssen. Es
kommt in das Unterverzeichnis plugins, also etwa
% unzip cdt-eclipse.zip -d /opt/eclipse/plugins
Eclipse geht davon aus, dass Sie in dem Verzeichnis arbeiten wollen, von dem Sie es aufrufen. Wechseln Sie also vor dem Start dorthin oder geben Sie das Arbeitsverzeichnis mit an, wenn Sie einen Link für diese Anwendung auf dem Desktop oder im KDE/GNOME-Menü anlegen. Bei meinen Tests mit Beta-Releases der Version 2.0 im Frühjahr 2002 erschien bei Aufruf des Programms nur das Projektlogo - danach passierte nichts mehr. Da half nur noch der direkte Start der Java-Applikation, entweder über
% java -classpath /opt/eclipse/startup.jar \
org.eclipse.core.launcher.Main -ws motif
oder gar als
% jdb -classpath /opt/eclipse/startup.jar \
org.eclipse.core.launcher.Main -ws motif
Nach dem Start fällt als Erstes die Aufteilung des Hauptfensters in verschiedene Teilbereiche auf. Es repräsentiert die verschiedenen Werkzeuge, die zum Startzeitpunkt geladen sind. Meist sichtbar ist der Navigator, eine Art Projektmanager, der die im Arbeitsverzeichnis vorhandenen Projekte und Unterprojekte sowie die zugehörigen Dateien anzeigt.
Wenn Sie ein neues Projekt anlegen möchten, verwenden Sie dazu den Projektassistenten, den Sie mit FILE | NEW | PROJECT erreichen. Wenn Sie das C++-Development-Toolkit installiert haben, finden Sie in der Auswahlliste auf der linken Seite auch C/C++, das Ihnen nach Anklicken rechts die Möglichkeit gibt, C/C++ Project auszuwählen. Im nächsten Dialog können Sie nun einen Namen für das Projekt festlegen und bestimmen, ob es sich in einem lokalen Verzeichnis oder auf einem anderen Rechner befinden soll. Mit FINISH schließen Sie das Anlegen des neuen Projektes ab.
Nun hat sich das Navigator-Werkzeug verändert. Es hat noch einen Reiter C/C++ PROJECTS am unteren Rand hinzubekommen; in diesem Modus erscheinen nur die C/C++-Projekte, alle anderen sind ausgeblendet.
Wenn Sie schon ein bestehendes klassisches C++-Projekt - mit Dateien und einem Makefile - haben, können Sie es mit FILE | IMPORT auch zu Ihrem gerade angelegten Eclipse-Projekt hinzufügen. Nach der Auswahl eines Verzeichnisses haben Sie sogar die Möglichkeit anzugeben, welche Dateien in diesem Verzeichnis übernommen werden sollen und welche nicht.
Wenn Sie nun noch bei diesem Projekt im Navigator PARSE | BEGIN PARSE aus dem Kontextmenü wählen, durchkämmt Eclipse Ihren Code nach allen Arten von Deklarationen und listet diese im Project Objects-Werkzeug auf. Hier können Sie nun eine Methode oder eine Klasse auswählen und durch einen Doppelklick deren Deklaration beziehungsweise Implementierung im Editor öffnen.
Ein Vorteil von Eclipse ist sicherlich, dass Sie nicht mühsam selbst Makefiles schreiben müssen, sondern dass diese Aufgabe von der IDE übernommen wird. Eclipse arbeitet hierbei mit autoconf, einem Werkzeug, das Ihnen die Projektkonfiguration und das Erzeugen von Makefiles noch weiter vereinfachen will. Zum Bauen eines Programms wird aber das übliche make verwendet.
Im Zentrum jeder IDE steht jedoch der Editor. Syntaxeinfärbung beherrscht der Eclipse-Editor für C++ recht gut. Interessant sind auch die Möglichkeiten zur automatischen Codeformatierung, die jedoch für Java schon weiter entwickelt sind als für C++. Auch sonst stellt der Editor mit Rechteckauswahl, Vergleichen, Aufzeichnung von Tastenanschlägen und Ähnlichem ein bemerkenswert breites Spektrum von Funktionsmerkmalen zur Verfügung. An Visual Studio orientiert sich etwa die Möglichkeit, die Anzeige des Codes gefiltert darzustellen (FILTER VIEW im Kontextmenü).
Interessant sind auch die so genannten Perspektiven. Diese kleinen Symbole am linken Rand stellen verschiedene Sichten auf die IDE dar, wobei die Werkzeuge jeweils in unterschiedlichen Größen und Anzeigeformen auftauchen. Auf diese Weise können Sie je nach dem Arbeitsschritt, an dem Sie gerade sind, die für Sie angenehmste Kombination an Werkzeugen definieren. Über die Punkte im Menü PERSPECTIVE können Sie die Perspektiven relativ frei konfigurieren.
Wie auch schon SNiFF+ ist Eclipse lediglich eine IDE, die auf den vorhandenen Programmen aufsetzt, und beispielsweise den GCC zum Kompilieren und den gdb fürs Debuggen verwendet. Sie starten das Übersetzen mittels WORKBENCH | REBUILD ALL und kontrollieren das Starten und die Fehlersuche (in Ihrem Programm, nicht in Eclipse ...) über das DEBUG-Menü.
Eclipse wird in Java entwickelt und dementsprechend ist die Unterstützung für Java auch die am weitesten fortgeschrittene. Daher gibt es dort schon eine interessante Funktion, die bei C++ noch nicht vorhanden ist: das Refactoring. Damit meint man das Umstrukturieren und Umgestalten von Code, wenn er nicht mehr den Erfordernissen entspricht oder zusätzliche Funktionalität erfüllen soll (siehe []). Mit den Refactoring-Funktionen in Eclipse können Sie - wie gesagt zunächst nur bei Java - Namen von Attributen, Methoden und Klassen verändern, Klassen in der Hierarchie verschieben und neue Klassen zwischen alte einfügen. Die notwendigen Änderungen werden dann automatisch im gesamten Projektcode nachgezogen. Auf diese Weise haben Sie immer einen konsistenten Code, auch wenn Sie Ihr Programm gründlich umorganisiert haben.
In diesem Abschnitt haben Sie drei weitere grafische Entwicklungsumgebungen unter Linux kennen gelernt. Der Source Navigator von Red Hat bietet Ihnen die meisten der Funktionen, die Sie schon bei SNiFF+ gesehen hatten. Der CodeWarrior von Metrowerks bringt dagegen eine eigene Bedienphilosophie mit sich, was Ihnen den Umstieg auf Linux erleichtert, wenn Sie bereits auf einer anderen Plattform mit dieser IDE gearbeitet haben. Eclipse ist eine viel versprechende IDE, die als reines Open-Source-Projekt zwar von vielen namhaften Firmen unterstützt wird, aber erst noch eine gewisse Reife erlangen muss, um wirklich alltagstauglich zu sein - insbesondere im Hinblick auf die C++-Entwicklung.
Diese Auswahl ist bei weitem noch nicht vollständig. Ich habe vielmehr versucht, Ihnen die derzeit aus meiner Sicht wichtigsten Entwicklungsumgebungen vorzustellen, damit Sie selbst entscheiden können, welche Ihnen am besten gefällt und Ihre Anforderungen am ehesten erfüllt. Denn letztlich sollen alle Ihnen ja nur dabei helfen, Ihre eigenen Programme zu entwickeln - denn den Quelltext müssen Sie immer noch selbst schreiben.