<- XML - Copertina - Impressioni su Linux -> |
Articolo
Come tutti i programmatori sanno, creare un programma eseguibile da più file sorgenti consiste nel compilare separatamente i file sorgenti uno ad uno e poi unirli nel file eseguibile finale. Ma quando i file sorgente sono molti, come si fa a far si che non diventi snervante il compilare? Semplicemente creando un file contente il compilatore da usare, in che modo usarlo, quali file compilare, come creare il file eseguibile (programma o libreria che esso sia) e altre cose sempre utili, come la directory dove trovare le librerie necessarie ed i file di include. Questo è il contenuto del file Makefile.
Creare un file Makefile è allo stesso tempo facile e difficile, il tutto dipende da cosa dovete fare. Per ora verrà descritto il metodo per creare un semplice file Makefile che consentirà di compilare il proprio programma. Ad esempio quello che segue è un mio file Makefile.
#Makefile del programma XLOAD VERSION = 0.8 CC = gcc VERSIONGTK = 0.99.0 SRCDIRGTK = /src/ #OPTIMIZE = -g -Wall OPTIMIZE = -O3 -s -fomit-frame-pointer CFLAGS = $(DEFINES) $(OPTIMIZE) LFLAGS = -lgtk -lgdk -lglib -lm PROGS = zb_xload PROGS_O = main.o LIBS = all: objs progs progs : $(CC) $(CFLAGS) $(LFLAGS) -o $(PROGS) $(PROGS_O) $(LIBS) objs: $(PROGS_O) .c.o: $(CC) $(CFLAGS) -c -o $*.o $< .c.s: $(CC) $(CFLAGS) -S -o $*.s $< .o: $(CC) $(CFLAGS) $(LFLAGS) -o $* $(PROGS_O) $(LIBS) #chmod a+rs,go-w $* testaccel: testaccel.o $(CC) $(CFLAGS) $(LFLAGS) -o testaccel testaccel.o $(LIBS) -lm chmod a+rs,go-w testaccel clean : cleanbin rm -f *.o *~ cleanbin : rm -f $(PROGS) dep : rm -f .depend make .depend tar: tar czvf zb_xload.tgz Makefile main.c README TODO # DO NOT DELETE
Ma vediamo nel dettaglio come è composto il Makefile.
La prima riga è
#Makefile del programma XLOAD
Come si può ben capire il simbolo # denota l'inizio di un commento, commento che non si può protrarre su più linee. Per creare un commento di più linee bisogna iniziare ogni linea con il simbolo #.
Ad esempio:
#Prima linea del commento. #Seconda linea. comando #inizio commento sulla terza riga #Terzo commento
La seguente linea definisce quale è il compilatore da usare.
CC = gcc
Logicamente il gcc sarà sostituito da g++ se si compila in C++. Definire il compilatore da usare rende più facile la compilazione di sorgenti situati sotto directory diverse, poiché da un Makefile se ne può chiamare (ed eseguire) un altro passandogli alcuni valori (decisi dall'utente) come il compilatore da usare. Questo è utile specialmente se vogliamo portare un programma da Linux (dove si usa il gcc) a Irix (che usa il cc).
Le 14 righe successive definiscono alcune cose come le librerie da usare o i flag da passare al compilatore. Logicamente queste informazioni variano da programma a programma e anche il modo di chiamare le definizioni possono variare.
Delle definzioni è utile spiegare la seguente linea:
CFLAGS = $(DEFINES) $(OPTIMIZE)
In questo modo la variabile CFLAGS viene istanziata con il contenuto della variabile DEFINES e e della variabile OPTIMIZE. Praticamente la variabile CFLAGS è l'unione di DEFINES e OPTIMIZE.
Il seguente pezzo di codice del Makefile è molto importante:
all: objs progs progs : $(CC) $(CFLAGS) $(LFLAGS) -o $(PROGS) $(PROGS_O) $(LIBS) objs: $(PROGS_O) .c.o: $(CC) $(CFLAGS) -c -o $*.o $< .c.s: $(CC) $(CFLAGS) -S -o $*.s $< .o: $(CC) $(CFLAGS) $(LFLAGS) -o $* $(PROGS_O) $(LIBS) #chmod a+rs,go-w $* testaccel: testaccel.o $(CC) $(CFLAGS) $(LFLAGS) -o testaccel testaccel.o $(LIBS) -lm chmod a+rs,go-w testaccel clean : cleanbin rm -f *.o *~ cleanbin : rm -f $(PROGS) dep : rm -f .depend make .depend tar: tar czvf zb_xload.tgz Makefile main.c README TODO
Queste linee definscono quali sono le sezioni del Makefile che possono essere richiamate singolarmente. In parole più semplici al comando make si può passare anche quale sezione del Makefile va eseguita semplicemente aggiungendola dopo il comando make.
Si pensi alla installazione di una libreria già compilata precedentemente. Se il comando eseguito fosse solo
% make
(con un un certo tipo di Makefile) la libreria sarebbe ricompilata del tutto e solo in seguito installata. Passando, al make, anche il nome della sezione che si occupa della installazione della nostra libreria (nel nostro caso install) questa non sarebbe ricompilata, ma subito installata. Quindi:
% make install
Il nome di ogni sezione deve essere formata da una parola unica che può, però, essere anche l'unione di più parole tramite i simboli - e _ e deve essere seguita dal simbolo :
Nel caso in cui al comando make non fosse passato anche il nome della sezione da eseguire, automaticamente make esegue la prima sezione che incontra, che nel nostro caso è all.
Le sezioni si possono dividere in 2 casi:
È inoltre importante sapere che nei file makefile non devono esistere spazi prima di un comando o del nome di una sezione. Nel caso della sezione cleanbin:
cleanbin : rm -f $(PROGS)
alla sinistra del comando rm non ci sono spazi, ma bensì una tabulazione.
È inoltre possibile unire, in una unica sezione, il richiamo ad altre sezioni e l'esecuzione di uno o più specifici comandi. Un esempio di questi è la sezione clean
clean : cleanbin rm -f *.o *
In questo caso prima viene eseguita la sezione cleanbin e poi il comando rm.
Il file Makefile sembra un pò strano in alcune parti, specialmente perché definisce alcune cose abbastanza inutili (almeno così sembra) come quale compilatore usare o come chiamare il file eseguibile; il motivo di tutto ciò è derivato dal fatto che il il file Makefile può essere utilizzato per creare un file chiamato configure che gestisce meglio il porting di uno stesso programma da una piattaforma ad un'altra controllando se tutto quello che occorre per compilare esattamente il programma stesso esiste ed è accessibile sulla macchina in questione. Si pensi ad esempio al compilatore standard che sotto linux è il gcc, mentre sotto Irix è il cc.
Può essere utile, in alcuni casi, creare più Makefile differenti senza crearne uno che vada bene per tutto. In questo modo il comando make, quando eseguito come descritto nella sezione precedente, terminerà la propria esecuzione con il seguente messaggio di errore:
make: *** No targets. Stop.Questo accade perché il comando make per default cerca il file chiamato esattamente Makefile, che noi, in questo caso, non abbiamo. Per far sì che il comando make utilizzi il Makefile da noi desiderato (ad esempio Makefile.mio) dobbiamo passare, tramite l'opzione -f anche il nome del file Makefile da eseguire. Nel nostro caso, il tutto si risolve esegeundo
% make -f Makefile.mio
Post su it.comp.linux ed comp.unix.programmer
<- XML - Copertina - Impressioni su Linux -> |