Page MenuHomeFreeBSD

chapter.sgml
No OneTemporary

chapter.sgml

This document is not UTF8. It was detected as ISO-8859-1 (Latin 1) and converted to UTF8 for display.
<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
<!--
The FreeBSD Documentation Project
The FreeBSD German Documentation Project
$FreeBSD$
$FreeBSDde: de-docproj/books/developers-handbook/tools/chapter.sgml,v 1.11 2011/05/12 17:36:17 bcr Exp $
basiert auf: 1.52
-->
<chapter id="tools">
<chapterinfo>
<authorgroup>
<author>
<firstname>James</firstname>
<surname>Raynard</surname>
<contrib>Contributed by </contrib>
</author>
<author>
<firstname>Murray</firstname>
<surname>Stokely</surname>
</author>
</authorgroup>
<authorgroup>
<author>
<firstname>Dirk</firstname>
<surname>Arlt</surname>
<contrib>Übersetzt von </contrib>
</author>
<author>
<firstname>Fabian</firstname>
<surname>Borschel</surname>
</author>
</authorgroup>
</chapterinfo>
<title>Werkzeuge zur Programmierung</title>
<sect1 id="tools-synopsis">
<title>Überblick</title>
<para>Dieses Kapitel ist eine Einführung in die Benutzung
einiger der Werkzeuge zur Programmierung die mit FreeBSD
ausgeliefert werden. Trotzdem ist vieles auch auf verschiedene
andere Versionen von &unix; übertragbar. Dieses Kapitel
soll <emphasis>kein</emphasis> Versuch sein Programmierung
detailliert zu beschreiben. Der größte Teil dieses
Kapitels setzt wenige oder gar keine Programmierkenntnisse
voraus, dennoch sollten die meisten Programmierer etwas
Sinnvolles darin finden.</para>
</sect1>
<sect1 id="tools-intro">
<title>Zusammenfassung</title>
<para>FreeBSD bietet eine exzellente Entwicklungsumgebung.
Compiler für C und C++, sowie ein Assembler sind im
Basissystem enthalten. Natürlich finden
sich auch klassische &unix;-Werkzeuge wie <command>sed</command>
und <command>awk</command>. Sollte das nicht genug sein, finden sich
zahlreiche weitere Compiler und Interpreter in der Ports-Sammlung.
Der folgende Abschnitt, <link
linkend="tools-programming">Einführung in die Programmierung</link>,
zählt ein paar der verfügbaren Optionen auf. FreeBSD ist
kompatibel zu vielen Standards wie <acronym>&posix;</acronym>
und <acronym>ANSI</acronym> C, sowie zu seinem eigenen BSD Erbe. So
ist es möglich Anwendungen zu schreiben, welche ohne oder
zumindest ohne wesentliche Änderungen auf einer
großen Zahl an Plattformen kompilieren und laufen
werden.</para>
<para>Allerdings können all diese Möglichkeiten
anfangs etwas überwältigend sein, wenn Sie vorher nie
Programme auf einem &unix;-System geschrieben haben. Dieses
Dokument hat die Zielsetzung ihnen beim Einstieg zu helfen ohne
allzu weit in fortgeschrittene Themen vorzudringen. Die
Intention ist, daß dieses Dokument ihnen ausreichend
Basiswissen vermittelt und die weitergehende Dokumentation
sinnvoll nutzen zu können.</para>
<para>Der größte Teil dieses Dokuments erfordert wenige
oder gar keine Kenntnisse in der Programmierung, es werden
trotzdem Basiswissen im Umgang mit &unix; und die Bereitschaft
zu lernen vorausgesetzt!</para>
</sect1>
<sect1 id="tools-programming">
<title>Einführung in die Programmierung</title>
<para>Ein Programm ist eine Zusammenstellung von Anweisungen, die
den Computer auffordern verschiedenste Dinge zu tun. Dieser
Abschnitt gibt ihnen einen Überblick über die beiden
wesentlichen Methoden diese Anweisungen oder
<quote>Befehle</quote>, wie man diese Anweisungen
üblicherweise nennt, zu geben. Die eine Methode nutzt einen
<firstterm>Interpreter</firstterm>, die andere einen
<firstterm>Compiler</firstterm>. Da menschliche Sprachen
für einen Computer nicht unmissverständlich sind,
werden diese Befehle in einer Sprache geschrieben die speziell
für diesen Zweck gedacht ist.</para>
<sect2>
<title>Interpreter</title>
<para>Mit einem Interpreter ist die Sprache vielmehr eine
Umgebung, in der Sie ein Kommando an der Kommandozeile
eingeben welches dann von der Umgebung ausgeführt wird.
Für kompliziertere Programme können Sie die Befehle
in eine Datei schreiben und den Interpreter dazu bringen diese
Datei zu laden und die enthaltenen Befehle auszuführen.
Falls etwas schief geht werden viele Interpreter Sie an einen
Debugger weiterleiten.</para>
<para>Der Vorteil hierbei ist, das Sie das Ergebnis ihres
Befehls direkt sehen und Fehler sofort korrigiert werden
können. Der größte Nachteil bei dieser Methode
entsteht, wenn Sie ihr Programm mit jemandem teilen wollen.
Diese Person muss den selben Interpreter nutzen wie Sie es tun
und Sie muss wissen wie dieser zu bedienen ist.
Zudem werden Benutzer es nicht begrüßen sich in
einem Debugger wiederzufinden, wenn Sie einmal die falsche
Taste drücken! Bei einem Blick auf die
Leistungsfähigkeit brauchen Interpreter oftmals viel
Speicher und erzeugen den Code nicht so effizient wie
Compiler.</para>
<para>Meiner Meinung nach sind interpretierte Sprachen der beste
Anfang, wenn Sie bisher noch nicht programmiert haben. Diese
Art von Umgebung findet man typischerweise bei Sprachen wie
Lisp, Smalltalk, Perl und Basic. Man könnte auch sagen,
dass die &unix; Shell (<command>sh</command>,
<command>csh</command>) für sich bereits einen
Interpreter darstellt und viele Leute schreiben
tatsächlich Shell <quote>Scripten</quote> um sich bei
einigen <quote>Haushaltsaufgaben</quote> auf ihren Maschinen
helfen zu lassen. Tatsächlich war es ein wesentlicher
Teil der originalen &unix; Philosophie eine große Zahl
an kleinen Hilfsprogrammen zur Verfügung zu stellen,
welche mittels eines Shellskripts miteinander kombiniert werden
um bestimmte Aufgaben zu übernehmen.</para>
</sect2>
<sect2>
<title>Für FreeBSD verfügbare Interpreter</title>
<para>Im folgenden eine Liste der über die &os;
Ports-Sammlung verfügbaren Interpreter
einschließlich einer kurzen Erörterung der
populären interpretierten Sprachen.</para>
<para>Anleitungen wie man Anwendungen aus der Ports-Sammlung
erhält und installiert können Sie dem Kapitel <ulink
url="&url.books.handbook;/ports-using.html">Benutzen der
Ports-Sammlung</ulink> aus dem FreeBSD Handbuch
entnehmen.</para>
<variablelist>
<varlistentry>
<term><acronym>BASIC</acronym></term>
<listitem>
<para>Kurz für Beginner's All-purpose Symbolic
Instruction Code. Entwickelt in den 50er Jahren um
Studenten in Programmierung zu unterrichten, wurde
<acronym>BASIC</acronym> in den 80er Jahren mit jedem
anständigen Personal Computer ausgeliefert und war
für viele Programmierer die erste
Programmiersprache. <acronym>BASIC</acronym> ist auch
die Grundlage für Visual Basic.</para>
<para>Der Bywater Basic Interpreter findet sich in der
Ports-Sammlung unter <filename
role="package">lang/bwbasic</filename> und Phil
Cockroft's Basic Interpreter (auch bekannt als Rabbit
Basic) findet sich unter <filename
role="package">lang/pbasic</filename>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Lisp</term>
<listitem>
<para>Diese Sprache wurde in den späten 50er Jahren
als Alternative zu den, zu dieser Zeit populären,
<quote>zahlenverarbeitenden</quote> Sprachen entwickelt.
Anstelle auf Zahlen basiert Lisp auf Listen;
tatsächlich ist der Name Lisp eine Kurzform
für <quote>List Processing</quote> (Listen
abarbeiten). Sehr populär fü
<acronym>AI</acronym> (Artificial Intelligence/
künstliche Intelligez) (Fach-) Kreisen.</para>
<para>Lisp ist eine extrem kraftvolle und durchdachte
Sprache, kann aber auch recht groß und unhandlich
sein.</para>
<para>Zahlreiche Ausformungen von Lisp, die auf &unix;
Systemen laufen sind über die Ports-Sammlung
verfügbar. GNU Common Lisp befindet sich in
<filename role="package">lang/gcl</filename>. CLISP von
Bruno Haible und Michael Stoll ist in <filename
role="package">lang/clisp</filename> zu finden. Für
CMUCL, welches auch einen hoch-optimierten Compiler
enthält, oder einfachere Ausformungen wie SLisp,
das die meisten gängigen Lisp Konstrukte in wenigen
hundert Zeilen C Code enthält sind in <filename
role="package">lang/cmucl</filename> und <filename
role="package">lang/slisp</filename> ebenfalls
enthalten.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Perl</term>
<listitem>
<para>Unter Systemadministratoren zum Schreiben von
Skripten sehr beliebt; wird häufig auch auf World
Wide Web Servern verwendet, um
<acronym>CGI</acronym>-Skripte zu schreiben.</para>
<para>Perl ist in der Ports-Sammlung unter <filename
role="package">lang/perl5.8</filename> für alle
&os;-Versionen verfügbar, und wird im Basissystem
von 4.x als <command>/usr/bin/perl</command>
installiert.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Scheme</term>
<listitem>
<para>Ein Dialekt von Lisp, der kompakter und sauberer
als Common Lisp ist. Dieser Dialekt ist an
Universitäten sehr beliebt, da er zum einen
für den Unterricht im Grundstudium einfach genug
ist, und zum anderen ein ausreichend hohes
Abstraktionsniveau für den Einsatz in der Forschung
bietet.</para>
<para>Scheme ist in der Ports-Sammlung in Form des Elk
Scheme Interpreters als <filename
role="package">lang/elk</filename> verfügbar. Den
MIT Scheme Interpreter findet man unter <filename
role="package">lang/mit-scheme</filename>, und den SCM
Scheme Interpreter unter <filename
role="package">lang/scm</filename>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Icon</term>
<listitem>
<para>Icon ist eine Hochsprache mit ausgereiften
Möglichkeiten zur Verarbeitung von Zeichenketten
und Strukturen. Die unter &os; verfügbare Version
von Icon steht in der Ports-Sammlung unter <filename
role="package">lang/icon</filename> zur
Verfügung.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Logo</term>
<listitem>
<para>Logo ist eine leicht zu erlernende
Programmiersprache, welche in vielen Kursen als
einführende Programmiersprache gewählt wird.
Sie ist ein ideales Arbeitswerkzeug beim Unterricht mit
jungen Menschen, da mit ihr die Erstellung komplizierter
geometrischer Oberflächen selbst für kleine
Kinder einfach ist.</para>
<para>Die für &os; aktuellste, verfügbare
Version findet man in der Ports-Sammlung unter <filename
role="package">lang/logo</filename>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Python</term>
<listitem>
<para>Python ist eine objektorientierte, interpretierte
Programmiersprache. Die Verfechter von Python
argumentieren, daß sie eine der besten
Programmiersprachen für Programmieranfänger
sei, da sie einfach zu erlernen ist, und anderen
populären interpretierten Programmiersprachen,
welche zur Entwicklung großer und komplexer
Anwendungen verwendet werden, in nichts nachsteht (Perl
und Tcl sind zwei solcher bekannten
Programmiersprachen).</para>
<para>Die aktuellste Version von Python ist in der
Ports-Sammlung unter <filename
role="package">lang/python</filename>
verfügbar.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Ruby</term>
<listitem>
<para>Ruby ist eine interpretierte und rein
objektorientierte Programmiersprache. Sie wurde wegen
ihrer leicht verständlichen Syntax, ihrer
Flexibilität und der Möglichkeit, große und
komplexe Programme einfach zu entwickeln und zu pflegen,
populär.</para>
<para>Ruby ist in der Ports-Sammlung unter <filename
role="package">lang/ruby18</filename>
verfügbar.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Tcl und Tk</term>
<listitem>
<para>Tcl ist eine einbettbare, interpretierte
Programmiersprache, welche aufgrund ihrer Portierbarkeit
auf viele unterschiedliche Plattformen eine weite
Verbreitung erfahren hat. Sie kann sowohl für die
schnelle Entwicklung kleinerer Prototypen, als auch (in
Verbindung mit Tk, einem GUI Toolkit) vollwertiger,
ausgereifter Programme verwendet werden.</para>
<para>Es sind mehrere Versionen von Tcl als Ports
für &os; verfügbar. Die aktuellste Version,
Tcl 8.5, ist unter <filename
role="package">lang/tcl85</filename>
verfügbar.</para>
</listitem>
</varlistentry>
</variablelist>
</sect2>
<sect2>
<title>Compiler</title>
<para>Compiler sind eher anders. Zuerst schreibt man seinen
Code unter Verwendung eines Editors in eine Datei (oder
mehrere Dateien). Anschließend ruft man den Compiler auf
um zu sehen, ob dieser das Programm annimmt. Wenn das Programm
nicht kompiliert werden konnte, muß man die Zähne
zusammenbeissen und wieder zum Editor zurückkehren; falls
das Programm kompiliert und eine ausführbare Anwendung
erzeugt wurde, kann man diese über eine
Eingabeaufforderung oder über einen Debugger aufrufen um
zu sehen, ob sie auch funktioniert.
<footnote>
<para>Wenn die Anwendung über eine Eingabeaufforderung
gestartet wird könnte bei Auftreten eines
Programmfehlers dieses abgebrochen und ein Speicherabbild
erzeugt werden.</para>
</footnote>
</para>
<para>Offensichtlich ist diese Art der Programmierung nicht
so direkt wie die Verwendung eines Interpreters. Jedoch sind
auf diese Weise viele Dinge möglich, die mit einem
Interpreter nur sehr schwer oder überhaupt nicht
realisierbar wären, wie z.B. das Schreiben von Code, der
sehr eng mit dem Betriebsystem zusammen arbeitet&mdash;oder
das Schreiben eines eigenen Betriebsystems selbst! Des
weiteren ist so das Erzeugen von sehr effizientem Code
möglich, da sich der Compiler für die Optimierung
Zeit nehmen kann, was bei einem Interpreter inakzeptabel
wäre. Ferner ist das Verbreiten von Programmen, welche
für einen Compiler geschrieben wurden, einfacher als
welche, die für einen Interpreter geschrieben
wurden&mdash;man muss in ersterem Fall nur die
ausführbare Datei verbreiten, vorausgesetzt, daß das
gleiche Betriebssystem verwendet wird.</para>
<para>Programmiersprachen, die kompiliert werden, sind unter
anderem Pascal, C und C++. C und C++ sind eher unbarmherzige
Programmiersprachen und daher eher für erfahrene
Programmierer gedacht; Pascal auf der anderen Seite wurde zu
Ausbildungszwecken entworfen, und stellt daher eine
einsteigerfreundliche Programmiersprache dar. FreeBSD
beinhaltet im Basissystem keine Unterstützung für
Pascal, stellt jedoch über die Ports-Sammlung den
Free Pascal Compiler unter <filename
role="package">lang/fpc</filename> zur Verfügung.</para>
<para>Da der editier-kompilier-ausführ-debug-Kreislauf
unter Verwendung mehrerer Programme eher mühsam ist haben
viele Hersteller von Compilern integrierte
Entwicklungsumgebungen (Integrated Development Environment;
auch kurz <acronym>IDE</acronym>) entwickelt. FreeBSD bietet
zwar im Basissystem keine IDE an, stellt jedoch über die
Ports-Sammlung IDEs wie <filename
role="package">devel/kdevelop</filename> oder
<application>Emacs</application> zur Verfügung, wobei
letztere weit verbreitet ist. Die Verwendung von
<application>Emacs</application> als IDE wird unter <xref
linkend="emacs"/> diskutiert.</para>
</sect2>
</sect1>
<sect1 id="tools-compiling">
<title>Kompilieren mit dem <command>cc</command></title>
<para>Dieser Abschnitt behandelt ausschließlich den GNU
Compiler für C und C++, da dieser bereits im Basissystem
von FreeBSD enthalten ist. Er kann mittels <command>cc</command>
oder <command>gcc</command> aufgerufen werden. Die Details zur
Erstellung einer Anwendung mit einem Interpreter variieren
zwischen verschiedenen Interpretern mehr oder weniger stark, und
werden meist ausführlich in der zugehörigen
Dokumentation oder Online-Hilfe beschrieben.</para> <para>Sobald
Sie Ihr Meisterwerk fertig geschrieben haben besteht der
nächste Schritt darin, dieses (hoffentlich!) unter FreeBSD
zum Laufen zu bekommen. Dies beinhaltet üblicherweise
mehrere Schritte, wobei jeder einzelne Schritt von einem
separaten Programm durchgeführt wird.</para>
<procedure>
<step>
<para>Aufbereiten Ihres Quelltextes durch Entfernen von
Kommentaren, sowie weiteren Tricks wie das Ersetzen von
Macros in C.</para>
</step>
<step>
<para>Überprüfen der Syntax Ihres Quelltextes, um
die Einhaltung der Sprachregeln sicherzustellen. Wenn Sie
diese verletzt haben werden entsprechende Fehlermeldungen
Ihnen dies mitteilen!</para>
</step>
<step>
<para>Übersetzen des Quelltextes in Assemblersprache
&mdash;diese ist dem eigentlichen Maschinencode schon sehr
nahe, jedoch immer noch für Menschen lesbar.
Angeblich.
<footnote>
<para>Um genau zu sein übersetzt der
<command>cc</command> den Quelltext an dieser Stelle
nicht in Assemblersprache, sondern in seine eigene,
maschinenunabhängige Sprache namens
<firstterm>p-code</firstterm>.</para>
</footnote>
</para>
</step>
<step>
<para>Übersetzen der Assemblersprache in
Maschinencode&mdash;genau, wir sprechen hier von Bits und
Bytes, Einsen und Nullen.</para>
</step>
<step>
<para>Überprüfen, ob Sie Dinge wie Funktionen und
globale Variablen in einheitlicher Weise verwendet haben.
Wenn Sie z.B. eine nicht existierende Funktion aufgerufen
haben, wird eine entsprechende Fehlermeldung Ihnen dies
mitteilen.</para>
</step>
<step>
<para>Wenn aus mehreren Quelltextdateien eine
ausführbare Datei erstellt werden soll wird
herausgefunden, wie die einzelnen Codeteile
zusammengefügt werden müssen.</para>
</step>
<step>
<para>Ausarbeiten, wie das Programm aussehen muss, damit
der Lader zur Laufzeit des Systems dieses in den Speicher
laden und ausführen kann.</para>
</step>
<step>
<para>Endgültiges Schreiben der ausführbaren Datei
in das Dateisystem.</para>
</step>
</procedure>
<para>Das Wort <firstterm>kompilieren</firstterm> wird häufig
für die Schritte 1 bis 4 verwendet&mdash;die anderen werden
mit dem Wort <firstterm>verlinken</firstterm> zusammengefasst.
Manchmal wird Schritt 1 auch als
<firstterm>Pre-Processing</firstterm> und die Schritte 3-4 als
<firstterm>assemblieren</firstterm> bezeichnet.</para>
<para>Glücklicherweise werden alle diese Details vor Ihnen
verborgen, da <command>cc</command> ein Frontend ist, welches
sich um die Ausführung all dieser Programme mit den
richtigen Argumenten für Sie kümmert; einfaches
eingeben von</para>
<screen>&prompt.user; <userinput>cc foobar.c</userinput></screen>
<para>führt zur Übersetzung von
<filename>foobar.c</filename> durch alle bereits erwähnten
Schritte. Wenn Sie mehr als eine Datei übersetzen wollen
müssen Sie etwas wie folgt eingeben</para>
<screen>&prompt.user; <userinput>cc foo.c bar.c</userinput></screen>
<para>Beachten Sie, daß die Überprüfung der Syntax
genau dies tut&mdash;das reine Überprüfen der Syntax.
Es findet keine Überprüfung bzgl. logischer Fehler
statt, die Sie vielleicht gemacht haben, wie z.B. das Programm
in eine Endlosschleife zu versetzen, oder Bubble Sort zu
verwenden, wenn Sie eigentlich Binary Sort benutzen wollten.
<footnote>
<para>Falls Sie es nicht wußten, Binary Sort ist, im
Gegensatz zu Bubble Sort, eine effektive Möglichkeit,
Dinge zu sortieren.</para>
</footnote>
</para>
<para>Es gibt haufenweise Optionen für <command>cc</command>,
die alle in der zugehörigen Manualpage beschrieben werden.
Im Folgenden werden ein paar der wichtigsten Optionen mit
Beispielen ihrer Anwendung gezeigt.</para>
<variablelist>
<varlistentry>
<term><option>-o <replaceable>filename</replaceable></option></term>
<listitem>
<para>Die Name der Ausgabedatei. Wenn Sie diese Option nicht
verwenden erstellt <command>cc</command> eine Datei mit
dem Namen <filename>a.out</filename>.
<footnote>
<para>Der Grund dafür ist im Haufen der Geschichte
begraben.</para>
</footnote>
</para>
<informalexample>
<screen>&prompt.user; <userinput>cc foobar.c</userinput> <lineannotation>executable is <filename>a.out</filename></lineannotation>
&prompt.user; <userinput>cc -o foobar foobar.c</userinput> <lineannotation>executable is <filename>foobar</filename></lineannotation>
</screen>
</informalexample>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-c</option></term>
<listitem>
<para>Dies kompiliert die Datei nur, verlinkt sie jedoch
nicht. Nützlich für Spielereien, um die Syntax
auf Korrektheit zu überprüfen, oder falls Sie
ein <filename>Makefile</filename> verwenden.</para>
<informalexample>
<screen>&prompt.user; <userinput>cc -c foobar.c</userinput>
</screen>
</informalexample>
<para>Dieser Befehl erzeugt eine
<firstterm>Objektdatei</firstterm> (nicht ausführbar)
mit den Namen <filename>foobar.o</filename>. Diese kann
mit anderen Objektdateien zusammen zu einer
ausführbaren Datei verlinkt werden.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-g</option></term>
<listitem>
<para>Diese Option erzeugt die Debug-Version einer
ausführbaren Datei. Dabei fügt der Compiler
zusätzliche Informationen darüber, welcher
Funktionsaufruf zu welcher Zeile im Quelltext gehört,
der ausführbaren Datei hinzu. Ein Debugger kann Ihnen
mit Hilfe dieser Information den zugehörigen
Quelltext anzeigen, während Sie den Programmverlauf
schrittweise verfolgen, was <emphasis>sehr</emphasis>
hilfreich sein kann; der Nachteil dabei ist, daß
durch die zusätzlichen Informationen das Programm
viel größer wird. Normalerweise verwendet man
die Option <option>-g</option> während der
Entwicklung eines Programms, und für die
<quote>Release-Version</quote>, wenn man von der
Korrektheit des Programms überzeugt ist, kompiliert
man das Programm dann ohne diese Option.</para>
<informalexample>
<screen>&prompt.user; <userinput>cc -g foobar.c</userinput>
</screen>
</informalexample>
<para>Mit diesem Befehl wird eine Debug-Version des
Programms erzeugt.
<footnote>
<para>Beachten Sie, daß an dieser Stelle die
Option <option>-o</option> zum Festlegen des Namens
der ausführbaren Datei nicht verwendet wurde,
weswegen an dieser Stelle die erzeugte Datei
<filename>a.out</filename> heißt. Die Erzeugung
einer Debug-Version namens <filename>foobar</filename>
ist als Übung dem Leser überlassen!</para>
</footnote>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-O</option></term>
<listitem>
<para>Diese Option erzeugt eine optimierte Version der
ausführbaren Datei. Der Compiler verwendet einige
clevere Tricks, um das erzeugte Programm schneller zu
machen. Sie können hinter der Option
<option>-O</option> eine Zahl angeben, um eine
höheres Level der Optimierung festzulegen. Dadurch
wird jedoch häufig eine fehlerhafte Optimierung
seitens des Compilers aufgedeckt. Zum Beispiel erzeugte
die Version des <command>cc</command>, welche mit dem
FreeBSD Release 2.1.0 mitgeliefert wurde, bei Verwendung
der Option <option>-O2</option> unter bestimmten
Umständen falschen Code.</para>
<para>Optimierungen werden normalerweise nur beim
Kompilieren von Release-Versionen aktiviert.</para>
<informalexample>
<screen>&prompt.user; <userinput>cc -O -o foobar foobar.c</userinput>
</screen>
</informalexample>
<para>Durch diesen Befehl wird eine optimierte Version von
<filename>foobar</filename> erzeugt.</para>
</listitem>
</varlistentry>
</variablelist>
<para>Die folgenden drei Flags zwingen den <command>cc</command>
dazu, Ihren Code auf die Einhaltung der internationalen
Standards hin zu überprüfen, welche häufig als
<acronym>ANSI</acronym> Standards bezeichnet werden, obwohl sie
streng genommen zum <acronym>ISO</acronym> Standard
gehören.</para>
<variablelist>
<varlistentry>
<term><option>-Wall</option></term>
<listitem>
<para>Aktivieren aller Warnmeldungen, die die Autoren des
<command>cc</command> für wichtig halten. Trotz des
Namens dieser Option werden dadurch nicht sämtliche
Warnungen ausgegeben, die der <command>cc</command>
ausgeben könnte.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-ansi</option></term>
<listitem>
<para>Deaktivieren der meisten, jedoch nicht aller,
nicht-<acronym>ANSI</acronym>&nbsp;C Eigenschaften, die
der <command>cc</command> bietet. Trotz des Namens ist
durch diese Option nicht sichergestellt, daß Ihr
Code diese Standards auch vollständig
einhält.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-pedantic</option></term>
<listitem>
<para>Deaktivieren <emphasis>aller</emphasis> Eigenschaften
des <command>cc</command>, welche nicht konform zu
<acronym>ANSI</acronym>&nbsp;C sind.</para>
</listitem>
</varlistentry>
</variablelist>
<para>Ohne diese Flags wird Ihnen der <command>cc</command> die
Verwendung eigener Erweiterungen des Standards erlauben. Einige
dieser Erweiterungen sind zwar sehr nützlich, werden jedoch
nicht von anderen Compilern unterstützt&mdash;eigentlich
ist eines der Hauptziele des Standards, das Leute Code so
schreiben können, daß dieser mit jedem Compiler auf
beliebigen Systemen funktioniert. Dies wird häufig als
<firstterm>portabler Code</firstterm> bezeichnet.</para>
<para>Im Allgemeinen sollten Sie versuchen, Ihren Code so portabel
wie möglich zu schreiben, da Sie ansonsten eventuell das
gesamte Programm noch einmal neu schreiben müssen, falls
dieser in einer anderen Umgebung laufen soll&mdash;und wer
weiß schon was er in ein paar Jahren verwenden
wird?</para>
<informalexample>
<screen>&prompt.user; <userinput>cc -Wall -ansi -pedantic -o foobar foobar.c</userinput></screen>
</informalexample>
<para>Durch diesen Befehl wird eine ausführbare Datei namens
<filename>foobar</filename> erzeugt, nachdem
<filename>foobar.c</filename> auf die Einhaltung der Standards
überprüft wurde.</para>
<variablelist>
<varlistentry>
<term><option>-l<replaceable>library</replaceable></option></term>
<listitem>
<para>Mit dieser Option kann eine Bibliothek mit Funktionen
angegeben werden, die während des Verlinkens
verwendet wird.</para>
<para>Das am häufigsten auftretende Beispiel dieser
Option ist die Übersetzung eines Programmes, welches
einige der mathematischen Funktionen in C verwendet. Im
Gegensatz zu den meisten anderen Plattformen befinden sich
diese Funktionen in einer separaten Bibliothek, deren
Verwendung Sie dem Compiler explizit mitteilen
müssen.</para>
<para>Angenommen eine Bibliothek heißt
<filename>lib<replaceable>irgendwas</replaceable>.a</filename>,
dann müssen Sie dem <command>cc</command> als
Argument
<option>-l<replaceable>irgendwas</replaceable></option>
übergeben. Zum Beispiel heißt die
Mathematik-Bibliothek <filename>libm.a</filename>, und
daher müssen Sie dem <command>cc</command> als
Argument <option>-lm</option> übergeben. Ein
typisches <quote>Manko</quote> der Mathematik-Bibliothek
ist, daß diese immer die letzte Bibliothek auf der
Kommandozeile sein muß.</para>
<informalexample>
<screen>&prompt.user; <userinput>cc -o foobar foobar.c -lm</userinput>
</screen>
</informalexample>
<para>Durch diesen Befehl werden die Funktionen aus der
Mathematik-Bibliothek in <filename>foobar</filename>
gelinkt.</para>
<para>Wenn Sie C++-Code kompilieren wollen, müssen Sie
<option>-lg++</option>, bzw. <option>-lstdc++</option>
falls Sie FreeBSD 2.2 oder neuer verwenden, zu Ihrer
Kommandozeile hinzufügen, um Ihr Programm gegen die
Funktionen der C++ Bibliothek zu linken. Alternativ
können Sie anstatt <command>cc</command> auch
<command>c++</command> aufrufen, welcher dies für Sie
erledigt. <command>c++</command> kann unter FreeBSD auch
als <command>g++</command> aufgerufen werden.</para>
<informalexample>
<screen>&prompt.user; <userinput>cc -o foobar foobar.cc -lg++</userinput> <lineannotation>Bei FreeBSD 2.1.6 oder älter</lineannotation>
&prompt.user; <userinput>cc -o foobar foobar.cc -lstdc++</userinput> <lineannotation>Bei FreeBSD 2.2 und neuer</lineannotation>
&prompt.user; <userinput>c++ -o foobar foobar.cc</userinput>
</screen>
</informalexample>
<para>Beide Varianten erzeugen eine ausführbare
<filename>foobar</filename> aus der C++ Quelltextdatei
<filename>foobar.cc</filename>. Beachten Sie bitte,
daß auf &unix; Systemen C++ Quelltextdateien
üblicherweise auf <filename>.C</filename>,
<filename>.cxx</filename> oder <filename>.cc</filename>
enden, und nicht wie bei &ms-dos; auf
<filename>.cpp</filename> (welche schon anderweitig
benutzt wurde). Der <command>gcc</command> hat
normalerweise anhand dieser Information entschieden,
welcher Compiler für die Quelltextdatei zum Einsatz
kommen soll; allerdings gilt diese Einschränkung
jetzt nicht mehr, und Sie können Ihre C++-Dateien
ungestraft auf <filename>.cpp</filename> enden
lassen!</para>
</listitem>
</varlistentry>
</variablelist>
<sect2>
<title>Häufig auftretende <command>cc</command>-Fragen und
-Probleme</title>
<qandaset>
<qandaentry>
<question>
<para>Ich versuche ein Programm zu schreiben, welches die
Funktion <function>sin()</function> verwendet, erhalte
jedoch eine Fehlermeldung. Was bedeutet diese?</para>
<informalexample>
<screen>/var/tmp/cc0143941.o: Undefined symbol `_sin' referenced from text segment
</screen>
</informalexample>
</question>
<answer>
<para>Wenn Sie mathematische Funktionen wie
<function>sin()</function> verwenden wollen, müssen
Sie den <command>cc</command> anweisen, die
Mathematik-Bibliothek wie folgt zu verlinken:</para>
<informalexample>
<screen>&prompt.user; <userinput>cc -o foobar foobar.c -lm</userinput>
</screen>
</informalexample>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>So, ich habe jetzt dieses einfache Programm als
Übung für <option>-lm</option> geschrieben.
Alles was es macht ist, 2.1 hoch 6 zu berechnen.</para>
<informalexample>
<programlisting>#include &lt;stdio.h&gt;
int main() {
float f;
f = pow(2.1, 6);
printf("2.1 ^ 6 = %f\n", f);
return 0;
}
</programlisting>
</informalexample>
<para>und ich habe es wie folgt kompiliert:</para>
<informalexample>
<screen>&prompt.user; <userinput>cc temp.c -lm</userinput>
</screen>
</informalexample>
<para>wie mir gesagt wurde. Allerdings bekomme ich jetzt
bei der Ausführung die folgende Ausgabe:</para>
<informalexample>
<screen>&prompt.user; <userinput>./a.out</userinput>
2.1 ^ 6 = 1023.000000
</screen>
</informalexample>
<para>Das ist <emphasis>nicht</emphasis> die richtige
Antwort! Was ist hier los?</para>
</question>
<answer>
<para>Wenn der Compiler Ihren Funktionsaufruf sieht,
überprüft er, ob er schon einmal einen
Prototypen für diese gesehen hat. Wenn nicht nimmt
er als Rückgabewert den Typ <type>int</type> an,
was sicherlich nicht das ist, was Sie an dieser Stelle
wollen.</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>Wie kann ich das korrigieren?</para>
</question>
<answer>
<para>Die Prototypen der mathematischen Funktionen
befinden sich in der Datei <filename>math.h</filename>.
Wenn Sie diese Datei in Ihrem Quelltext includen ist der
Compiler in der Lage, den Prototypen zu finden, und wird
aufhören, seltsame Dinge mit Ihrer Berechnung zu
machen!</para>
<informalexample>
<programlisting>#include &lt;math.h&gt;
#include &lt;stdio.h&gt;
int main() {
...
</programlisting>
</informalexample>
<para>Nach erneutem Compilieren sollte das Folgende bei
der Ausführung ausgegeben werden:</para>
<informalexample>
<screen>&prompt.user; <userinput>./a.out</userinput>
2.1 ^ 6 = 85.766121
</screen>
</informalexample>
<para>Wenn Sie irgendwelche mathematischen Funktionen
verwenden sollten Sie <emphasis>immer</emphasis> die
Datei <filename>math.h</filename> includen und nicht
vergessen, Ihr Programm gegen die Mathematik-Bibliothek
zu verlinken.</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>Ich habe eine Datei mit dem Namen
<filename>foobar.c</filename> kompiliert, kann jedoch
nirgends eine ausführbare Datei namens
<filename>foobar</filename> finden. Wo befindet sich
diese?</para>
</question>
<answer>
<para>Denken Sie daran, daß der
<command>cc</command> die ausführbare Datei
<filename>a.out</filename> nennt, wenn Sie nicht
explizit einen Namen angeben. Verwenden Sie in solch
einem Fall die Option
<option>-o&nbsp;<replaceable>filename</replaceable></option>:</para>
<informalexample>
<screen>&prompt.user; <userinput>cc -o foobar foobar.c</userinput>
</screen>
</informalexample>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>OK, ich habe eine ausführbare Datei namens
<filename>foobar</filename>, ich kann sie sehen, wenn
ich <command>ls</command> aufrufe. Gebe ich jedoch
<command>foobar</command> in die Kommandozeile ein wird
mir gesagt, daß eine Datei mit diesem Namen nicht
existiert. Warum kann die Datei nicht gefunden
werden?</para>
</question>
<answer>
<para>Im Gegensatz zu &ms-dos; sucht &unix; nicht im
aktuellen Verzeichnis nach einem ausführbaren
Programm, das Sie versuchen auszuführen, solange
Sie dies nicht explizit mit angeben. Sie können
entweder <command>./foobar</command> eingeben, was
soviel bedeutet wie <quote>führe eine Datei namens
<filename>foobar</filename> im aktuellen Verzeichnis
aus</quote>, oder Sie können Ihre Umgebungsvariable
<envar>PATH</envar> so erweitern, daß sie
ähnlich wie folgt aussieht</para>
<informalexample>
<screen>bin:/usr/bin:/usr/local/bin:.
</screen>
</informalexample>
<para>Der Punkt am Ende bedeutet <quote>siehe im aktuellen
Verzeichnis nach, wenn es in keinem der anderen zu
finden war</quote>.</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>Ich habe meine ausführbare Datei
<filename>test</filename> genannt, allerdings passiert
nichts wenn ich diese aufrufe. Was ist hier los?</para>
</question>
<answer>
<para>Bei den meisten &unix;-Systeme existiert bereits
ein Programm mit dem Namen <command>test</command> im
Verzeichnis <filename>/usr/bin</filename>, und die Shell
nimmt dieses, bevor sie im aktuellen Verzeichnis
nachsieht. Sie können entweder den folgenden Befehl
eingeben:</para>
<informalexample>
<screen>&prompt.user; <userinput>./test</userinput>
</screen>
</informalexample>
<para>oder Sie können einen geeigneteren Namen
für Ihr Programm wählen!</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>Ich habe mein Programm kompiliert und bei dessen
Aufruf sah zuerst alles gut aus. Jedoch gab es dann eine
Fehlermeldung, welche irgendetwas mit <errorname>core
dumped</errorname> lautete. Was bedeutet das?</para>
</question>
<answer>
<para>Der Name <firstterm>core dump</firstterm> stammt
noch aus sehr frühen Zeiten von &unix;, als die
Maschinen noch Kernspeicher zum Speichern von Daten
verwendeten. Einfach ausgedrückt, wenn bei einem
Programm unter bestimmen Bedingungen ein Fehler auftrat,
hat das System den Inhalt des Kernspeichers auf der
Festplatte in eine Datei namens
<filename>core</filename> geschrieben, welche der
Programmierer dann näher untersuchen konnte, um die
Ursache des Fehlers herauszufinden.</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>Faszinierendes Zeugs, aber was soll ich jetzt
machen?</para>
</question>
<answer>
<para>Verwenden Sie den <command>gdb</command>, um das
Speicherabbild zu untersuchen (siehe <xref
linkend="debugging"/>).</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>Als mein Programm den core dump erzeugt hat, sagte
es etwas von einem <errorname>segmentation
fault</errorname>. Was ist das?</para>
</question>
<answer>
<para>Diese Meldung heißt im Prinzip, daß Ihr
Programm eine illegale Operation mit dem Speicher
durchführen wollte; &unix; wurde so entworfen,
daß es das andere Programme und das Betriebssystem
selbst vor wildgewordenen Programmen
schützt.</para>
<para>Häufige Ursachen hierfür sind:</para>
<itemizedlist>
<listitem>
<para>Der Versuch, einen <symbol>NULL</symbol>-Zeiger
zu beschreiben, z.B.</para>
<programlisting>char *foo = NULL;
strcpy(foo, "bang!");
</programlisting>
</listitem>
<listitem>
<para>Einen Zeiger zu verwenden, welcher noch nicht
initialisiert wurde, z.B.</para>
<programlisting>char *foo;
strcpy(foo, "bang!");
</programlisting>
<para>Der Zeiger hat einen zufälligen Wert,
welcher mit etwas Glück in einen Bereich des
Speichers zeigt, der für Ihr Programm nicht
verfügbar ist, und der Kernel bricht Ihr
Programm ab, bevor es irgendwelchen Schaden
anrichten kann. Wenn Sie Pech haben zeigt der Zeiger
irgendwo mitten in Ihr eigenes Programm, und
verändert dort ihre eigenen Datenstrukturen,
was zu sehr seltsamen Fehlern Ihres Programmes
führt.</para>
</listitem>
<listitem>
<para>Der Versuch, auf Daten außerhalb eines
Arrays zuzugreifen, z.B.</para>
<programlisting>int bar[20];
bar[27] = 6;
</programlisting>
</listitem>
<listitem>
<para>Der Versuch, Daten in eine Speicherbereich zu
schreiben, der nur lesbar ist, z.B.</para>
<programlisting>char *foo = "My string";
strcpy(foo, "bang!");
</programlisting>
<para>&unix;-Compiler speichern häufig feste
Zeichenketten wie <literal>"My string"</literal> in
nur lesbaren Speicherbereichen ab.</para>
</listitem>
<listitem>
<para>Wenn man unerlaubte Operationen mit
<function>malloc()</function> und
<function>free()</function> ausführt,
z.B.</para>
<programlisting>char bar[80];
free(bar);
</programlisting>
<para>oder</para>
<programlisting>char *foo = malloc(27);
free(foo);
free(foo);
</programlisting>
</listitem>
</itemizedlist>
<para>Einzelne solcher Fehler führen zwar nicht
immer zu einem Fehlverhalten des Programms, stellen
jedoch immer eine falsche Verwendung dar. Manche Systeme
und Compiler sind toleranter als andere, weshalb
Programme auf dem einen System einwandfrei laufen, auf
dem anderen System jedoch abstürzen.</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>Wenn ich einen core dump erhalte erscheint
manchmal die Meldung <errorname>bus error</errorname>.
In meinem &unix;-Buch steht, daß die Ursache ein
Hardwareproblem sei. Der Computer scheint aber weiterhin
zu funktionieren. Ist dies wahr?</para>
</question>
<answer>
<para>Nein, glücklicherweise nicht (es sei denn Sie
haben wirklich ein Hardwareproblem&hellip;).
Üblicherweise ist dies ein Weg Ihnen mitzuteilen,
daß Sie auf Speicher in einer Weise zugegriffen
haben, in der Sie dies nicht tun sollten.</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>Diese Sache mit den core dumps hört sich sehr
nützlich an, wenn ich so etwas selber an beliebiger
Stelle bewirken könnte. Kann ich das tun, oder
muß ich warten bis ein Fehler auftritt?</para>
</question>
<answer>
<para>Ja, nehmen sie einfach eine andere Konsole oder
XTerm und führen Sie</para>
<screen>&prompt.user; <userinput>ps</userinput>
</screen>
<para>aus, um die Prozess-ID Ihres Programms
herauszufinden. Führen Sie
anschließend</para>
<screen>&prompt.user; <userinput>kill -ABRT <replaceable>pid</replaceable></userinput>
</screen>
<para>aus, wobei
<parameter><replaceable>pid</replaceable></parameter>
die Prozess-ID ist, die Sie vorher ermittelt
haben.</para>
<para>Dies ist nützlich, wenn sich Ihr Programm z.B.
in einer Endlosschleife verfangen hat. Sollte Ihr
Programm das Signal <symbol>SIGABRT</symbol> abfangen,
gibt es noch andere Möglichkeiten, die denselben
Effekt haben.</para>
<para>Alternativ können Sie einen core dump aus
Ihrem Programm heraus erstellen, indem Sie die Funktion
<function>abort()</function> aufrufen. Weitere
Informationen darüber können Sie in der
Manualpage &man.abort.3; nachlesen.</para>
<para>Wenn Sie einen core dump von außerhalb Ihres
Programms erzeugen wollen, ohne dabei den Prozess
abzubrechen, können Sie das Programm
<command>gcore</command> verwenden. Weitere
Informationen dazu finden Sie in der zugehörigen
Manualpage &man.gcore.1;.</para>
</answer>
</qandaentry>
</qandaset>
</sect2>
</sect1>
<sect1 id="tools-make">
<title>Make</title>
<sect2>
<title>Was ist <command>make</command>?</title>
<para>Wenn Sie an einem einfachen Programm mit nur einer oder
zwei Quelltextdateien arbeiten, ist die Eingabe von</para>
<screen>&prompt.user; <userinput>cc file1.c file2.c</userinput></screen>
<para>zwar nicht aufwendig, wird aber mit zunehmender Anzahl
der Quelltextdateien sehr lästig&mdash;und auch das
Kompilieren kann eine Weile dauern.</para>
<para>Eine Möglichkeit dies zu umgehen besteht in der
Verwendung von Objektdateien, wobei man nur die
Quelltextdateien neu kompiliert, die verändert wurden. So
könnten wir etwa folgendes erhalten:</para>
<screen>&prompt.user; <userinput>cc file1.o file2.o</userinput> &hellip; <userinput>file37.c</userinput> &hellip;</screen>
<para>falls wir seit dem letzten Kompiliervorgang nur die Datei
<filename>file37.c</filename> verändert haben. Dadurch
könnte der Kompiliervorgang um einiges beschleunigt
werden, es muß jedoch immer noch alles von Hand
eingegeben werden.</para>
<para>Oder wir könnten uns ein Shell Skript schreiben.
Dieses würde jedoch alles immer wieder neu kompilieren,
was bei einem großen Projekt sehr ineffizient
wäre.</para>
<para>Was ist, wenn wir hunderte von Quelltextdateien
hätten? Was ist, wenn wir in einem Team mit anderen
Leuten arbeiten würden, die vergessen uns Bescheid zu
sagen, falls sie eine der Quelltextdateien verändert
haben, die wir ebenfalls benutzen?</para>
<para>Vielleicht könnten wir beide Lösungen
kombinieren und etwas wie ein Shell Skript schreiben, welches
eine Art magische Regel enthalten würde, die feststellt,
welche Quelltextdateien neu kompiliert werden müssten.
Alles was wir bräuchten wäre ein Programm, das diese
Regeln verstehen könnte, da diese Aufgabe etwas zu
kompliziert für eine Shell ist.</para>
<para>Dieses Programm heißt <command>make</command>. Es
liest eine Datei namens <firstterm>makefile</firstterm>,
welche ihm sagt, wie unterschiedliche Dateien voneinander
abhängen, und berechnet, welche Dateien neu kompiliert
werden müssen und welche nicht. Zum Beispiel könnte
eine Regel etwas sagen wie <quote>wenn
<filename>fromboz.o</filename> älter als
<filename>fromboz.c</filename> ist, bedeutet dies, daß
jemand die Datei <filename>fromboz.c</filename> verändert
haben muß, und diese daher neu kompiliert werden
muß.</quote> Das makefile enthält außerdem
Regeln die make sagen, <emphasis>wie</emphasis> die
Quelltextdatei neu kompiliert werden muß, was dieses
Tool noch sehr viel mächtiger macht.</para>
<para>Makefiles werden normalerweise im selben Verzeichnis
wie die Quelltextdateien abgelegt, zu denen sie gehören,
und kann <filename>makefile</filename>,
<filename>Makefile</filename> oder
<filename>MAKEFILE</filename> heißen. Die meisten
Programmierer verwenden den Namen
<filename>Makefile</filename>, da diese Schreibweise
dafür sorgt, daß die Datei gut lesbar ganz oben in
der Verzeichnisliste aufgeführt wird.
<footnote>
<para>Verwenden Sie nicht <filename>MAKEFILE</filename> mit
lauter Großbuchstaben, da diese Schreibweise
häufig für Dokumentationsdateien wie
<filename>README</filename> benutzt wird.</para>
</footnote>
</para>
</sect2>
<sect2>
<title>Beispielhafte Verwendung von <command>make</command></title>
<para>Hier ist eine sehr einfache make Datei:</para>
<programlisting>foo: foo.c
cc -o foo foo.c</programlisting>
<para>Sie besteht aus zwei Zeilen, einer
Abhängigkeitszeile und einer Erzeugungszeile.</para>
<para>Die Abhängigkeitszeile hier besteht aus dem Namen
des Programms (auch <firstterm>Ziel</firstterm> genannt),
gefolgt von einem Doppelpunkt und einem Leerzeichen, und
anschließend dem Namen der Quelltextdatei. Wenn
<command>make</command> diese Zeile liest überprüft
es die Existenz von <filename>foo</filename>; falls diese
Datei existiert vergleicht es das Datum der letzten
Änderung von <filename>foo</filename> mit der von
<filename>foo.c</filename>. Falls <filename>foo</filename>
nicht existiert, oder älter als
<filename>foo.c</filename> ist, liest es die Erzeugungszeile
um herauszufinden, was zu tun ist. Mit anderen Worten, dies
ist die Regel die festlegt, wann <filename>foo.c</filename>
neu kompiliert werden muß.</para>
<para>Die Erzeugungszeile beginnt mit einem <token>tab</token>
(drücken Sie dazu die <keycap>tab</keycap>-Taste) gefolgt
von dem Befehl, mit dem Sie <filename>foo</filename> manuell
erzeugen würden. Wenn <filename>foo</filename> veraltet
ist, oder nicht existiert, führt <command>make</command>
diesen Befehl aus, um die Datei zu erzeugen. Mit anderen
Worten, dies ist die Regel die make sagt, wie
<filename>foo.c</filename> kompiliert werden muß.</para>
<para>Wenn Sie also <userinput>make</userinput> eingeben wird
dieses sicherstellen, daß <filename>foo</filename> bzgl.
Ihrer letzten Änderungen an <filename>foo.c</filename>
auf dem neuesten Stand ist. Dieses Prinzip kann auf
<filename>Makefile</filename>s mit hunderten von
Zielen&mdash;es ist bei FreeBSD praktisch möglich, das
gesamte Betriebssystem zu kompilieren, indem man nur
<userinput>make world</userinput> im richtigen Verzeichnis
eingibt!</para>
<para>Eine weitere nützliche Eigenschaft der makefiles
ist, daß die Ziele keine Programme sein müssen. Wir
könnten zum Beispiel eine make Datei haben, die wie folgt
aussieht:</para>
<programlisting>foo: foo.c
cc -o foo foo.c
install:
cp foo /home/me</programlisting>
<para>Wir können make sagen welches Ziel wir erzeugt haben
wollen, indem wir etwas wie folgt eingeben:</para>
<screen>&prompt.user; <userinput>make <replaceable>target</replaceable></userinput></screen>
<para><command>make</command> wird dann nur dieses Ziel
beachten und alle anderen ignorieren. Wenn wir zum Beispiel
<userinput>make foo</userinput> mit dem obigen makefile
eingeben, dann wird make das Ziel
<maketarget>install</maketarget> ignorieren.</para>
<para>Wenn wir nur <userinput>make</userinput> eingeben wird
make immer nur nach dem ersten Ziel suchen und danach mit dem
Suchen aufhören. Wenn wir hier also nur
<userinput>make</userinput> eingegeben hätten, würde
es nur zu dem Ziel <maketarget>foo</maketarget> gehen,
gegebenenfalls <filename>foo</filename> neu kompilieren, und
danach einfach aufhören, ohne das Ziel
<maketarget>install</maketarget> zu beachten.</para>
<para>Beachten Sie, daß das <maketarget>install</maketarget>-Ziel
von nichts anderem abhängt! Dies bedeutet, daß der
Befehl in der nachfolgenden Zeile immer ausgeführt wird,
wenn wir dieses Ziel mittels <userinput>make
install</userinput> aufrufen. In diesem Fall wird die Datei
<filename>foo</filename> in das Heimatverzeichnis des
Benutzers kopiert. Diese Vorgehensweise wird häufig bei
makefiles von Anwendungen benutzt, damit die Anwendung nach
erfolgreicher Kompilierung in das richtige Verzeichnis
installiert werden kann.</para>
<para>Dieser Teil ist etwas schwierig zu erklären. Wenn
Sie immer noch nicht so richtig verstanden haben, wie
<command>make</command> funktioniert, wäre es das Beste,
sie erstellen sich selber ein einfaches Programm wie
<quote>hello world</quote> und eine make Datei wie die weiter
oben angegebene, und experimentieren damit selber ein bißchen
herum. Als nächstes könnten Sie mehrere
Quelltextdateien verwenden, oder in Ihrer Quelltextdatei eine
Header-Datei includen. Der Befehl <command>touch</command> ist
an dieser Stelle ganz hilfreich&mdash;er verändert das
Datum einer Datei, ohne das Sie diese extra editieren
müssen.</para>
</sect2>
<sect2>
<title>Make und include-Dateien</title>
<para>C-Code beginnt häufig mit einer Liste von Dateien,
die included werden sollen, zum Beispiel stdio.h. Manche
dieser Dateien sind include-Dateien des Systems, andere
gehören zum aktuellen Projekt, an dem Sie gerade
arbeiten:</para>
<programlisting>#include &lt;stdio.h&gt;
#include "foo.h"
int main(....</programlisting>
<para>Um sicherzustellen, daß diese Datei neu kompiliert
wird, wenn <filename>foo.h</filename> verändert wurde,
müssen Sie diese Datei Ihrem
<filename>Makefile</filename> hinzufügen:</para>
<programlisting>foo: foo.c foo.h</programlisting>
<para>Sobald Ihr Projekt größer wird und Sie mehr
und mehr eigene include-Dateien verwalten müssen wird es
nur noch sehr schwer möglich sein, die Übersicht
über alle include-Dateien und Dateien, die von diesen
abhängen, beizubehalten. Falls Sie eine include-Datei
verändern, jedoch das erneute Kompilieren aller Dateien,
die von dieser Datei abhängen, vergessen, werden die
Folgen verheerend sein. Der <command>gcc</command> besitzt
eine Option, bei der er Ihre Dateien analysiert und eine Liste
aller include-Dateien und deren Abhängigkeiten erstellt:
<option>-MM</option>.</para>
<para>Wenn Sie das Folgende zu Ihrem Makefile
hinzufügen:</para>
<programlisting>depend:
gcc -E -MM *.c &gt; .depend</programlisting>
<para>und <userinput>make depend</userinput> ausführen,
wird die Datei <filename>.depend</filename> mit einer Liste
von Objekt-Dateien, C-Dateien und den include-Dateien
auftauchen:</para>
<programlisting>foo.o: foo.c foo.h</programlisting>
<para>Falls Sie <filename>foo.h</filename> verändern
werden beim nächsten Aufruf von <command>make</command>
alle Dateien, die von <filename>foo.h</filename>
abhängen, neu kompiliert.</para>
<para>Vergessen Sie nicht jedes mal
<command>make depend</command> aufzurufen, wenn Sie eine
include-Datei zu einer Ihrer Dateien hinzugefügt
haben.</para>
</sect2>
<sect2>
<title>FreeBSD Makefiles</title>
<para>Makefiles können eher schwierig zu schreiben sein.
Glücklicherweise kommen BSD-basierende Systeme wie
FreeBSD mit einigen sehr mächtigen solcher Dateien als
Teil des Systems daher. Ein sehr gutes Beispiel dafür ist
das FreeBSD Portssystem. Hier ist der grundlegende Teil eines
typischen <filename>Makefile</filename>s des
Portssystems:</para>
<programlisting>MASTER_SITES= ftp://freefall.cdrom.com/pub/FreeBSD/LOCAL_PORTS/
DISTFILES= scheme-microcode+dist-7.3-freebsd.tgz
.include &lt;bsd.port.mk&gt;</programlisting>
<para>Wenn wir jetzt in das Verzeichnis dieses Ports wechseln
und <userinput>make</userinput> aufrufen, passiert das
Folgende:</para>
<procedure>
<step>
<para>Es wird überprüft, ob sich der Quelltext
für diesen Port bereits auf Ihrem System
befindet.</para>
</step>
<step>
<para>Falls dies nicht der Fall ist wird eine
FTP-Verbindung zu der URL in <symbol>MASTER_SITES</symbol>
aufgebaut und der Quelltext heruntergeladen.</para>
</step>
<step>
<para>Die Checksumme für den Quelltext wird berechnet
und mit der schon bekannten und für sicher und gut
empfundenen verglichen. Damit wird sichergestellt,
daß der Quelltext bei der Übertragung nicht
beschädigt wurde.</para>
</step>
<step>
<para>Sämtliche Anpassungen, die nötig sind,
damit der Quelltext unter FreeBSD funktioniert, werden
vorgenommen&mdash;dieser Vorgang wird auch
<firstterm>patchen</firstterm> genannt.</para>
</step>
<step>
<para>Alle speziellen Konfigurationen, die am Quelltext
nötig sind, werden vorgenommen. (Viele &unix;
Programmdistributionen versuchen herauszufinden, auf
welcher &unix;-Version sie kompiliert werden sollen und
welche optionalen &unix;-Features vorhanden sind&mdash;an
dieser Stelle erhalten sie die Informationen im FreeBSD
Ports Szenario).</para>
</step>
<step>
<para>Der Quelltext für das Programm wird kompiliert.
Im Endeffekt wechseln wir in das Verzeichnis, in das der
Quelltext entpackt wurde, und rufen
<command>make</command> auf&mdash;die eigene make-Datei
des Programms besitzt die nötigen Informationen um
dieses zu bauen.</para>
</step>
<step>
<para>Wir haben jetzt eine kompilierte Version des
Programmes. Wenn wir wollen können wir dieses jetzt
testen; wenn wir überzeugt vom Programm sind,
können wir <userinput>make install</userinput>
eingeben. Dadurch werden das Programm sowie alle
zugehörigen Dateien an die richtige Stelle kopiert;
es wird auch ein Eintrag in der
<database>Paketdatenbank</database> erzeugt, sodaß
der Port sehr einfach wieder deinstalliert werden kann,
falls wir unsere Meinung über dieses geändert
haben.</para>
</step>
</procedure>
<para>Ich glaube jetzt werden Sie mit mir übereinstimmen,
daß dies ziemlich eindrucksvoll für ein Skript mit
vier Zeilen ist!</para>
<para>Das Geheimnis liegt in der letzten Zeile, die
<command>make</command> anweist, in das makefile des Systems
mit dem Namen <filename>bsd.port.mk</filename> zu sehen. Man
kann diese Zeile zwar leicht übersehen, aber hierher
kommt all das klevere Zeugs&mdash;jemand hat ein makefile
geschrieben, welches <command>make</command> anweist, alle
weiter oben beschriebenen Schritte durchzuführen (neben
vielen weiteren Dingen, die ich nicht angesprochen habe,
einschließlich der Behandlung sämtlicher Fehler,
die auftreten könnten) und jeder kann darauf
zurückgreifen, indem er eine einzige Zeile in seine
eigene make-Datei einfügt!</para>
<para>Falls Sie einen Blick in die makefiles des Systems werfen
möchten, finden Sie diese in
<filename>/usr/share/mk</filename>. Es ist aber wahrscheinlich
besser, wenn Sie damit noch warten, bis Sie ein bißchen mehr
Praxiserfahrung mit makefiles gesammelt haben, da die dortigen
makefiles sehr kompliziert sind (und wenn Sie sich diese
ansehen sollten Sie besser eine Kanne starken Kaffee
griffbereit haben!)</para>
</sect2>
<sect2>
<title>Fortgeschrittene Verwendung von
<command>make</command></title>
<para><command>Make</command> ist ein sehr mächtiges
Werkzeug und kann noch sehr viel mehr als die gezeigten
einfachen Beispiele weiter oben. Bedauerlicherweise gibt es
mehrere verschiedene Versionen von <command>make</command>,
und sie alle unterscheiden sich beträchtlich voneinander.
Der beste Weg herauszufinden was sie können ist
wahrscheinlich deren Dokumentation zu lesen&mdash;hoffentlich
hat diese Einführung Ihnen genügend Grundkenntnisse
vermitteln können, damit Sie dies tun können.</para>
<para>Die Version von make, die in FreeBSD enthalten ist, ist
<application>Berkeley make</application>; es gibt eine
Anleitung dazu in
<filename>/usr/share/doc/psd/12.make</filename>. Um sich diese
anzusehen, müssen Sie</para>
<screen>&prompt.user; <userinput>zmore paper.ascii.gz</userinput></screen>
<para>in diesem Verzeichnis ausführen.</para>
<para>Viele Anwendungen in den Ports verwenden
<application>GNU make</application>, welches einen sehr guten
Satz an <quote>info</quote>-Seiten mitbringt. Falls Sie
irgendeinen dieser Ports installiert haben wurde
<application>GNU make</application> automatisch als
<command>gmake</command> mit installiert. Es ist auch als
eigenständiger Port und Paket verfügbar.</para>
<para>Um sich die Info-Seiten für
<application>GNU make</application> anzusehen müssen Sie
die Datei <filename>dir</filename> in
<filename>/usr/local/info</filename> um einen entsprechenden
Eintrag erweitern. Dies beinhaltet das Einfügen einer
Zeile wie</para>
<programlisting> * Make: (make). The GNU Make utility.</programlisting>
<para>in die Datei. Nachdem Sie dies getan haben können
Sie <userinput>info</userinput> eingeben und dann den
Menüeintrag <guimenuitem>make</guimenuitem>
auswählen (oder Sie können in
<application>Emacs</application> die Tastenkombination
<userinput>C-h i</userinput> verwenden).</para>
</sect2>
</sect1>
<sect1 id="debugging">
<title>Debuggen</title>
<sect2>
<title>Der Debugger</title>
<para>Der Debugger bei FreeBSD heißt
<command>gdb</command> (<application>GNU
debugger</application>). Sie können Ihn durch die Eingabe
von</para>
<screen>&prompt.user; <userinput>gdb <replaceable>progname</replaceable></userinput></screen>
<para>starten, wobei viele Leute ihn vorzugsweise
innerhalb von <application>Emacs</application> aufrufen. Sie
erreichen dies durch die Eingabe von:</para>
<screen><userinput>M-x gdb RET <replaceable>progname</replaceable> RET</userinput></screen>
<para>Die Verwendung eines Debuggers erlaubt Ihnen Ihr
Programm unter kontrollierteren Bedingungen ausführen zu
können. Typischerweise können Sie so Zeile für
Zeile durch Ihr Programm gehen, die Werte von Variablen
untersuchen, diese verändern, dem Debugger sagen er soll
das Programm bis zu einem bestimmten Punkt ausführen und
dann anhalten, und so weiter und so fort. Sie können
damit sogar ein schon laufendes Programm untersuchen, oder
eine Datei mit einem Kernspeicherabbild laden um
herauszufinden, warum das Programm abgestürzt ist. Es ist
sogar möglich damit den Kernel zu debuggen, wobei dies
etwas trickreicher als bei den Benutzeranwendungen ist, welche
wir in diesem Abschnitt behandeln werden.</para>
<para>Der <command>gdb</command> besitzt eine recht gute
Online-Hilfe, sowie einen Satz von Info-Seiten, weshalb sich
dieser Abschnitt auf ein paar grundlegende Befehle
beschränken wird.</para>
<para>Falls Sie den textbasierten Kommandozeilen-Stil
abstoßend finden gibt es ein graphisches Front-End
dafür (<filename
role="package">devel/xxgdb</filename>) in der Ports-Sammlung.</para>
<para>Dieser Abschnitt ist als Einführung in die
Verwendung des <command>gdb</command> gedacht und beinhaltet
nicht spezielle Themen wie das Debuggen des Kernels.</para>
</sect2>
<sect2>
<title>Ein Programm im Debugger ausführen</title>
<para>Sie müssen das Programm mit der Option
<option>-g</option> kompiliert haben um den
<command>gdb</command> effektiv einsetzen zu können. Es
geht auch ohne diese Option, allerdings werden Sie dann nur
den Namen der Funktion sehen, in der Sie sich gerade befinden,
anstatt direkt den zugehörigen Quelltext. Falls Sie eine
Meldung wie die folgende sehen:</para>
<screen>&hellip; (no debugging symbols found) &hellip;</screen>
<para>wenn der <command>gdb</command> gestartet wird, dann
wissen Sie, daß das Programm nicht mit der Option
<option>-g</option> kompiliert wurde.</para>
<para>Geben Sie in der Eingabeaufforderung des
<command>gdb</command> <userinput>break main</userinput> ein.
Dies weist den Debugger an, dass Sie nicht daran interessiert sind,
den einleitenden Schritten beim Programmstart zuzusehen und dass
am Anfang Ihres Codes die Ausführung beginnen soll. Geben Sie
nun <userinput>run</userinput> ein, um das Programm zu starten -
es wird starten und beim Aufruf von <function>main()</function> vom
Debugger angehalten werden. (Falls Sie sich jemals gewundert haben von
welcher Stelle <function>main()</function> aufgerufen wird, dann
wissen Sie es jetzt!).</para>
<para>Sie können nun Schritt für Schritt durch Ihr
Programm gehen, indem Sie <command>n</command> drücken.
Wenn Sie zu einem Funktionsaufruf kommen können Sie diese
Funktion durch drücken von <command>s</command> betreten.
Sobald Sie sich in einem Funktionsaufruf befinden können
Sie diesen durch drücken von <command>f</command> wieder
verlassen. Sie können auch <command>up</command> und
<command>down</command> verwenden, um sich schnell den
Aufrufer einer Funktion anzusehen.</para>
<para>Hier ist ein einfaches Beispiel, wie man mit Hilfe des
<command>gdb</command> einen Fehler in einem Programm findet.
Dies ist unser eigenes Programm (mit einem absichtlich
eingebauten Fehler):</para>
<programlisting>#include &lt;stdio.h&gt;
int bazz(int anint);
main() {
int i;
printf("This is my program\n");
bazz(i);
return 0;
}
int bazz(int anint) {
printf("You gave me %d\n", anint);
return anint;
}</programlisting>
<para>Dieses Programm setzt <symbol>i</symbol> auf den Wert
<literal>5</literal> und übergibt dies einer Funktion
<function>bazz()</function>, welche den Wert ausgibt, den Sie
von uns erhalten hat.</para>
<para>Wenn wir das Programm kompilieren und ausführen
erhalten wir</para>
<screen>&prompt.user; <userinput>cc -g -o temp temp.c</userinput>
&prompt.user; <userinput>./temp</userinput>
This is my program
anint = 4231</screen>
<para>Das ist nicht was wir erwartet hatten! Es ist Zeit,
daß wir sehen was hier passiert!</para>
<screen>&prompt.user; <userinput>gdb temp</userinput>
GDB is free software and you are welcome to distribute copies of it
under certain conditions; type "show copying" to see the conditions.
There is absolutely no warranty for GDB; type "show warranty" for details.
GDB 4.13 (i386-unknown-freebsd), Copyright 1994 Free Software Foundation, Inc.
(gdb) <userinput>break main</userinput> <lineannotation>Skip the set-up code</lineannotation>
Breakpoint 1 at 0x160f: file temp.c, line 9. <lineannotation><command>gdb</command> puts breakpoint at <function>main()</function></lineannotation>
(gdb) <userinput>run</userinput> <lineannotation>Run as far as <function>main()</function></lineannotation>
Starting program: /home/james/tmp/temp <lineannotation>Program starts running</lineannotation>
Breakpoint 1, main () at temp.c:9 <lineannotation><command>gdb</command> stops at <function>main()</function></lineannotation>
(gdb) <userinput>n</userinput> <lineannotation>Go to next line</lineannotation>
This is my program <lineannotation>Program prints out</lineannotation>
(gdb) <userinput>s</userinput> <lineannotation>step into <function>bazz()</function></lineannotation>
bazz (anint=4231) at temp.c:17 <lineannotation><command>gdb</command> displays stack frame</lineannotation>
(gdb)</screen>
<para>Halt mal! Wieso hat denn <symbol>anint</symbol> den Wert
<literal>4231</literal>? Haben wir dieser Variablen nicht in
<function>main()</function> den Wert <literal>5</literal>
zugewiesen? Gehen wir mal zurück zu
<function>main()</function> und schauen dort nach.</para>
<screen>(gdb) <userinput>up</userinput> <lineannotation>Move up call stack</lineannotation>
#1 0x1625 in main () at temp.c:11 <lineannotation><command>gdb</command> displays stack frame</lineannotation>
(gdb) <userinput>p i</userinput> <lineannotation>Show us the value of <symbol>i</symbol></lineannotation>
$1 = 4231 <lineannotation><command>gdb</command> displays <literal>4231</literal></lineannotation></screen>
<para>Oh! Anscheinend haben wir vergessen <symbol>i</symbol> zu
initialisieren. Wir wollten eigentlich</para>
<programlisting><lineannotation>&hellip;</lineannotation>
main() {
int i;
i = 5;
printf("This is my program\n");
<lineannotation>&hellip;</lineannotation></programlisting>
<para>schreiben, haben aber die Zeile mit
<literal>i=5;</literal> vergessen. Da wir <symbol>i</symbol>
nicht initialisiert haben hatte diese Variable gerade den
Wert, der in dem ihr zugewiesenen Speicherbereich stand als
wir das Programm gestartet haben, welcher in diesem Fall
<literal>4231</literal> war.</para>
<note>
<para>Der <command>gdb</command> zeigt jedes mal, wenn wir
eine Funktion betreten oder verlassen, den Inhalt des
Stack-Rahmens an, selbst wenn wir uns mit
<command>up</command> und <command>down</command> im
Aufruf-Stack umher bewegen. Dabei wird der Name der Funktion
sowie der übergebenen Argumente angezeigt, was uns
dabei hilft, die Übersicht zu behalten. (Der Stack ist
ein Speicherbereich, in dem ein Programm Informationen
über die an eine Funktion übergebenen Argumente
ablegt, sowie die Rücksprungadresse eines
Funktionsaufrufes).</para>
</note>
</sect2>
<sect2>
<title>Eine Kernspeicherdatei untersuchen</title>
<para>Eine Kernspeicherdatei ist im Prinzip eine Datei, die den
vollständigen Zustand eines Prozesses enthält, als
dieses abgestürzt ist. In <quote>den guten alten
Zeiten</quote> mußten Programmierer hexadezimale Listen
der Kernspeicherdatei ausdrucken und über
Maschinencodehandbüchern schwitzen, aber heutzutage ist
das Leben etwas einfacher geworden. Zufälligerweise wird
die Kernspeicherdatei unter FreeBSD und anderen
4.4BSD-Systemen
<filename><replaceable>progname</replaceable>.core</filename>
anstatt einfach nur <filename>core</filename> genannt, um
deutlich zu machen, zu welchem Programm eine Kernspeicherdatei
gehört.</para>
<para>Um eine Kernspeicherdatei zu untersuchen müssen Sie
den <command>gdb</command> wie gewohnt starten. An Stelle von
<command>break</command> oder <command>run</command>
müssen Sie das Folgende eingeben</para>
<screen>(gdb) <userinput>core <replaceable>progname</replaceable>.core</userinput></screen>
<para>Wenn Sie sich nicht in demselben Verzeichnis befinden wie
die Kernspeicherdatei müssen Sie zuerst <userinput>dir
/path/to/core/file</userinput> eingeben.</para>
<para>Sie sollten dann etwas wie folgt sehen:</para>
<screen>&prompt.user; <userinput>gdb a.out</userinput>
GDB is free software and you are welcome to distribute copies of it
under certain conditions; type "show copying" to see the conditions.
There is absolutely no warranty for GDB; type "show warranty" for details.
GDB 4.13 (i386-unknown-freebsd), Copyright 1994 Free Software Foundation, Inc.
(gdb) <userinput>core a.out.core</userinput>
Core was generated by `a.out'.
Program terminated with signal 11, Segmentation fault.
Cannot access memory at address 0x7020796d.
#0 0x164a in bazz (anint=0x5) at temp.c:17
(gdb)</screen>
<para>In diesem Fall hieß das Programm
<filename>a.out</filename>, weshalb die Kernspeicherdatei den
Namen <filename>a.out.core</filename> trägt. Wie wir
sehen können stürzte das Programm in einer Funktion
namens <function>bazz</function> ab, als es versuchte auf
einen Speicherbereich zuzugreifen, der dem Programm nicht zur
Verfügung stand.</para>
<para>Manchmal ist es ganz nützlich zu sehen, wie eine
Funktion aufgerufen wurde, da bei komplexen Programmen das
eigentliche Problem schon sehr viel weiter oben auf dem
Aufruf-Stack aufgetreten sein könnte. Der Befehl
<command>bt</command> veranlaßt den
<command>gdb</command> dazu, einen Backtrace des Aufruf-Stacks
auszugeben:</para>
<screen>(gdb) <userinput>bt</userinput>
#0 0x164a in bazz (anint=0x5) at temp.c:17
#1 0xefbfd888 in end ()
#2 0x162c in main () at temp.c:11
(gdb)</screen>
<para>Die Funktion <function>end()</function> wird aufgerufen,
wenn ein Programm abstürzt; in diesem Fall wurde die
Funktion <function>bazz()</function> aus der
<function>main()</function>-Funktion heraus aufgerufen.</para>
</sect2>
<sect2>
<title>Ein bereits laufendes Programm untersuchen</title>
<para>Eine der tollsten Features des <command>gdb</command>
ist die Möglichkeit, damit bereits laufende Programme zu
untersuchen. Dies bedeutet natürlich, daß Sie die
erforderlichen Rechte dafür besitzen. Ein häufig
auftretendes Problem ist das Untersuchen eines Programmes,
welches sich selber forkt. Vielleicht will man den Kindprozess
untersuchen, aber der Debugger erlaubt einem nur den Zugriff
auf den Elternprozess.</para>
<para>Was Sie an solch einer Stelle machen ist, Sie starten
einen weiteren <command>gdb</command>, ermitteln mit Hilfe von
<command>ps</command> die Prozess-ID des Kindprozesses, und
geben</para>
<screen>(gdb) <userinput>attach <replaceable>pid</replaceable></userinput></screen>
<para>im <command>gdb</command> ein, und können dann wie
üblich mit der Fehlersuche fortfahren.</para>
<para><quote>Das ist zwar alles sehr schön,</quote> werden
Sie jetzt vielleicht denken, <quote>aber in der Zeit, in der
ich diese Schritte durchführe, ist der Kindprozess schon
längst über alle Berge</quote>. Fürchtet euch
nicht, edler Leser, denn Ihr müßt wie folgt
vorgehen (freundlicherweise zur Verfügung gestellt von
den Info-Seite des <command>gdb</command>):</para>
<screen><lineannotation>&hellip;</lineannotation>
if ((pid = fork()) &lt; 0) /* _Always_ check this */
error();
else if (pid == 0) { /* child */
int PauseMode = 1;
while (PauseMode)
sleep(10); /* Wait until someone attaches to us */
<lineannotation>&hellip;</lineannotation>
} else { /* parent */
<lineannotation>&hellip;</lineannotation></screen>
<para>Alles was Sie jetzt noch tun müssen ist, sich an
den Kindprozess ranzuhängen, <symbol>PauseMode</symbol>
auf <literal>0</literal> zu setzen und auf den
<function>sleep()</function> Funktionsaufruf zu warten, um
zurückzukehren!</para>
</sect2>
</sect1>
<sect1 id="emacs">
<title>Emacs als Entwicklungsumgebung verwenden</title>
<sect2>
<title>Emacs</title>
<para>Leider werden &unix;-Systeme nicht mit einem
alles-was-du-jemals-brauchst-und-vieles-mehr-megapaket an
integrierten Entwicklungsumgebungen ausgestattet, die bei
anderen Systemen dabei sind.
<footnote>
<para>Es gibt jetzt einige mächtige und freie IDEs in
der Ports-Sammlung wie etwa KDevelop.</para>
</footnote>
Trotzdem ist es möglich, seine eigene
Entwicklungsumgebung aufzusetzen. Diese wird vielleicht nicht
so hübsch und integriert sein, aber dafür
können Sie sie Ihren eigenen Wünschen anpassen. Und
sie ist frei. Und Sie haben die Quelltexte davon.</para>
<para>Der Schlüssel zu all dem ist Emacs. Es gibt zwar ein
paar Leute die ihn hassen, es gibt jedoch auch viele die ihn
lieben. Falls Sie zu ersteren gehören befürchte ich,
daß dieser Abschnitt Ihnen wenig interessantes zu bieten
hat. Des weiteren benötigen Sie eine angemessene Menge an
freiem Speicher, um ihn zu benutzen&mdash;ich würde 8MB
für den Textmodus und 16MB unter X als absolutes Minimum
empfehlen, um eine halbwegs brauchbare Performance zu
erhalten.</para>
<para>Emacs ist im Prinzip ein extrem anpassbarer Editor&mdash;
in der Tat ist er so stark veränderbar, daß er eher
einem Betriebssystem als einem Editor gleicht! Viele
Entwickler und Systemadministratoren erledigen praktisch ihre
gesamte Arbeit aus Emacs heraus und beenden ihn nur, um sich
komplett auszuloggen.</para>
<para>Es ist nicht einmal möglich alles hier
zusammenzufassen, was man mit dem Emacs machen kann. Im
Folgenden werden einige Features aufgelistet, die für
einen Entwickler interessant sein könnten:</para>
<itemizedlist>
<listitem>
<para>Sehr mächtiger Editor, der suchen-und-ersetzen
mit Zeichenfolgen und regulären Ausdrücken
(Pattern) sowie das direkte Anspringen von Anfang/Ende von
Blockausdrücken erlaubt, etc, etc.</para>
</listitem>
<listitem>
<para>Pull-Down Menüs und eine Online-Hilfe.</para>
</listitem>
<listitem>
<para>Sprachunabhängige Syntaxhervorhebung und
automatische Einrückung.</para>
</listitem>
<listitem>
<para>Vollständig konfigurierbar.</para>
</listitem>
<listitem>
<para>Sie können Programme im Emacs kompilieren und
debuggen.</para>
</listitem>
<listitem>
<para>Bei Kompilationsfehlern können Sie direkt zu der
entsprechenden Zeile im Quelltext springen.</para>
</listitem>
<listitem>
<para>Benutzerfreundliches Front-End für das
<command>info</command>-Programm, um die GNU Hypertext
Dokumentation inklusive der Dokumentation des Emacs
selber.</para>
</listitem>
<listitem>
<para>Benutzerfreundliches Front-End für den
<command>gdb</command> um sich beim Verfolgen der
Programmanweisungen den zugehörigen Quelltext
anzeigen zu lassen.</para>
</listitem>
<listitem>
<para>Sie können E-Mails und News im Usenet lesen,
während ihr Programm kompiliert wird.</para>
</listitem>
</itemizedlist>
<para>Und zweifelsfrei viele weitere Punkte, die ich
übersehen habe.</para>
<para>Emacs kann unter &os; über den <filename
role="package">editors/emacs</filename> Port installiert werden.</para>
<para>Sobald er installiert ist starten Sie ihn, und geben
dann <userinput>C-h t</userinput> ein, um die Einführung
in Emacs zu lesen&mdash;d.h. Sie sollen bei gedrückter
<keycap>Strg</keycap>-Taste die <keycap>h</keycap>-Taste
drücken, beide wieder loslassen und anschließend
<keycap>t</keycap> drücken. (Alternativ können Sie
mit der Maus den Eintrag <guimenuitem>Emacs
Tutorial</guimenuitem> aus dem
<guimenu>Hilfe</guimenu>-Menü auswählen).</para>
<para>Obwohl der Emacs Menüs besitzt ist das Erlernen der
Tastaturkombinationen lohnenswert, da man beim Editieren sehr
viel schneller Tastenkombinationen eingeben kann, als die Maus
zu finden und mit dieser dann an der richtigen Stelle zu
klicken. Und wenn Sie sich mit erfahrenen Emacs-Benutzern
unterhalten werden Sie feststellen, daß diese
häufig nebenbei Ausdrücke wie <quote><literal>M-x
replace-s RET foo RET bar RET</literal></quote> verwenden,
weshalb das Erlernen dieser sehr nützlich ist. Und Emacs
hat auf jeden Fall weit mehr nützliche Funktionen als das
diese in der Menüleiste unterzubringen wären.</para>
<para>Zum Glück ist es sehr einfach die jeweiligen
Tastaturkombinationen herauszubekommen, da diese direkt neben
den Menüeinträgen stehen. Meine Empfehlung
wäre, den Menüeintrag für, sagen wir, das
Öffnen einer Datei zu verwenden, bis Sie die
Funktionsweise verstanden haben und sie mit dieser vertraut
sind, und es dann mit C-x C-f versuchen. Wenn Sie damit
zufrieden sind, gehen Sie zum nächsten
Menüeintrag.</para>
<para>Falls Sie sich nicht daran erinnern können, was eine
bestimmte Tastenkombination macht, wählen Sie
<guimenuitem>Describe Key</guimenuitem> aus dem
<guimenu>Hilfe</guimenu>-Menü aus und geben Sie die
Tastenkombination ein&mdash;Emacs sagt Ihnen dann was diese
macht. Sie können ebenfalls den Menüeintrag
<guimenuitem>Command Apropos</guimenuitem> verwenden, um alle
Befehle, die ein bestimmtes Wort enthalten, mit den
zugehörigen Tastenkombinationen aufgelistet zu
bekommen.</para>
<para>Übrigends bedeutet der Ausdruck weiter oben, bei
gedrückter <keysym>Meta</keysym>-Taste <keysym>x</keysym>
zu drücken, beide wieder loszulassen,
<userinput>replace-s</userinput> einzugeben (Kurzversion
für <literal>replace-string</literal>&mdash;ein weiteres
Feature des Emacs ist, daß Sie Befehle abkürzen
können), anschließend die
<keysym>return</keysym>-Taste zu drücken, dann
<userinput>foo</userinput> einzugeben (die Zeichenkette, die
Sie ersetzen möchten), dann wieder
<keysym>return</keysym>, dann die Leertaste zu drücken
(die Zeichenkette, mit der Sie <literal>foo</literal> ersetzen
möchten) und anschließend erneut
<keysym>return</keysym> zu drücken. Emacs wird dann die
gewünschte suchen-und-ersetzen-Operation
ausführen.</para>
<para>Wenn Sie sich fragen was in aller Welt die
<keysym>Meta</keysym>-Taste ist, das ist eine spezielle Taste
die viele &unix;-Workstations besitzen. Bedauerlicherweise
haben PCs keine solche Taste, und daher ist es
üblicherweise die <keycap>alt</keycap>-Taste (oder falls
Sie Pech haben die <keycap>Esc</keycap>-Taste).</para>
<para>Oh, und um den Emacs zu verlassen müssen sie
<command>C-x C-c</command> (das bedeutet, Sie müssen bei
gedrückter <keysym>Strg</keysym>-Taste zuerst
<keysym>x</keysym> und dann <keysym>c</keysym> drücken)
eingeben. Falls Sie noch irgendwelche ungespeicherten Dateien
offen haben wird Emacs Sie fragen ob Sie diese speichern
wollen. (Ignorieren Sie bitte die Stelle der Dokumentation, an
der gesagt wird, daß <command>C-z</command> der
übliche Weg ist, Emacs zu verlassen&mdash;dadurch wird
der Emacs in den Hintergrund geschaltet, was nur nützlich
ist, wenn Sie an einem System ohne virtuelle Terminals
arbeiten).</para>
</sect2>
<sect2>
<title>Emacs konfigurieren</title>
<para>Emacs kann viele wundervolle Dinge; manche dieser Dinge
sind schon eingebaut, andere müssen erst konfiguriert
werden.</para>
<para>Anstelle einer proprietären Macrosprache verwendet
der Emacs für die Konfiguration eine speziell für
Editoren angepaßte Version von Lisp, auch bekannt als
Emacs Lisp. Das Arbeiten mit Emacs Lisp kann sehr hilfreich
sein, wenn Sie darauf aufbauend etwas wie Common Lisp lernen
möchten. Emacs Lisp hat viele Features von Common Lisp
obwohl es beträchtlich kleiner ist (und daher auch
einfacher zu beherrschen).</para>
<para>Der beste Weg um Emacs Lisp zu erlernen besteht darin,
sich das <ulink
url="ftp://ftp.gnu.org/old-gnu/emacs/elisp-manual-19-2.4.tar.gz">Emacs
Tutorial</ulink> herunterzuladen.</para>
<para>Es ist jedoch keine Kenntnis von Lisp erforderlich, um
mit der Konfiguration von Emacs zu beginnen, da ich eine
beispielhafte <filename>.emacs</filename>-Datei hier
eingefügt habe, die für den Anfang ausreichen
sollte. Kopieren Sie diese einfach in Ihr Heimverzeichnis und
starten Sie den Emacs neu, falls dieser bereits läuft; er
wird die Befehle aus der Datei lesen und Ihnen (hoffentlich)
eine brauchbare Grundeinstellung bieten.</para>
</sect2>
<sect2>
<title>Eine beispielhafte <filename>.emacs</filename>-Datei</title>
<para>Bedauerlicherweise gibt es hier viel zu viel, um es im
Detail zu erklären; es gibt jedoch ein oder zwei Punkte,
die besonders erwähnenswert sind.</para>
<itemizedlist>
<listitem>
<para>Alles was mit einem <literal>;</literal> anfängt
ist ein Kommentar und wird von Emacs ignoriert.</para>
</listitem>
<listitem>
<para>In der ersten Zeile mit
<literal>-*-&nbsp;Emacs-Lisp&nbsp;-*-</literal> sorgt
dafür, daß wir die Datei
<filename>.emacs</filename> in Emacs selber editieren
können und uns damit alle tollen Features zum
Editieren von Emacs Lisp zur Verfügung stehen. Emacs
versucht dies normalerweise anhand des Dateinamens
auszumachen, was vielleicht bei
<filename>.emacs</filename> nicht funktionieren
könnte.</para>
</listitem>
<listitem>
<para>Die <keysym>Tab</keysym>-Taste ist in manchen Modi
an die Einrückungsfunktion gebunden, so daß
beim drücken dieser Taste die aktuelle Zeile
eingerückt wird. Wenn Sie ein
<token>tab</token>-Zeichen in einen Text, welchen auch
immer Sie dabei schreiben, einfügen wollen,
müssen Sie bei gedrückter
<keysym>Strg</keysym>-Taste die <keysym>Tab</keysym>-Taste
drücken.</para>
</listitem>
<listitem>
<para>Diese Datei unterstützt Syntax Highlighting
für C, C++, Perl, Lisp und Scheme, indem die Sprache
anhand des Dateinamens erraten wird.</para>
</listitem>
<listitem>
<para>Emacs hat bereits eine vordefinierte Funktion mit dem
Namen <function>next-error</function>. Diese erlaubt es
einem, in einem Fenster mit der Kompilierungsausgabe
mittels <command>M-n</command> von einem zum nächsten
Kompilierungsfehler zu springen; wir definieren eine
komplementäre Funktion
<function>previous-error</function>, die es uns erlaubt,
mittels <command>M-p</command> von einem zum vorherigen
Kompilierungsfehler zu springen. Das schönste Feature
von allen ist, daß mittels <command>C-c
C-c</command> die Quelltextdatei, in der der Fehler
aufgetreten ist, geöffnet und die betreffende Zeile
direkt angesprungen wird.</para>
</listitem>
<listitem>
<para>Wir aktivieren die Möglichkeit von Emacs als
Server zu agieren, so daß wenn Sie etwas
außerhalb von Emacs machen und eine Datei editieren
möchten, Sie einfach das folgende eingeben
können</para>
<screen>&prompt.user; <userinput>emacsclient <replaceable>filename</replaceable></userinput>
</screen>
<para>und dann die Datei in Ihrem Emacs editieren
können!
<footnote>
<para>Viele Emacs-Benutzer setzen Ihre
<envar>EDITOR</envar>-Umgebungsvariable auf
<literal>emacsclient</literal>, so daß dies
immer passiert, wenn sie eine Datei editieren
müssen.</para>
</footnote>
</para>
</listitem>
</itemizedlist>
<example>
<title>Eine einfache <filename>.emacs</filename>-Datei</title>
<programlisting>;; -*-Emacs-Lisp-*-
;; This file is designed to be re-evaled; use the variable first-time
;; to avoid any problems with this.
(defvar first-time t
"Flag signifying this is the first time that .emacs has been evaled")
;; Meta
(global-set-key "\M- " 'set-mark-command)
(global-set-key "\M-\C-h" 'backward-kill-word)
(global-set-key "\M-\C-r" 'query-replace)
(global-set-key "\M-r" 'replace-string)
(global-set-key "\M-g" 'goto-line)
(global-set-key "\M-h" 'help-command)
;; Function keys
(global-set-key [f1] 'manual-entry)
(global-set-key [f2] 'info)
(global-set-key [f3] 'repeat-complex-command)
(global-set-key [f4] 'advertised-undo)
(global-set-key [f5] 'eval-current-buffer)
(global-set-key [f6] 'buffer-menu)
(global-set-key [f7] 'other-window)
(global-set-key [f8] 'find-file)
(global-set-key [f9] 'save-buffer)
(global-set-key [f10] 'next-error)
(global-set-key [f11] 'compile)
(global-set-key [f12] 'grep)
(global-set-key [C-f1] 'compile)
(global-set-key [C-f2] 'grep)
(global-set-key [C-f3] 'next-error)
(global-set-key [C-f4] 'previous-error)
(global-set-key [C-f5] 'display-faces)
(global-set-key [C-f8] 'dired)
(global-set-key [C-f10] 'kill-compilation)
;; Keypad bindings
(global-set-key [up] "\C-p")
(global-set-key [down] "\C-n")
(global-set-key [left] "\C-b")
(global-set-key [right] "\C-f")
(global-set-key [home] "\C-a")
(global-set-key [end] "\C-e")
(global-set-key [prior] "\M-v")
(global-set-key [next] "\C-v")
(global-set-key [C-up] "\M-\C-b")
(global-set-key [C-down] "\M-\C-f")
(global-set-key [C-left] "\M-b")
(global-set-key [C-right] "\M-f")
(global-set-key [C-home] "\M-&lt;")
(global-set-key [C-end] "\M-&gt;")
(global-set-key [C-prior] "\M-&lt;")
(global-set-key [C-next] "\M-&gt;")
;; Mouse
(global-set-key [mouse-3] 'imenu)
;; Misc
(global-set-key [C-tab] "\C-q\t") ; Control tab quotes a tab.
(setq backup-by-copying-when-mismatch t)
;; Treat 'y' or &lt;CR&gt; as yes, 'n' as no.
(fset 'yes-or-no-p 'y-or-n-p)
(define-key query-replace-map [return] 'act)
(define-key query-replace-map [?\C-m] 'act)
;; Load packages
(require 'desktop)
(require 'tar-mode)
;; Pretty diff mode
(autoload 'ediff-buffers "ediff" "Intelligent Emacs interface to diff" t)
(autoload 'ediff-files "ediff" "Intelligent Emacs interface to diff" t)
(autoload 'ediff-files-remote "ediff"
"Intelligent Emacs interface to diff")
(if first-time
(setq auto-mode-alist
(append '(("\\.cpp$" . c++-mode)
("\\.hpp$" . c++-mode)
("\\.lsp$" . lisp-mode)
("\\.scm$" . scheme-mode)
("\\.pl$" . perl-mode)
) auto-mode-alist)))
;; Auto font lock mode
(defvar font-lock-auto-mode-list
(list 'c-mode 'c++-mode 'c++-c-mode 'emacs-lisp-mode 'lisp-mode 'perl-mode 'scheme-mode)
"List of modes to always start in font-lock-mode")
(defvar font-lock-mode-keyword-alist
'((c++-c-mode . c-font-lock-keywords)
(perl-mode . perl-font-lock-keywords))
"Associations between modes and keywords")
(defun font-lock-auto-mode-select ()
"Automatically select font-lock-mode if the current major mode is in font-lock-auto-mode-list"
(if (memq major-mode font-lock-auto-mode-list)
(progn
(font-lock-mode t))
)
)
(global-set-key [M-f1] 'font-lock-fontify-buffer)
;; New dabbrev stuff
;(require 'new-dabbrev)
(setq dabbrev-always-check-other-buffers t)
(setq dabbrev-abbrev-char-regexp "\\sw\\|\\s_")
(add-hook 'emacs-lisp-mode-hook
'(lambda ()
(set (make-local-variable 'dabbrev-case-fold-search) nil)
(set (make-local-variable 'dabbrev-case-replace) nil)))
(add-hook 'c-mode-hook
'(lambda ()
(set (make-local-variable 'dabbrev-case-fold-search) nil)
(set (make-local-variable 'dabbrev-case-replace) nil)))
(add-hook 'text-mode-hook
'(lambda ()
(set (make-local-variable 'dabbrev-case-fold-search) t)
(set (make-local-variable 'dabbrev-case-replace) t)))
;; C++ and C mode...
(defun my-c++-mode-hook ()
(setq tab-width 4)
(define-key c++-mode-map "\C-m" 'reindent-then-newline-and-indent)
(define-key c++-mode-map "\C-ce" 'c-comment-edit)
(setq c++-auto-hungry-initial-state 'none)
(setq c++-delete-function 'backward-delete-char)
(setq c++-tab-always-indent t)
(setq c-indent-level 4)
(setq c-continued-statement-offset 4)
(setq c++-empty-arglist-indent 4))
(defun my-c-mode-hook ()
(setq tab-width 4)
(define-key c-mode-map "\C-m" 'reindent-then-newline-and-indent)
(define-key c-mode-map "\C-ce" 'c-comment-edit)
(setq c-auto-hungry-initial-state 'none)
(setq c-delete-function 'backward-delete-char)
(setq c-tab-always-indent t)
;; BSD-ish indentation style
(setq c-indent-level 4)
(setq c-continued-statement-offset 4)
(setq c-brace-offset -4)
(setq c-argdecl-indent 0)
(setq c-label-offset -4))
;; Perl mode
(defun my-perl-mode-hook ()
(setq tab-width 4)
(define-key c++-mode-map "\C-m" 'reindent-then-newline-and-indent)
(setq perl-indent-level 4)
(setq perl-continued-statement-offset 4))
;; Scheme mode...
(defun my-scheme-mode-hook ()
(define-key scheme-mode-map "\C-m" 'reindent-then-newline-and-indent))
;; Emacs-Lisp mode...
(defun my-lisp-mode-hook ()
(define-key lisp-mode-map "\C-m" 'reindent-then-newline-and-indent)
(define-key lisp-mode-map "\C-i" 'lisp-indent-line)
(define-key lisp-mode-map "\C-j" 'eval-print-last-sexp))
;; Add all of the hooks...
(add-hook 'c++-mode-hook 'my-c++-mode-hook)
(add-hook 'c-mode-hook 'my-c-mode-hook)
(add-hook 'scheme-mode-hook 'my-scheme-mode-hook)
(add-hook 'emacs-lisp-mode-hook 'my-lisp-mode-hook)
(add-hook 'lisp-mode-hook 'my-lisp-mode-hook)
(add-hook 'perl-mode-hook 'my-perl-mode-hook)
;; Complement to next-error
(defun previous-error (n)
"Visit previous compilation error message and corresponding source code."
(interactive "p")
(next-error (- n)))
;; Misc...
(transient-mark-mode 1)
(setq mark-even-if-inactive t)
(setq visible-bell nil)
(setq next-line-add-newlines nil)
(setq compile-command "make")
(setq suggest-key-bindings nil)
(put 'eval-expression 'disabled nil)
(put 'narrow-to-region 'disabled nil)
(put 'set-goal-column 'disabled nil)
(if (&gt;= emacs-major-version 21)
(setq show-trailing-whitespace t))
;; Elisp archive searching
(autoload 'format-lisp-code-directory "lispdir" nil t)
(autoload 'lisp-dir-apropos "lispdir" nil t)
(autoload 'lisp-dir-retrieve "lispdir" nil t)
(autoload 'lisp-dir-verify "lispdir" nil t)
;; Font lock mode
(defun my-make-face (face color &amp;optional bold)
"Create a face from a color and optionally make it bold"
(make-face face)
(copy-face 'default face)
(set-face-foreground face color)
(if bold (make-face-bold face))
)
(if (eq window-system 'x)
(progn
(my-make-face 'blue "blue")
(my-make-face 'red "red")
(my-make-face 'green "dark green")
(setq font-lock-comment-face 'blue)
(setq font-lock-string-face 'bold)
(setq font-lock-type-face 'bold)
(setq font-lock-keyword-face 'bold)
(setq font-lock-function-name-face 'red)
(setq font-lock-doc-string-face 'green)
(add-hook 'find-file-hooks 'font-lock-auto-mode-select)
(setq baud-rate 1000000)
(global-set-key "\C-cmm" 'menu-bar-mode)
(global-set-key "\C-cms" 'scroll-bar-mode)
(global-set-key [backspace] 'backward-delete-char)
; (global-set-key [delete] 'delete-char)
(standard-display-european t)
(load-library "iso-transl")))
;; X11 or PC using direct screen writes
(if window-system
(progn
;; (global-set-key [M-f1] 'hilit-repaint-command)
;; (global-set-key [M-f2] [?\C-u M-f1])
(setq hilit-mode-enable-list
'(not text-mode c-mode c++-mode emacs-lisp-mode lisp-mode
scheme-mode)
hilit-auto-highlight nil
hilit-auto-rehighlight 'visible
hilit-inhibit-hooks nil
hilit-inhibit-rebinding t)
(require 'hilit19)
(require 'paren))
(setq baud-rate 2400) ; For slow serial connections
)
;; TTY type terminal
(if (and (not window-system)
(not (equal system-type 'ms-dos)))
(progn
(if first-time
(progn
(keyboard-translate ?\C-h ?\C-?)
(keyboard-translate ?\C-? ?\C-h)))))
;; Under UNIX
(if (not (equal system-type 'ms-dos))
(progn
(if first-time
(server-start))))
;; Add any face changes here
(add-hook 'term-setup-hook 'my-term-setup-hook)
(defun my-term-setup-hook ()
(if (eq window-system 'pc)
(progn
;; (set-face-background 'default "red")
)))
;; Restore the "desktop" - do this as late as possible
(if first-time
(progn
(desktop-load-default)
(desktop-read)))
;; Indicate that this file has been read at least once
(setq first-time nil)
;; No need to debug anything now
(setq debug-on-error nil)
;; All done
(message "All done, %s%s" (user-login-name) ".")
</programlisting>
</example>
</sect2>
<sect2>
<title>Erweitern des von Emacs unterstützten Sprachbereichs</title>
<para>Das ist jetzt alles sehr schön wenn Sie
ausschließlich in einer der Sprachen programmieren
wollen, um die wir uns bereits in der
<filename>.emacs</filename>-Datei gekümmert haben (C,
C++, Perl, Lisp und Scheme), aber was passiert wenn eine neue
Sprache namens <quote>whizbang</quote> herauskommt, mit jeder
Menge neuen tollen Features?</para>
<para>Als erstes muß festgestellt werden, ob whizbang mit
irgendwelchen Dateien daherkommt, die Emacs etwas über
die Sprache sagen. Diese enden üblicherweise auf
<filename>.el</filename>, der Kurzform für <quote>Emacs
Lisp</quote>. Falls whizbang zum Beispiel ein FreeBSD Port
ist, könnten wir diese Dateien mittels</para>
<screen>&prompt.user; <userinput>find /usr/ports/lang/whizbang -name "*.el" -print</userinput></screen>
<para>finden und durch Kopieren in das Emacs-seitige
Lisp-Verzeichnis installieren. Unter &os; ist dies
<filename>/usr/local/share/emacs/site-lisp</filename>.</para>
<para>Wenn zum Beispiel die Ausgabe des find-Befehls wie folgt
war</para>
<screen>/usr/ports/lang/whizbang/work/misc/whizbang.el</screen>
<para>könnten wir das folgende tun</para>
<screen>&prompt.root; <userinput>cp /usr/ports/lang/whizbang/work/misc/whizbang.el /usr/local/share/emacs/site-lisp</userinput></screen>
<para>Als nächstes müssen wir festlegen, welche
Dateiendung Quelltextdateien für whizbang haben. Lassen
Sie uns um der Argumente Willen annehmen, die Dateiendung sei
<filename>.wiz</filename>. Wir müssen dann einen Eintrag
unserer <filename>.emacs</filename>-Datei hinzufügen um
sicherzustellen, daß Emacs die Informationen in
<filename>whizbang.el</filename> auch verwenden kann.</para>
<para>Suchen Sie den <symbol>auto-mode-alist Eintrag</symbol>
in der <filename>.emacs</filename>-Datei und fügen Sie an
dieser Stelle eine Zeile wie folgt für whizbang
hinzu:</para>
<programlisting><lineannotation>&hellip;</lineannotation>
("\\.lsp$" . lisp-mode)
("\\.wiz$" . whizbang-mode)
("\\.scm$" . scheme-mode)
<lineannotation>&hellip;</lineannotation></programlisting>
<para>Dies bedeutet das Emacs automatisch in den
<function>whizbang-mode</function> wechseln wird, wenn Sie
eine Datei mit der Dateiendung <filename>.wiz</filename>
editieren.</para>
<para>Direkt darunter werden Sie den Eintrag
<symbol>font-lock-auto-mode-list</symbol> finden. Erweitern
Sie den <function>whizbang-mode</function> um diesen wie
folgt:</para>
<programlisting>;; Auto font lock mode
(defvar font-lock-auto-mode-list
(list 'c-mode 'c++-mode 'c++-c-mode 'emacs-lisp-mode 'whizbang-mode 'lisp-mode 'perl-mode 'scheme-mode)
"List of modes to always start in font-lock-mode")</programlisting>
<para>Dies bedeutet das Emacs immer
<function>font-lock-mode</function> (z.B. Syntax Highlighting)
aktiviert, wenn Sie eine <filename>.wiz</filename>-Datei
editieren.</para>
<para>Und das ist alles was benötigt wird. Falls es
weitere Dinge gibt, die automatisch beim Öffnen einer
<filename>.wiz</filename>-Datei ausgeführt werden sollen,
können Sie einen <function>whizbang-mode
hook</function>-Eintrag hinzufügen (für ein
einfaches Beispiel, welches <function>auto-indent</function>
hinzufügt, sehen Sie sich bitte
<function>my-scheme-mode-hook</function> an).</para>
</sect2>
</sect1>
<sect1 id="tools-reading">
<title>Weiterführende Literatur</title>
<para>Für Informationen zum Aufsetzen einer
Entwicklungsumgebung, um Fehlerbehebungen an FreeBSD selber
beizusteuern sehen Sie sich bitte &man.development.7; an.</para>
<itemizedlist>
<listitem>
<para>Brian Harvey and Matthew Wright
<emphasis>Simply Scheme</emphasis>
MIT 1994.<!-- <br> -->
ISBN 0-262-08226-8</para>
</listitem>
<listitem>
<para>Randall Schwartz
<emphasis>Learning Perl</emphasis>
O'Reilly 1993<!-- <br> -->
ISBN 1-56592-042-2</para>
</listitem>
<listitem>
<para>Patrick Henry Winston and Berthold Klaus Paul Horn
<emphasis>Lisp (3rd Edition)</emphasis>
Addison-Wesley 1989<!-- <br> -->
ISBN 0-201-08319-1</para>
</listitem>
<listitem>
<para>Brian W. Kernighan and Rob Pike
<emphasis>The Unix Programming Environment</emphasis>
Prentice-Hall 1984<!-- <br> -->
ISBN 0-13-937681-X</para>
</listitem>
<listitem>
<para>Brian W. Kernighan and Dennis M. Ritchie
<emphasis>The C Programming Language (2nd Edition)</emphasis>
Prentice-Hall 1988<!-- <br> -->
ISBN 0-13-110362-8</para>
</listitem>
<listitem>
<para>Bjarne Stroustrup
<emphasis>The C++ Programming Language</emphasis>
Addison-Wesley 1991<!-- <br> -->
ISBN 0-201-53992-6</para>
</listitem>
<listitem>
<para>W. Richard Stevens
<emphasis>Advanced Programming in the Unix Environment</emphasis>
Addison-Wesley 1992<!-- <br> -->
ISBN 0-201-56317-7</para>
</listitem>
<listitem>
<para>W. Richard Stevens
<emphasis>Unix Network Programming</emphasis>
Prentice-Hall 1990<!-- <br> -->
ISBN 0-13-949876-1</para>
</listitem>
</itemizedlist>
</sect1>
</chapter>

File Metadata

Mime Type
text/xml
Expires
Thu, Mar 13, 10:23 AM (1 d, 6 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17117802
Default Alt Text
chapter.sgml (95 KB)

Event Timeline