======== Makefile ======== Zuerst ein paar Bemerkungen zu `make` und makefiles: - Die Idee von `make` ist es Tipparbeit beim Übersetzen und Linken einzusparen. - Tippt man im Terminal lediglich `make` ein wird nach einer *Regeldatei* mit dem Namen `GNU-makefile`, `makefile` oder `Makefile` gesucht. Und zwar in dieser Reihenfolge. Der erste Treffer wird verwendet. Meist nennt man das makefile aber `Makefile`. - Mit `make -f mymakefile` kann man gezielt die Regeldatei `mymakefile` verwenden. - Ein makefile definiert verschiedene *Ziele (Targets)*, die dann von `make` erzeugt werden. Die Namen der Targets kann man im Prinzip frei wählen. Es gibt aber gewisse vordefinierte oder übliche Targets: - Der Aufruf `make` ist äquivalent zu `make all`. - Das Target `all` muss wie jedes andere definiert werden. Es ist also nicht so dass damit automatisch alle Targets gemeint sind. Mit `make` soll alles übersetzt und erzeugt werden was der Entwickler für primär sinnvoll und wichtig hält. Bei einer BLAS Implementierung wird das normalerweise die BLAS Implementierung sein. - Ein Target `clean` räumt auf. Das heisst alle Files, die beim übersetzen Erzeugt wurden werden wieder gelöscht (z.B. object files, executables). - Ein Target `check` könnte man definieren damit nach einem `make` eine Test Suite für die erzeugten Programme und Bibliotheken gestartet wird. - Ein Target `bench` könnte man zum Erzeugen von Benchmarks definieren Makefile in Aktion ================== Wir testen zunächst, ob das zuvor vorgestellte makefile tut was es soll: *--[SHELL(path=day05)]----------------------------------------------------* | | | make clean | | make | | make sum_f77 | | make clean | | make sum_f77 | | make | | ./sum_f77 | | ./sum_c | | | *-------------------------------------------------------------------------* Fragen/Aufgaben: - Überzeugt euch, dass ein Aufruf von `make` nur das übersetzt was neu übersetzt werden muss. - Wieso wird da bei `make clean` das `rm` mit Option `-f` aufgerufen? Verbessertes Makefile ===================== Das obige Makefile entstand dadurch, dass man das was sonst im Terminal eingetippt wurde einfach ins makefile geschrieben wurde. Wenn man nun aber neue Source Files hinzufügt, dann wird das makefile schnell unübersichtlicher. Zum Glück kann man die Regeln aber auch allgemeiner formulieren: :import: day05/NewMakefile Interessant sind hier Zeilen in denen Variablen definiert (`=`) werden bzw. Werte an die Variable hinten angehängt werden (`+=`) --- CODE(type=txt) -------------- FC = gfortran FFLAGS += -Wall -fimplicit-none --------------------------------- Und allgemeine Regeln wie zum Beispiel ein Object File `foo.o` aus einem Fortran Source File `foo.f` allgemein erzeugt werden soll: --- CODE(type=txt) -------------- %.o : %.f $(FC) $(FFLAGS) -c -o $@ $< --------------------------------- Dabei wird (siehe __gnu make__): - Im Muster der Regel `%` als Platzhalter für einen Basisnamen (z.B. `foo`) benutzt. - Mit `$@` das Ergebnis der Regel bezeichnet (z.B. `foo.o`). - Mit `$<` die Abhängigkeit der Regel bezeichnet (z.B. `foo.f`) - Die Regel wird ausgeführt, wenn die Datei `$<` neuer ist als `$@` oder `$@` gar nicht existiert. Ansonsten macht das Makefile das gleiche: *--[SHELL(path=day05)]----------------------------------------------------* | | | make -f NewMakefile clean | | make -f NewMakefile | | make -f NewMakefile sum_f77 | | make -f NewMakefile clean | | make -f NewMakefile sum_f77 | | make -f NewMakefile | | | *-------------------------------------------------------------------------* Fragen/Aufgaben: - Dem Target `clean` wird oft das phony-tag `.PHONY: clean` vorangestellt. Was hat es damit auf sich? (*google* hilft) :links: __gnu make__ -> http://www.gnu.org/software/make/ :navigate: __up__ -> doc:index __back__ -> doc:day05/page01