Makefile - Guida rapida

Compilare i file del codice sorgente può essere stancante, soprattutto quando devi includere diversi file sorgente e digitare il comando di compilazione ogni volta che devi compilare. I makefile sono la soluzione per semplificare questo compito.

I makefile sono file di formato speciale che aiutano a costruire e gestire i progetti automaticamente.

Ad esempio, supponiamo di avere i seguenti file sorgente.

  • main.cpp
  • hello.cpp
  • factorial.cpp
  • functions.h

main.cpp

Di seguito è riportato il codice per il file sorgente main.cpp -

#include <iostream>

using namespace std;

#include "functions.h"

int main(){
   print_hello();
   cout << endl;
   cout << "The factorial of 5 is " << factorial(5) << endl;
   return 0;
}

hello.cpp

Il codice fornito di seguito è per il file sorgente hello.cpp -

#include <iostream>

using namespace std;

#include "functions.h"

void print_hello(){
   cout << "Hello World!";
}

factorial.cpp

Il codice per factorial.cpp è fornito di seguito:

#include "functions.h"

int factorial(int n){
   
   if(n!=1){
      return(n * factorial(n-1));
   } else return 1;
}

functions.h

Quello che segue è il codice per fnctions.h -

void print_hello();
int factorial(int n);

Il modo più banale per compilare i file e ottenere un eseguibile è eseguire il comando -

gcc  main.cpp hello.cpp factorial.cpp -o hello

Questo comando genera hello binary. In questo esempio abbiamo solo quattro file e conosciamo la sequenza delle chiamate di funzione. Quindi, è possibile digitare il comando precedente e preparare un binario finale.

Tuttavia, per un progetto di grandi dimensioni in cui abbiamo migliaia di file di codice sorgente, diventa difficile mantenere le build binarie.

Il makecomando consente di gestire programmi di grandi dimensioni o gruppi di programmi. Quando si inizia a scrivere programmi di grandi dimensioni, si nota che la ricompilazione di programmi di grandi dimensioni richiede più tempo rispetto alla ricompilazione di programmi brevi. Inoltre, noti che di solito lavori solo su una piccola sezione del programma (come una singola funzione) e gran parte del programma rimanente rimane invariato.

Nella sezione successiva, vediamo come preparare un makefile per il nostro progetto.

Il makeprogramma consente di utilizzare macro, che sono simili alle variabili. Le macro sono definite in un Makefile come = coppie. Di seguito è stato mostrato un esempio:

MACROS  = -me
PSROFF  = groff -Tps
DITROFF = groff -Tdvi
CFLAGS  = -O -systype bsd43
LIBS    = "-lncurses -lm -lsdl"
MYFACE  = ":*)"

Macro speciali

Prima di eseguire qualsiasi comando in un set di regole di destinazione, ci sono alcune macro speciali predefinite:

  • $ @ è il nome del file da creare.

  • $? sono i nomi dei dipendenti modificati.

Ad esempio, potremmo usare una regola come segue:

hello: main.cpp hello.cpp factorial.cpp
   $(CC) $(CFLAGS) $? $(LDFLAGS) -o [email protected]

Alternatively:

hello: main.cpp hello.cpp factorial.cpp
   $(CC) $(CFLAGS) [email protected] $(LDFLAGS) -o [email protected]

In questo esempio, $ @ rappresenta ciao e $? o $ @. cpp preleva tutti i file sorgente modificati.

Ci sono altre due macro speciali usate nelle regole implicite. Sono -

  • $ <il nome del file correlato che ha causato l'azione.

  • $ * il prefisso condiviso dai file di destinazione e dipendenti.

La regola implicita comune è per la costruzione di file .o (oggetto) da .cpp (file sorgente).

.cpp.o:
   $(CC) $(CFLAGS) -c $<

Alternatively:

.cpp.o:
   $(CC) $(CFLAGS) -c $*.c

Macro convenzionali

Sono disponibili varie macro predefinite. Puoi vederli digitando "make -p" per stampare i valori predefiniti. La maggior parte sono abbastanza evidenti dalle regole in cui vengono utilizzate.

Queste variabili predefinite, ovvero le macro utilizzate nelle regole implicite, rientrano in due classi. Sono i seguenti:

  • Macro che sono nomi di programmi (come CC)

  • Macro che contengono argomenti dei programmi (come CFLAGS).

Di seguito è riportata una tabella di alcune delle variabili comuni utilizzate come nomi di programmi nelle regole integrate dei makefile:

Suor n Variabili e descrizione
1

AR

Programma di conservazione dell'archivio; il valore predefinito è "ar".

2

AS

Programma per compilare file assembly; il valore predefinito è "as".

3

CC

Programma per compilare programmi in C; il valore predefinito è "cc".

4

CO

Programma per estrarre file da RCS; il valore predefinito è "co".

5

CXX

Programma per compilare programmi C ++; il valore predefinito è "g ++".

6

CPP

Programma per eseguire il preprocessore C, con risultati sullo standard output; il valore predefinito è "$ (CC) -E".

7

FC

Programma per la compilazione o la preelaborazione di programmi Fortran e Ratfor; il valore predefinito è "f77".

8

GET

Programma per estrarre un file da SCCS; il valore predefinito è "get".

9

LEX

Programma da utilizzare per trasformare le grammatiche Lex in codice sorgente; il valore predefinito è "lex".

10

YACC

Programma da utilizzare per trasformare le grammatiche Yacc in codice sorgente; il valore predefinito è "yacc".

11

LINT

Programma da utilizzare per eseguire lint sul codice sorgente; il valore predefinito è "lint".

12

M2C

Programma da utilizzare per compilare il codice sorgente Modula-2; il valore predefinito è "m2c".

13

PC

Programma per compilare programmi Pascal; l'impostazione predefinita è "pc".

14

MAKEINFO

Programma per convertire un file sorgente Texinfo in un file Info; il valore predefinito è "makeinfo".

15

TEX

Programma per creare file TeX dvi da sorgenti TeX; il valore predefinito è "tex".

16

TEXI2DVI

Programma per creare file TeX dvi dalla sorgente Texinfo; il valore predefinito è `texi2dvi '.

17

WEAVE

Programma per tradurre Web in TeX; il valore predefinito è "tessere".

18

CWEAVE

Programma per tradurre C Web in TeX; il valore predefinito è "cweave".

19

TANGLE

Programma per tradurre Web in Pascal; il valore predefinito è "tangle".

20

CTANGLE

Programma per tradurre C Web in C; il valore predefinito è "ctangle".

21

RM

Comando per rimuovere un file; il valore predefinito è "rm -f".

Ecco una tabella di variabili i cui valori sono argomenti aggiuntivi per i programmi sopra. Il valore predefinito per tutti questi è la stringa vuota, se non diversamente specificato.

Sr.No. Variabili e descrizione
1

ARFLAGS

Flag per fornire il programma di mantenimento dell'archivio; il valore predefinito è "rv".

2

ASFLAGS

Flag aggiuntivi da dare all'assembler quando invocato esplicitamente su un file `.s 'o` .S'.

3

CFLAGS

Flag extra da dare al compilatore C.

4

CXXFLAGS

Flag extra da dare al compilatore C.

5

COFLAGS

Flag extra da dare al programma RCS co.

6

CPPFLAGS

Flag extra da dare al preprocessore C e ai programmi che lo usano (come i compilatori C e Fortran).

7

FFLAGS

Flag aggiuntivi da dare al compilatore Fortran.

8

GFLAGS

Flag aggiuntivi da dare al programma SCCS get.

9

LDFLAGS

Flag aggiuntivi da dare ai compilatori quando si suppone che invocino il linker, `ld '.

10

LFLAGS

Flag extra da dare a Lex.

11

YFLAGS

Bandiere extra da dare a Yacc.

12

PFLAGS

Flag extra da dare al compilatore Pascal.

13

RFLAGS

Flag extra da dare al compilatore Fortran per i programmi Ratfor.

14

LINTFLAGS

Bandiere extra da dare alla lanugine.

NOTE - Puoi cancellare tutte le variabili usate dalle regole implicite con l'opzione '-R' o '--no-builtin-variables'.

È inoltre possibile definire macro dalla riga di comando come mostrato di seguito:

make CPP = /home/courses/cop4530/spring02

È molto comune che un binario finale dipenda da vari codici sorgente e file di intestazione del sorgente. Le dipendenze sono importanti perché consentono amakeConosciuto sull'origine per qualsiasi destinazione. Considera il seguente esempio:

hello: main.o factorial.o hello.o
   $(CC) main.o factorial.o hello.o -o hello

Qui, diciamo al makeche hello dipende dai file main.o, factorial.o e hello.o. Quindi, ogni volta che si verifica una modifica in uno di questi file oggetto,make agirà.

Allo stesso tempo, dobbiamo dire al file makecome preparare i file .o. Quindi dobbiamo definire anche quelle dipendenze come segue:

main.o: main.cpp functions.h
   $(CC) -c main.cpp

factorial.o: factorial.cpp functions.h
   $(CC) -c factorial.cpp

hello.o: hello.cpp functions.h
   $(CC) -c hello.cpp

Ora impareremo le regole per Makefile.

La sintassi generale di una regola di destinazione Makefile è:

target [target...] : [dependent ....]
[ command ...]

Nel codice precedente, gli argomenti tra parentesi sono facoltativi e i puntini di sospensione indicano uno o più. Qui, nota che è richiesta la scheda che precede ogni comando.

Di seguito viene fornito un semplice esempio in cui si definisce una regola per salutare il proprio target da altri tre file.

hello: main.o factorial.o hello.o
   $(CC) main.o factorial.o hello.o -o hello

NOTE - In questo esempio, dovresti dare delle regole per creare tutti i file oggetto dai file sorgente.

La semantica è molto semplice. Quando dici "crea target", il filemaketrova la regola di destinazione che si applica; e, se qualcuno dei dipendenti è più recente del target,makeesegue i comandi uno alla volta (dopo la sostituzione della macro). Se è necessario creare delle dipendenze, ciò accade per primo (quindi hai una ricorsione).

Maketermina se qualsiasi comando restituisce uno stato di errore. In tal caso verrà mostrata la seguente regola:

clean:
   -rm *.o *~ core paper

Makeignora lo stato restituito sulle righe di comando che iniziano con un trattino. Ad esempio, a chi importa se non esiste un file core?

Makefa eco i comandi, dopo la sostituzione della macro per mostrarti cosa sta succedendo. A volte potresti volerlo disattivare. Ad esempio:

install:
   @echo You must be root to install

Le persone si aspettano determinati obiettivi nei Makefile. Dovresti sempre navigare prima. Tuttavia, è ragionevole aspettarsi che le destinazioni tutte (o solo create), installate e pulite vengano trovate.

  • make all - Compila tutto in modo da poter eseguire test locali prima di installare le applicazioni.

  • make install - Installa le applicazioni nei posti giusti.

  • make clean - Pulisce le applicazioni, elimina gli eseguibili, i file temporanei, i file oggetto, ecc.

Regole implicite del makefile

Il comando è uno che dovrebbe funzionare in tutti i casi in cui si crea un eseguibile x dal codice sorgente x.cpp. Questo può essere affermato come una regola implicita:

.cpp:
   $(CC) $(CFLAGS) [email protected] $(LDFLAGS) -o [email protected]

Questa regola implicita dice come creare x da xc: eseguire cc su xc e chiamare l'output x. La regola è implicita perché non viene menzionato alcun obiettivo particolare. Può essere utilizzato in tutti i casi.

Un'altra regola implicita comune è per la costruzione di file .o (oggetto) da .cpp (file sorgente).

.cpp.o:
   $(CC) $(CFLAGS) -c $<

alternatively

.cpp.o:
   $(CC) $(CFLAGS) -c $*.cpp

Makepuò creare automaticamente un file ao, utilizzando cc -c sul file .c corrispondente. Queste regole sono integrate inmakee puoi sfruttare questo vantaggio per accorciare il tuo Makefile. Se indichi solo i file .h nella riga di dipendenza del Makefile da cui dipende il target corrente,makesaprà che il file .c corrispondente è già richiesto. Non è necessario includere il comando per il compilatore.

Questo riduce ulteriormente il Makefile, come mostrato di seguito -

OBJECTS = main.o hello.o factorial.o
hello: $(OBJECTS)
   cc $(OBJECTS) -o hello
hellp.o: functions.h

main.o: functions.h 
factorial.o: functions.h

Makeutilizza un obiettivo speciale, denominato .SUFFIXES per consentire di definire i propri suffissi. Ad esempio, fare riferimento alla riga di dipendenza fornita di seguito:

.SUFFIXES: .foo .bar

Informa make che utilizzerai questi suffissi speciali per creare le tue regole.

Simile a come makesa già come creare un file .o da un file .c , puoi definire le regole nel modo seguente:

.foo.bar:
   tr '[A-Z][a-z]' '[N-Z][A-M][n-z][a-m]' < $< > [email protected]
.c.o:
   $(CC) $(CFLAGS) -c $<

La prima regola ti consente di creare un file .bar da un file .foo . Fondamentalmente codifica il file. La seconda regola è la regola predefinita utilizzata damakeper creare un file .o da un file .c .

Sono disponibili numerose direttive in varie forme. Ilmakeil programma sul sistema potrebbe non supportare tutte le direttive. Quindi per favore controlla se il tuomake supporta le direttive che stiamo spiegando qui. GNU make supporta queste direttive.

Direttive condizionali

Le direttive condizionali sono:

  • Il ifeqdirettiva inizia il condizionale e specifica la condizione. Contiene due argomenti, separati da una virgola e circondati da parentesi. La sostituzione delle variabili viene eseguita su entrambi gli argomenti e quindi vengono confrontati. Le righe del makefile che seguono ifeq vengono rispettate se i due argomenti corrispondono; altrimenti vengono ignorati.

  • Il ifneqdirettiva inizia il condizionale e specifica la condizione. Contiene due argomenti, separati da una virgola e circondati da parentesi. La sostituzione delle variabili viene eseguita su entrambi gli argomenti e quindi vengono confrontati. Le righe del makefile che seguono l'ifneq vengono rispettate se i due argomenti non corrispondono; altrimenti vengono ignorati.

  • Il ifdefdirettiva inizia il condizionale e specifica la condizione. Contiene un singolo argomento. Se l'argomento fornito è vero, la condizione diventa vera.

  • Il ifndefdirettiva inizia il condizionale e specifica la condizione. Contiene un singolo argomento. Se l'argomento fornito è falso, la condizione diventa vera.

  • Il elsedirettiva fa sì che le seguenti righe vengano rispettate se il condizionale precedente non è riuscito. Nell'esempio sopra, ciò significa che il secondo comando di collegamento alternativo viene utilizzato ogni volta che la prima alternativa non viene utilizzata. È facoltativo avere un altro in un condizionale.

  • Il endifla direttiva pone fine al condizionale. Ogni condizionale deve terminare con un endif.

Sintassi delle direttive condizionali

La sintassi di un condizionale semplice senza nient'altro è la seguente:

conditional-directive
   text-if-true
endif

Il testo-se-vero può essere qualsiasi riga di testo, da considerare come parte del makefile se la condizione è vera. Se la condizione è falsa, non viene utilizzato alcun testo.

La sintassi di un condizionale complesso è la seguente:

conditional-directive
   text-if-true
else
   text-if-false
endif

Se la condizione è vera, viene utilizzato text-if-true; in caso contrario, viene utilizzato text-if-false. Il testo-se-falso può essere un numero qualsiasi di righe di testo.

La sintassi della direttiva condizionale è la stessa sia che il condizionale sia semplice o complesso. Esistono quattro diverse direttive che testano varie condizioni. Sono come dati -

ifeq (arg1, arg2)
ifeq 'arg1' 'arg2'
ifeq "arg1" "arg2"
ifeq "arg1" 'arg2'
ifeq 'arg1' "arg2"

Le direttive opposte alle condizioni di cui sopra sono le seguenti:

ifneq (arg1, arg2)
ifneq 'arg1' 'arg2'
ifneq "arg1" "arg2"
ifneq "arg1" 'arg2'
ifneq 'arg1' "arg2"

Esempio di direttive condizionali

libs_for_gcc = -lgnu
normal_libs =

foo: $(objects)
ifeq ($(CC),gcc)
   $(CC) -o foo $(objects) $(libs_for_gcc)
else
   $(CC) -o foo $(objects) $(normal_libs)
endif

La direttiva include

Il include directive permette makeper sospendere la lettura del makefile corrente e leggere uno o più altri makefile prima di continuare. La direttiva è una riga nel makefile che sembra seguire -

include filenames...

I nomi dei file possono contenere modelli di nomi di file di shell. Gli spazi aggiuntivi sono consentiti e ignorati all'inizio della riga, ma non è consentita una tabulazione. Ad esempio, se hai tre file ".mk", ovvero "a.mk", "b.mk" e "c.mk" e $ (bar), si espande in bish bash, e poi quanto segue espressione.

include foo *.mk $(bar)

is equivalent to:

include foo a.mk b.mk c.mk bish bash

Quando il makeelabora una direttiva include, sospende la lettura del makefile e legge a turno da ogni file elencato. Quando è finito,make riprende a leggere il makefile in cui appare la direttiva.

La direttiva override

Se una variabile è stata impostata con un argomento di comando, le assegnazioni ordinarie nel makefile vengono ignorate. Se vuoi impostare la variabile nel makefile anche se è stata impostata con un argomento di comando, puoi usare una direttiva override, che è una riga che sembra seguire -

override variable = value

or

override variable := value

Il makeè un'utilità intelligente e funziona in base alle modifiche apportate ai file sorgente. Se hai quattro file main.cpp, hello.cpp, factorial.cpp e functions.h, tutti i file rimanenti dipendono da functions.he main.cpp dipende sia da hello.cpp che da factorial.cpp. Quindi, se si apportano modifiche a functions.h, il filemakericompila tutti i file sorgente per generare nuovi file oggetto. Tuttavia, se si apportano modifiche a main.cpp, poiché questo non dipende da nessun altro file, viene ricompilato solo il file main.cpp e help.cpp e factorial.cpp non lo sono.

Durante la compilazione di un file, il makecontrolla il suo file oggetto e confronta i timestamp. Se il file di origine ha un timestamp più recente del file oggetto, genera un nuovo file oggetto presupponendo che il file di origine sia stato modificato.

Evitare la ricompilazione

Potrebbe esserci un progetto composto da migliaia di file. A volte potresti aver modificato un file sorgente ma potresti non voler ricompilare tutti i file che dipendono da esso. Ad esempio, supponiamo di aggiungere una macro o una dichiarazione a un file di intestazione, da cui dipendono gli altri file. Essere conservatore,make presume che qualsiasi cambiamento nel file di intestazione richieda la ricompilazione di tutti i file dipendenti, ma sai che non hanno bisogno di ricompilazione e preferiresti non sprecare il tuo tempo ad aspettare che si compilino.

Se prevedi il problema prima di modificare il file di intestazione, puoi usare il flag `-t '. Questa bandiera dicemakenon per eseguire i comandi nelle regole, ma piuttosto per contrassegnare l'obiettivo come aggiornato cambiando la sua data di ultima modifica. È necessario seguire questa procedura:

  • Usa il comando "make" per ricompilare i file sorgente che hanno davvero bisogno di essere ricompilati.

  • Apporta le modifiche nei file di intestazione.

  • Utilizzare il comando "make -t" per contrassegnare tutti i file oggetto come aggiornati. La prossima volta che si esegue make, le modifiche nei file di intestazione non causano alcuna ricompilazione.

Se hai già modificato il file di intestazione in un momento in cui alcuni file necessitano di essere ricompilati, è troppo tardi per farlo. Invece, puoi usare il flag `-o file ', che contrassegna un file specificato come" vecchio ". Ciò significa che il file stesso non verrà rifatto e nient'altro verrà rifatto sul suo account. è necessario seguire questa procedura -

  • Ricompilate i file sorgente che necessitano di compilazione per ragioni indipendenti dal particolare file di intestazione, con "make -o file di intestazione". Se sono coinvolti più file di intestazione, utilizzare un'opzione `-o 'separata per ogni file di intestazione.

  • Aggiorna tutti i file oggetto con "make -t".

In questo capitolo, esamineremo varie altre caratteristiche di Makefile.

Uso ricorsivo di Make

Uso ricorsivo di make significa usare makecome comando in un makefile. Questa tecnica è utile quando si vogliono makefile separati per vari sottosistemi che compongono un sistema più grande. Ad esempio, supponi di avere una sottodirectory chiamata `subdir 'che ha il suo makefile e desideri che il makefile della directory contenentemakenella sottodirectory. Puoi farlo scrivendo il codice sottostante -

subsystem:
   cd subdir && $(MAKE)

or, equivalently:
 	
subsystem:
   $(MAKE) -C subdir

Puoi scrivere ricorsivo makecomandi semplicemente copiando questo esempio. Tuttavia, è necessario sapere come funzionano e perché e in che modo la marca secondaria si collega alla marca di primo livello.

Comunicazione di variabili a una marca secondaria

Valori variabili del primo livello makepuò essere passato al sub-make attraverso l'ambiente su esplicita richiesta. Queste variabili sono definite nella sub-marca come valori predefiniti. Non è possibile sovrascrivere ciò che è specificato nel makefile usato dal sub-make makefile a meno che non si usi l'opzione `-e '.

Per trasmettere o esportare una variabile, makeaggiunge la variabile e il suo valore all'ambiente per l'esecuzione di ogni comando. Il sub-make, a sua volta, utilizza l'ambiente per inizializzare la sua tabella di valori variabili.

Le variabili speciali SHELL e MAKEFLAGS vengono sempre esportate (a meno che non vengano annullate). MAKEFILES viene esportato se lo imposti su qualcosa.

Se vuoi esportare variabili specifiche in un sub-make, usa la direttiva export, come mostrato di seguito -

export variable ...

Se vuoi impedire che una variabile venga esportata, usa la direttiva unexport, come mostrato di seguito -

unexport variable ...

La variabile MAKEFILES

Se la variabile d'ambiente MAKEFILES è definita, makeconsidera il suo valore come un elenco di nomi (separati da spazi bianchi) di makefile aggiuntivi da leggere prima degli altri. Funziona in modo molto simile alla direttiva include: i file vengono ricercati in varie directory.

L'utilizzo principale di MAKEFILES è nella comunicazione tra invocazioni ricorsive di make.

Incluso file di intestazione da directory diverse

Se hai messo i file di intestazione in directory diverse e stai eseguendo makein una directory diversa, quindi è necessario fornire il percorso dei file di intestazione. Questo può essere fatto usando l'opzione -I nel makefile. Supponendo che il file functions.h sia disponibile nella cartella / home / tutorialspoint / header e il resto dei file sia disponibile nella cartella / home / tutorialspoint / src /, il makefile verrebbe scritto come segue:

INCLUDES = -I "/home/tutorialspoint/header"
CC = gcc
LIBS =  -lm
CFLAGS = -g -Wall
OBJ =  main.o factorial.o hello.o

hello: ${OBJ}
   ${CC} ${CFLAGS} ${INCLUDES} -o [email protected] ${OBJS} ${LIBS}
.cpp.o:
   ${CC} ${CFLAGS} ${INCLUDES} -c $<

Aggiunta di più testo alle variabili

Spesso è utile aggiungere più testo al valore di una variabile già definita. Lo fai con una riga contenente "+ =", come mostrato -

objects += another.o

Prende il valore degli oggetti variabili e vi aggiunge il testo "another.o", preceduto da un singolo spazio come mostrato di seguito.

objects = main.o hello.o factorial.o
objects += another.o

Il codice precedente imposta gli oggetti su `main.o hello.o factorial.o another.o '.

L'uso di "+ =" è simile a:

objects = main.o hello.o factorial.o
objects := $(objects) another.o

Riga di continuazione nel Makefile

Se non ti piacciono le righe troppo grandi nel tuo Makefile, puoi spezzare la riga usando una barra rovesciata "\" come mostrato di seguito -

OBJ =  main.o factorial.o \
   hello.o

is equivalent to

OBJ =  main.o factorial.o hello.o

Esecuzione di Makefile dal prompt dei comandi

Se hai preparato il Makefile con il nome "Makefile", scrivi semplicemente make al prompt dei comandi e verrà eseguito il file Makefile. Ma se hai dato un altro nome al Makefile, usa il seguente comando:

make -f your-makefile-name

Questo è un esempio del Makefile per compilare il programma hello. Questo programma è composto da tre file main.cpp , factorial.cpp e hello.cpp .

# Define required macros here
SHELL = /bin/sh

OBJS =  main.o factorial.o hello.o
CFLAG = -Wall -g
CC = gcc
INCLUDE =
LIBS = -lm

hello:${OBJ}
   ${CC} ${CFLAGS} ${INCLUDES} -o [email protected] ${OBJS} ${LIBS}

clean:
   -rm -f *.o core *.core

.cpp.o:
   ${CC} ${CFLAGS} ${INCLUDES} -c $<

Ora puoi costruire il tuo programma hello usando il make. Se emetterai un comandomake clean quindi rimuove tutti i file oggetto e i file core disponibili nella directory corrente.