next up previous
Next: Cuncurrent Version System - Up: Make Previous: Introduzione

Utilizzo

Make mette a disposizione una serie molto complesse di opzioni e di regole standard predefinite e sottintese, che permettono una gestione estremamente rapida e concisa di progetti anche molto complessi; per questo piuttosto che fare una replica del manuale preferisco commentare un esempio di makefile, quello usato per ricompilare i programmi di analisi dei dati dei test su fascio del tracciatore di Pamela.


#----------------------------------------------------------------------
#
# Makefile for a Linux System:
# use GNU FORTRAN compiler g77
# Makefile done for tracker test data
#
#----------------------------------------------------------------------
# Fortran flags
FC=g77
FFLAGS= -fvxt -fno-automatic -Wall -O6 -DPC # -DDEBUG
CC=gcc
CFLAGS= -Wall -O6
CFLADJ=-c #-DDEBUG
#
# FC            Fortran compiler for standard rules
# FFLAGS        Fortran flags for standard rules
# CC            C Compiler for standard rules
# CFLAGS        C compiler flags for standard rules 
LIBS=  -L/cern/pro/lib -lkernlib -lpacklib -lgraflib -lmathlib
OBJ=cnoise.o fit2.o pedsig.o loop.o badstrp.o cutcn.o readevnt.o \
erasepedvar.o readinit.o dumpval.o writeinit.o

riduzione: riduzione.F $(OBJ) commondef.f readfile.o
        $(FC) $(FFLAGS) -o riduzione riduzione.F readfile.o $(OBJ) $(LIBS) 

readfile.o: readfile.c
        $(CC) $(CFLAGS) -o readfile.o readfile.c

$(OBJ): commondef.f

.PHONY : clean
clean:
        rm -f *.o 
        rm -f *~
        rm -f riduzione
        rm -f *.rz
        rm -f output

Anzitutto i commenti, ogni linea che inizia con un # è un commento e non viene presa in considerazione.

Con make possono essere definite delle variabili, da potersi riusare a piacimento, per leggibilità si tende a definirle tutte maiuscole, nell'esempio ne sono definite varie:


FC=g77
FFLAGS= -fvxt -fno-automatic -Wall -O6 -DPC # -DDEBUG
CC=gcc
CFLAGS= -Wall -O6
CFLADJ=-c #-DDEBUG
...
LIBS=  -L/cern/pro/lib -lkernlib -lpacklib -lgraflib -lmathlib
OBJ=cnoise.o fit2.o pedsig.o loop.o badstrp.o cutcn.o readevnt.o \
La sintassi è NOME=, alcuni nomi però hanno un significato speciale (nel caso FC, FLAGS, CC, CFLAGS) in quanto sono usati da make nelle cosiddette regole implicite (su cui torneremo dopo).

Nel caso specifico, vedi anche i commenti, abbiamo definito i comandi di compilazione da usare per il C e il Fortran, e i rispettivi flag, una variabile che contiene il path e la lista delle librerie del CERN e una variabile con una lista di file oggetto.

Per richiamare una variabile si usa la sintassi $(NOME), ad esempio nel makefile abbiamo usato:


        $(FC) $(FFLAGS) -o riduzione riduzione.F readfile.o $(OBJ) $(LIBS)
e questo significa che la regola verrà trattata come se avessimo scritto esplicitamente i valori delle variabili.

Veniamo ora alla parte principale del makefile che esegue la costruzione del programma:


riduzione: riduzione.F $(OBJ) commondef.f readfile.o
        $(FC) $(FFLAGS) -o riduzione riduzione.F readfile.o $(OBJ) $(LIBS) 
readfile.o: readfile.c
        $(CC) $(CFLAGS) -o readfile.o readfile.c
$(OBJ): commondef.f

Il primo bersaglio del makefile, che definisce il bersaglio di default, è il programma di riduzione dei dati; esso dipende dal suo sorgente da tutti gli oggetti definiti dalla variabile OBJ, dal file di definizioni commondef.f e dalla routine C readfile.o; si noti il .F del sorgente, che significa che il file prima di essere compilato viene fatto passare attraverso il preprocessore C (cosa che non avviene per i .f) che permette di usare i comandi di compilazione condizionale del preprocessore C con la relativa sintassi. Sotto segue il comando di compilazione che sfrutta le variabili definite in precedenza per specificare quale compilatore e flags usare e specifica di nuovo gli oggetti e le librerie.

Il secondo bersaglio definisce le regole per la compilazione della routine in C; essa dipende solo dal suo sorgente. Si noti che per la compilazione vengono usate le variabili relative al compilatore C. Si noti anche che se questa regola viene usata, allora lo sarà anche la precedente, dato che riduzione dipende da readfile.o.

Il terzo bersaglio è apparentemente incomprensibile dato che vi compare solo il riferimento alla variabile OBJ con una sola dipendenza e nessuna regola, essa però mostra le possibilità (oltre che la complessità) di make connesse alla presenza di quelle regole implicite a cui avevamo accennato.

Anzitutto una una peculiarità di make è che si possono anche usare più bersagli per una stessa regola (nell'esempio quelli contenuti nella variabile OBJ che viene espansa in una lista); in questo caso la regola di costruzione sarà applicata a ciascuno che si potrà citare nella regola stessa facendo riferimento con la variabile automatica: $@. L'esempio usato per la nostra costruzione però sembra non avere neanche la regola di costruzione.

Questa mancanza sia di regola che di dipendenze (ad esempio dai vari sorgenti) illustra le capacità di funzionamento automatico di make. Infatti è facile immaginarsi che un oggetto dipenda da un sorgente, e che per ottenere l'oggetto si debba compilare quest'ultimo.

Make sa tutto questo per cui quando un bersaglio è un oggetto (cioé ha un nome tipo qualcosa.o) non è necessario specificare il sorgente, ma il programma lo va a cercare nella directory corrente (ma è possibile pure dirgli di cercarlo altrove, vedi il manuale). Nel caso specifico allora si è messo come dipendenza solo il file delle definizioni che viene incluso in ogni subroutine. Inoltre come dicevamo in genere per costruire un oggetto si deve compilarne il sorgente; make sa anche questo e sulla base dell'estenzione del sorgente trovato (che nel caso sarà un qualcosa.f) applica la regola implicita. In questo caso la regola è quella di chiamare il compilatore fortran applicato al file oggetto e al relativo sorgente, questo viene fatto usando la variabile FC che è una delle variabili standard usata dalle regole implicite (come CC nel caso di file .c); per una maggiore flessibilità poi la regola standard usa anche la variabile FFLAGS per specificare, a scelta dell'utente che non ha che da definirla, quali flag di compilazione usare (nella documentazione sono riportate tutte le regole implicite e le relative variabili usate).

In questo modo è stato possibile usare una sola riga per indicare la serie di dipendenze e relative compilazioni delle singole subroutine; inoltre con l'uso della variabile OBJ l'aggiunta di una nuova eventuale routine nuova.f comporta solo l'aggiunta di nuova.o alla definizione di OBJ.


next up previous
Next: Cuncurrent Version System - Up: Make Previous: Introduzione
Simone Piccardi
2000-10-30