Workstation online OnWorks Linux e Windows

Logo

Hosting online gratuito per workstation

<Precedenti | Contenuti | Succ.>

Costruire il programma

La maggior parte dei programmi viene creata con una semplice sequenza di due comandi:



./configurare make

./configurare make


. configure Il programma è uno script di shell fornito con l'albero sorgente. Il suo compito è analizzare il costruire l'ambienteLa maggior parte del codice sorgente è progettato per essere portatileIn altre parole, è progettato per essere implementato su più di un tipo di sistema Unix-like. Tuttavia, per farlo, il codice sorgente potrebbe dover subire lievi modifiche durante la compilazione per adattarsi alle differenze tra i sistemi. configure controlla anche che siano installati gli strumenti e i componenti esterni necessari. Eseguiamo configure. Da configure non si trova dove la shell normalmente si aspetta che i programmi siano posizionati, dobbiamo indicare esplicitamente alla shell la sua posizione anteponendo il comando con ./ per indicare che il programma si trova nella directory di lavoro corrente:



[me@linuxbox diction-1.11]$ . / Configure

[me@linuxbox diction-1.11]$ . / Configure


configure produrrà molti messaggi durante il test e la configurazione della build. Al termine, apparirà qualcosa di simile a questo:



verifica della presenza di libintl.h... sì verifica della presenza di libintl.h... sì

verifica della libreria contenente gettext... nessuna configurazione richiesta: creazione di ./config.status

config.status: creazione Makefile config.status: creazione diction.1 config.status: creazione diction.texi config.status: creazione diction.spec config.status: creazione di style.1 config.status: creazione di test/rundiction config.status: creazione di config.h [me@linuxbox diction-1.11]$

verifica della presenza di libintl.h... sì verifica della presenza di libintl.h... sì

verifica della libreria contenente gettext... nessuna configurazione richiesta: creazione di ./config.status

config.status: creazione Makefile config.status: creazione diction.1 config.status: creazione diction.texi config.status: creazione diction.spec config.status: creazione di style.1 config.status: creazione di test/rundiction config.status: creazione di config.h [me@linuxbox diction-1.11]$


Ciò che è importante è che non ci siano messaggi di errore. Se ci fossero, la configurazione non è riuscita e il programma non verrà compilato finché gli errori non saranno corretti.

Vediamo configure creato diversi nuovi file nella nostra directory sorgente. Il più importante è Makefile. Makefile è un file di configurazione che istruisce il make programma esattamente come costruire il programma. Senza di esso, make si rifiuterà di correre. Makefile è un normale file di testo, quindi possiamo visualizzarlo:



[me@linuxbox diction-1.11]$ meno Makefile

[me@linuxbox diction-1.11]$ meno Makefile


. make il programma prende come input un makefile (che normalmente è denominato Makefile), che descrive le relazioni e le dipendenze tra i componenti che compongono il programma finito.

La prima parte del makefile definisce le variabili che vengono sostituite nelle sezioni successive del makefile. Ad esempio, vediamo la riga:



CC= gcc

CC= gcc


che definisce il compilatore C come gccPiù avanti nel makefile, vediamo un caso in cui viene utilizzato:


dizione:

dizione.o frase.o misc.o getopt.o getopt1.o

$(CC) -o $@ $(LDFLAGS) diction.o sentence.o misc.o \ getopt.o getopt1.o $(LIBS)

dizione:


Immagine

Qui viene eseguita una sostituzione e il valore $(CC) è sostituito da gcc in fase di esecuzione.

Immagine

La maggior parte del makefile è composta da linee che definiscono un bersaglio, in questo caso il file eseguibile dizionee i file da cui dipende. Le righe rimanenti descrivono i comandi necessari per creare il target a partire dai suoi componenti. In questo esempio vediamo che il file eseguibile dizione (uno dei prodotti finali) dipende dall'esistenza di dizione.o, frase.o, misc.o, getopt.oe getopt1.oPiù avanti, nel makefile, vediamo le definizioni di ciascuno di questi come target:


dizione.o:

getopt.o: getopt1.o: misc.o:

diction.c config.h getopt.h misc.h sentence.h

getopt.c getopt.h getopt_int.h getopt1.c getopt.h getopt_int.h misc.c config.h misc.h

dizione.o:

getopt.o: getopt1.o: misc.o:


frase.o:

stile.o:

frase.c config.h misc.h frase.h

style.c config.h getopt.h misc.h sentence.h

frase.o:

stile.o:


Immagine

Tuttavia, non vediamo alcun comando specificato per loro. Questo è gestito da un target generale, in precedenza nel file, che descrive il comando utilizzato per compilare qualsiasi .c file in a .o file:



.co:

$(CC) -c $(CPPFLAGS) $(CFLAGS) $

.co:

$(CC) -c $(CPPFLAGS) $(CFLAGS) $


Tutto questo sembra molto complicato. Perché non elencare semplicemente tutti i passaggi per compilare le parti e concludere? La risposta a questa domanda sarà chiara tra un attimo. Nel frattempo, procediamo... make e costruiamo i nostri programmi:


[me@linuxbox diction-1.11]$ make

[me@linuxbox diction-1.11]$ make


. make il programma verrà eseguito, utilizzando il contenuto di Makefile per guidare le sue azioni. Produrrà molti messaggi.

Al termine, vedremo che tutti i target sono ora presenti nella nostra directory:



[io@linuxbox

dizione-1.11]$ ls

config.indovina

magazzino

en

installazione-sh

frase.c

config.h

dizione

it_IT

Makefile

frase.h

config.h.in

dizione.1

en_GB.mo

Makefile.in

frase.o

config.log

dizione.1.in

en_GB.po

misc.c

stile

config.stato

dizione.c

getopt1.c

misc.h

stile.1

config.sub

dizione.o

getopt1.o

misc.o

stile.1.in

configure

dizione.pentola

getopt.c

NEWS

stile.c

configurare.in

dizione.spec

getopt.h

nl

stile.o

COPIA

diction.spec.in

getopt_int.h

nl.mo

test

de

dizione.texi

getopt.o

nl.po

de.mo

diction.texi.in

INSTALLARE

README


Tra i file vediamo dizione e stile, i programmi che ci siamo prefissati di realizzare. Congratulazioni! Abbiamo appena compilato i nostri primi programmi dal codice sorgente!

Ma solo per curiosità, corriamo make ancora una volta:


[me@linuxbox diction-1.11]$ make

fare: Non c'è niente da fare per `tutti'.

[me@linuxbox diction-1.11]$ make

fare: Non c'è niente da fare per `tutti'.


Produce solo questo strano messaggio. Cosa sta succedendo? Perché non ha ricostruito il programma? Ah, questa è la magia di makeInvece di ricostruire semplicemente tutto, make costruisce solo ciò che deve essere costruito. Con tutti gli obiettivi presenti, make ha stabilito che non c'era nulla da fare. Possiamo dimostrarlo eliminando uno dei target ed eseguendo nuovamente make per vedere cosa succede. Eliminiamo uno dei target intermedi:



[me@linuxbox diction-1.11]$ rm getopt.o

[me@linuxbox diction-1.11]$ make

[me@linuxbox diction-1.11]$ rm getopt.o

[me@linuxbox diction-1.11]$ make


Lo vediamo make lo ricostruisce e ricollega il dizione e stile programmi, poiché dipendono dal modulo mancante. Questo comportamento evidenzia anche un'altra importante caratteristica di make: mantiene aggiornati gli obiettivi. make insiste sul fatto che gli obiettivi siano più recenti delle loro dipendenze. Questo ha perfettamente senso, poiché un programmatore spesso aggiorna un po' di codice sorgente e poi usa make per realizzare una nuova versione del prodotto finito. make assicura che tutto ciò che deve essere costruito in base al codice aggiornato venga costruito. Se utilizziamo il toccare programma per "aggiornare" uno dei file del codice sorgente, possiamo vedere che accade questo:



[me@linuxbox diction-1.11]$ ls -l dizione getopt.c

-rwxr-xr-x 1 me me 37164 2009-03-05 06:14 dizione

-rw-r--r-- 1 me me 33125 2007-03-30 17:45 getopt.c [me@linuxbox diction-1.11]$ tocca getopt.c

[me@linuxbox diction-1.11]$ ls -l dizione getopt.c

-rwxr-xr-x 1 me me 37164 2009-03-05 06:14 dizione

-rw-r--r-- 1 me me 33125 2009-03-05 06:23 getopt.c [me@linuxbox diction-1.11]$ make

[me@linuxbox diction-1.11]$ ls -l dizione getopt.c

-rwxr-xr-x 1 me me 37164 2009-03-05 06:14 dizione

-rw-r--r-- 1 me me 33125 2007-03-30 17:45 getopt.c [me@linuxbox diction-1.11]$ tocca getopt.c

[me@linuxbox diction-1.11]$ ls -l dizione getopt.c

-rwxr-xr-x 1 me me 37164 2009-03-05 06:14 dizione

-rw-r--r-- 1 me me 33125 2009-03-05 06:23 getopt.c [me@linuxbox diction-1.11]$ make


Dopo make viene eseguito, vediamo che ha ripristinato il target come più recente della dipendenza:



[me@linuxbox diction-1.11]$ ls -l dizione getopt.c

-rwxr-xr-x 1 me me 37164 2009-03-05 06:24 dizione

-rw-r--r-- 1 me me 33125 2009-03-05 06:23 getopt.c

[me@linuxbox diction-1.11]$ ls -l dizione getopt.c

-rwxr-xr-x 1 me me 37164 2009-03-05 06:24 dizione

-rw-r--r-- 1 me me 33125 2009-03-05 06:23 getopt.c


La capacità di make Costruire in modo intelligente solo ciò che è necessario costruire è un grande vantaggio per i programmatori. Anche se il risparmio di tempo potrebbe non essere molto evidente con il nostro piccolo progetto,


è molto significativo con progetti più grandi. Ricorda, il kernel Linux (un programma che subisce continue modifiche e miglioramenti) contiene diversi milione linee di codice.


Il miglior sistema operativo cloud computing su OnWorks: