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> make clean rm -f *.o sum_f77 sum_c $shell> make gfortran -Wall -fimplicit-none -c dsum.f gfortran -Wall -fimplicit-none -c sumtest.f gfortran -Wall -fimplicit-none -o sum_f77 dsum.o sumtest.o gcc-4.8 -Wall -c new_dsum.c gfortran -Wall -fimplicit-none -o sum_c new_dsum.o sumtest.o $shell> make sum_f77 make: `sum_f77' is up to date. $shell> make clean rm -f *.o sum_f77 sum_c $shell> make sum_f77 gfortran -Wall -fimplicit-none -c dsum.f gfortran -Wall -fimplicit-none -c sumtest.f gfortran -Wall -fimplicit-none -o sum_f77 dsum.o sumtest.o $shell> make gcc-4.8 -Wall -c new_dsum.c gfortran -Wall -fimplicit-none -o sum_c new_dsum.o sumtest.o $shell> ./sum_f77 X = 1.0000000000000000 4.0000000000000000 9.0000000000000000 16.000000000000000 25.000000000000000 36.000000000000000 49.000000000000000 64.000000000000000 81.000000000000000 100.00000000000000 ALPHA = DSUM(10, X, 1) = 385.00000000000000 ALPHA = DSUM(5, X, 2) = 165.00000000000000 ALPHA = DSUM(5, X(2), 2) = 220.00000000000000 $shell> ./sum_c X = 1.0000000000000000 4.0000000000000000 9.0000000000000000 16.000000000000000 25.000000000000000 36.000000000000000 49.000000000000000 64.000000000000000 81.000000000000000 100.00000000000000 ALPHA = DSUM(10, X, 1) = 385.00000000000000 ALPHA = DSUM(5, X, 2) = 165.00000000000000 ALPHA = DSUM(5, X(2), 2) = 220.00000000000000
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:
FFLAGS += -Wall -fimplicit-none
CC = gcc-4.8
CFLAGS += -Wall
all: sum_f77 sum_c
sum_f77: dsum.o sumtest.o
$(FC) -o sum_f77 dsum.o sumtest.o
sum_c: new_dsum.o sumtest.o
$(CC) -o sum_c new_dsum.o sumtest.o
%.o : %.c
$(CC) $(CFLAGS) -c -o $@ $<
%.o : %.f
$(FC) $(FFLAGS) -c -o $@ $<
clean:
rm -f *.o sum_f77 sum_c
Interessant sind hier Zeilen in denen Variablen definiert (=) werden bzw. Werte an die Variable hinten angehängt werden (+=)
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:
$(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> make -f NewMakefile clean rm -f *.o sum_f77 sum_c $shell> make -f NewMakefile gfortran -Wall -fimplicit-none -c -o dsum.o dsum.f gfortran -Wall -fimplicit-none -c -o sumtest.o sumtest.f gfortran -o sum_f77 dsum.o sumtest.o gcc-4.8 -Wall -c -o new_dsum.o new_dsum.c gcc-4.8 -o sum_c new_dsum.o sumtest.o Undefined symbols for architecture x86_64: "__gfortran_set_args", referenced from: _main in sumtest.o "__gfortran_set_options", referenced from: _main in sumtest.o "__gfortran_st_write", referenced from: _MAIN__ in sumtest.o "__gfortran_st_write_done", referenced from: _MAIN__ in sumtest.o "__gfortran_transfer_array_write", referenced from: _MAIN__ in sumtest.o "__gfortran_transfer_character_write", referenced from: _MAIN__ in sumtest.o "__gfortran_transfer_real_write", referenced from: _MAIN__ in sumtest.o ld: symbol(s) not found for architecture x86_64 collect2: error: ld returned 1 exit status make: *** [sum_c] Error 1 $shell> make -f NewMakefile sum_f77 make: `sum_f77' is up to date. $shell> make -f NewMakefile clean rm -f *.o sum_f77 sum_c $shell> make -f NewMakefile sum_f77 gfortran -Wall -fimplicit-none -c -o dsum.o dsum.f gfortran -Wall -fimplicit-none -c -o sumtest.o sumtest.f gfortran -o sum_f77 dsum.o sumtest.o $shell> make -f NewMakefile gcc-4.8 -Wall -c -o new_dsum.o new_dsum.c gcc-4.8 -o sum_c new_dsum.o sumtest.o Undefined symbols for architecture x86_64: "__gfortran_set_args", referenced from: _main in sumtest.o "__gfortran_set_options", referenced from: _main in sumtest.o "__gfortran_st_write", referenced from: _MAIN__ in sumtest.o "__gfortran_st_write_done", referenced from: _MAIN__ in sumtest.o "__gfortran_transfer_array_write", referenced from: _MAIN__ in sumtest.o "__gfortran_transfer_character_write", referenced from: _MAIN__ in sumtest.o "__gfortran_transfer_real_write", referenced from: _MAIN__ in sumtest.o ld: symbol(s) not found for architecture x86_64 collect2: error: ld returned 1 exit status make: *** [sum_c] Error 1
Fragen/Aufgaben:
-
Dem Target clean wird oft das phony-tag .PHONY: clean vorangestellt. Was hat es damit auf sich? (google hilft)