Frühjahrsemester 2011 CS104 Programmieren II Teil II: C++ Programmierung Kapitel 9: Entwicklungsprozess in C++ H. Schuldt Entwicklung mit mehreren Dateien In C++ ist es üblich, den Quelltext in mehreren Dateien zu halten Jede Datei ist dabei ein entsprechendes Modul Es gibt dabei keine Relation zwischen dem Dateinamen und dem Inhalt der Datei main.cpp int add(int a, int b); int main(void) { int result, a=2, b=3; std::cout << add(a,b); return 0; } utils.cpp int add(int a, int b) { return a + b; } int sub(int a, int b) { return a - b; } 9-2 1
Kompilation unter Linux Der folgende Befehl führt den gesamten Kompilationsprozess durch: g++ -Wall -g file1.cpp file2.cpp -o progname Man kann auch einzelne Teilprozesse (Präprozessor, Kompilieren, Linken) einzeln durchführen: Nur Präprozessor g++ -E file.cpp Nur Kompilieren (ohne Linken) g++ -Wall -c file.cpp Alle Dateien linken g++ file1.o file2.o -o progname 9-3 Getrennte Übersetzung Präprozessor Ersetzt #define, #include Compiler Übersetzt den Quelltext in Machinencode Die Ausgabe ist eine Objekt-Datei. Dieser Binärcode ist nicht ausführbar Linker Nimmt alle Objekt-Dateien und löst alle Referenzen auf Funktionen, Klassen und Variablen in verschiedenen Dateien auf Source code (text, *.cpp) C/C++ code (text) Object code (binary, *.o) Native Executable (bin).cpp.h.cpp.h Preprocessor Compiler Linker executable Libraries 9-4 2
Präprozessor und Compiler Präprozessor Ersetzt alle #include-anweisungen und erzeugt C++ Text Versteht selbst kein C++ (bzw. C) Der erzeugte C++ Quelltext wird an den Compiler übergeben Compiler Erwartet C++ (bzw. C)-Quelltext (ohne Präprozessor-Anweisungen) Überprüft Syntax Generiert und optimiert Maschine-Code Erzeugt Objekt-Datei für den Linker Die Quelltext-Dateien und Zeilennummer sind immer noch bekannt 9-5 Die wichtigsten GNU G++ Compiler Optionen -Wall enable all warnings -ansi turn on strict ansi compliance -v verbose mode on (lists which directories were searched for include files/libraries) -g generate debugging symbols -c compile only (create object file) -E run the preprocessor only -s generate assembly code (instead of object code) -I<dir> prepend directory to include path -L<dir> prepend directory to library path -l<libname> library to link (looks for lib<libname>.so, or.a) in library path -o <filename> specifies output filename -O[n] specifies optimization level (default 0) -D<name>[=value] define the given preprocessor Tag Entwicklung Immer mit -Wall und -g: Produktion Immer mit -Wall und O3: g++ -Wall -g <filenames...> g++ -Wall O3 <filenames...> 9-6 3
Linker (Binder) Linker Löst alle Abhängigkeiten der Objekt Dateien (*.o) auf. Erzeugt das ausführbare Programm Macht keine Code-Optimierung Kennt keine Typen oder Variablen mehr Auflösung des Namens ist abhängig vom Compiler es ist also nicht garantiert, dass der Linker Objektdateien (*.o) von unterschiedlichen Compilern linken (binden) kann. 9-7 Librarys (Bibliotheken) Idee: bereits sorgfältig implementierte Software wieder verwenden Library: Menge aller vor-compilierten Sourcen (Funktionen, Klassen, Typen, ), zusammengefasst in einer Datei Ist kein lauffähiges Programm (enthält kein main) System-Library: Library, die in bestimmten, vordefinierten Verzeichnissen installiert ist Kommt typischerweise mit dem Betriebssystem Linux: /usr/lib Ein guter Programmierer kennt viele und die richtigen Librarys... 9-8 4
Librarys (Bibliotheken) Wie verwendet man System-Librarys? In der C++ Datei: Header-Datei includen Beispiel: #include <math.h> Linken einer übersetzen Bibliothek (Objektdatei) Konvention unter Linux: -lm linkt libm.so Beispiel Math-Library linken: g++ -o myprog file1.o file2.o lm 9-9 Objekt-Dateien Objekt-Dateien enthalten den kompilierten Quelltext und einen Index der definierten und nicht definierten Symbole nm (Linux) oder dumpbin (Windows) erzeugt diese Indexliste. Statisches Linken: Der Linker sucht in allen Objekt-Dateien nach entsprechenden Symbolen und führt eine Zuweisung zwischen definierten und nicht definierten Symbolen durch Dynamisches Linken.dll (Windows) and.so (Linux) Bibliotheken, die aus Objekt-Dateien bestehen und zur Laufzeit vom Betriebssystem eingebunden werden Endung einer Objekt-Datei:.o bzw..obj 9-10 5
Makefile Der Prozess des Kompilierens wird durch ein Makefile automatisiert. Ein Makefile führt eine Liste der Abhängigkeiten der einzelnen Quelltext-Dateien und liefert Direktiven und Befehle zum automatischen Kompilieren des Projektes. Body.o: Body.cpp, Body.h g++ -c -o Body.o Body.cpp test_body.o: test_body.cpp, Body.h, iostream g++ -c -o test_body.o test_body.cpp test: test.o, Body.o g++ -o test test.o Body.o Abhängigkeiten Compile Befehl Abhängigkeiten Compile Befehl Abhängigkeiten Link Befehl Das Erstellen und das Verwalten von Makefiles kann sehr aufwändig sein. Es gibt Werkzeuge zum automatischen Erzeugen von Makefile: TMake oder QMake 9-11 TMake TMake ist frei verfügbar unter: http://tmake.sourceforge.net/ to create and maintain makefiles for software projects. It can be a painful task to manage makefiles manually, especially if you develop for more than one platform or use more than one compiler. tmake automates and streamlines this process and lets you spend your valuable time on writing code, not makefiles. 9-12 6
test_body.pro HEADERS SOURCES TARGET TMake - Beispiel = Body.h = Body.cpp hello.cpp = test_body >: setenv TMAKEPATH /local/tmake/lib/linux-g++ >: setenv PATH $PATH:/local/tmake/bin >: tmake test_body.pro -o Makefile >: make g++ -c -pipe -Wall -W -O2 -o Body.o Body.cpp g++ -c -pipe -Wall -W -O2 -o hello.o hello.cpp rm -f test_body g++ -o test_body Body.o hello.o >: make clean rm -f Body.o hello.o test_body rm -f core *~ TMake: generiert automatisch ein Makefile die Anhängigkeiten zwischen den Dateien werden automatisch erkannt. 9-13 Dokumentation des C++ Codes Das Verwalten und Modifizieren von grossen C++ Paketen kann sehr komplex sein. Gute Dokumentation ist deshalb sehr wichtig. Doxygen ist ein Werkzeug zur Dokumentation von C++ Quelltexten vergleichbar zu javadoc. Doxygen ist frei verfügbar unter http://www.doxygen.org 9-14 7
Doxygen Beispiel einer Dokumentation einer Funktion /** Dokumentation of a function * @param lower lower bound of the range * @param upper upper bound of the range * @return A vector with the same size as this * vector and binary elements * @warning some detail.. * @todo... * @bug... **/ FVector findinrange(float lower, float upper) const; Doxygen analysiert die C++ Dateien und erzeugt html-dateien mit der entsprechenden Dokumentation. 9-15 Werkzeuge: Emacs Farbliche Hervorhebung der C++ Syntax Automatischer Texteinzug und C++ Formatierung Kontext- (sprach-) sensitive Hilfefunktion Automatisches Interface mit Ihrem Debugger (gdb) Tutorial: www.lib.uchicago.edu/keith/tcl-course/emacs-tutorial.html 9-16 8
Werkzeuge: Debugging Debugger := Tool zur Inspektion der Daten und des Ablaufs eines Programms zur Laufzeit Debugger braucht Debug-Infos im Executable daher: g++ -Wall -g program.cpp o program Aufruf gdb program ddd program (console) oder (GUI) Breakpoint := Haltepunkt: Ausführung des Programms bis dahin, danach wird die Kontrolle an den Benutzer weitergegeben 9-17 9