# Make

Il make è un'utility, sviluppata sui sistemi operativi della famiglia UNIX, ma disponibile su un'ampia gamma di sistemi, che automatizza il processo di creazione di file che dipendono da altri file, risolvendo le dipendenze e invocando programmi esterni per il lavoro necessario.
Tale gestione delle dipendenze è molto semplice, e si basa sulla data e ora di ultima modifica dei file interessati.
L'utility è usata soprattutto per la compilazione di codice sorgente in codice oggetto, unendo e poi linkando il codice oggetto in programmi eseguibili o in librerie. Esso usa file chiamati makefile per determinare il grado delle dipendenze per un particolare output, e gli script necessari per la compilazione da passare alla shell. Il termine makefile deriva dal nome dato tipicamente al file di input di make.

## Origine

Ora ci sono delle utilities per la verifica delle dipendenze, ma 'make' è effettivamente l'utility più utilizzata, principalmente per la sua inclusione dei sistemi operativi Unix. È stato creato da Stuart Feldman nel 1977 nei laboratori Bell (Bell Labs). Nel 2003, il Dr. Feldman ha ricevuto il premio: ACM, per l'invenzione di questo importante tool. Prima dell'invenzione di make il sistema di build di UNIX consisteva semplicemente in "make" e "install", che erano dei semplici shellscript, insieme al codice sorgente di un programma. Poter mischiare i comandi / istruzioni per diversi target in un singolo file e poter astrarre la verifica e il tracking delle dipendenze, è stato un importante passo avanti per i più avanzati ambienti di building.

## Versioni moderne

Make è stato riscritto più volte e in alcuni casi sono state scritte delle varianti da zero, che utilizzano lo stesso format dei file e lo stesso algoritmo base. Tre versioni riscritte di make più comuni e tradizionali sono:
* BSD make, che è derivato dal lavoro di Adam de Boor, su una versione di make capace di costruire target in parallelo, e funziona con varie modifiche in FreeBSD, NetBSD e OpenBSD.
* GNU make, che è parte di (quasi) tutte le distribuzioni GNU/Linux è usato insieme al GNU build system . Una delle differenze principali con BSD make, è che quest'ultimo ha un set predefinito di macro, GNU make di solito usa un set esterno di macro come M4.
* NMAKE, il buildtool fornito con Visual C++.
POSIX include la standardizzazione delle feature basilari e operazioni di make, grazie a questo è possibile usare semplici Makefiles in più varianti di make, alcune versioni di GNU e BSD make, cercheranno rispettivamente prima i file GNUmakefile e BSDmakefile.

## Utilizzo e critiche

Make ha la sua porzione di fan e non. Sono emersi molti problemi quando si è tentato di usare make con moderni o grandi progetti, ma molte persone hanno comunque sottolineato che make funziona effettivamente molto bene, è semplice da utilizzare e molto potente. È utilizzato per compilare e gestire (quasi) ogni sistema operativo, e molti sostituti moderni sono molto simili al funzionamento del "vero" make. Allo stesso modo, molti linguaggi di programmazione moderni, hanno dei loro modi specifici di rilevare le dipendenze.
Con l'avvento degli Ambienti di Sviluppo Integrati (IDE), specialmente sulle piattaforme non-UNIX, molti programmatori non fanno manualmente il tracking e la gestione delle dipendenze, o anche la lista dei file che fanno parte del progetto, lasciano fare queste cose al loro ambiente di sviluppo automatizzato.

## Struttura di un makefile

Un makefile consiste in linee di testo che definiscono un file (o un gruppo di file) oppure il nome di una regola dipendente dal gruppo di file. I file generati sono contrassegnati come i loro file sorgenti, mentre i file sorgenti sono contrassegnati a seconda dei file inclusi internamente. Dopo che ogni dipendenza è dichiarata, può seguire una serie di linee indentate (da tabulazioni) che definiscono come trasformare i file di ingresso nei file d'uscita, se il primo è stato modificato più di recente rispetto al secondo. Nel caso in cui tali definizioni sono presenti, queste sono riferite a dei script di compilazione e sono passate alla shell per generare i file target.
La struttura base è:
Un makefile può anche contenere definizioni di variabili e inclusioni di altri makefile. Le variabili nei makefile possono essere sovrascritte dagli argomenti passati all'utility make dalla riga di comando. Questo permette all'utente di specificare differenti comportamenti degli script di compilazione e come invocare i programmi oltre ad altre cose. Per esempio la variabile "CC" è frequentemente usata nei makefile per riferirsi al compilatore C e l'utente potrebbe fornire una alternativa al compilatore da usare.

## Esempio di un makefile

Sotto è riportato un esempio di un makefile che compila un sorgente chiamato "helloworld.c" usando cc, un compilatore C. Il tag PHONY è un tecnicismo che dice al make che un particolare nome di target non produce un file. I simboli $@ e $< sono due di quelle che sono chiamate variabili automatiche e rappresentano il nome del target. Ci sono altre variabili automatiche.
Si noti che nel target "clean", un meno precede nel comando, dicendo al make di ignorare gli errori durante l'esecuzione del comando; make normalmente esce se l'esecuzione di un comando fallisce in qualsiasi punto. Nel caso del target di pulizia, chiamato tipicamente "clean", si vuole rimuovere ogni file generato nel processo di compilazione, senza uscire se i file da cancellare non esistono. Con l'aggiunta del tag PHONY al clean, si previene che make si aspetti un file dal target. In questo particolare caso, il prefisso meno nel comando è ridondante e in casi comuni, l'opzione -f o "force" aggiunta a rm previene che rm esca a causa della non esistenza di un file.

## Tool simili

Make è sicuramente il tool più conosciuto per l'automazione del project-building, ma esistono anche altri tool, simili a make:
* ant Tool molto popolare per gestire grandi progetti Java, incluso in Eclipse. Utilizza un file XML per la configurazione del progetto.
* maven Tool simile a ant, utilizzato in Android Studio (e non, ovviamente)
* Rake: Un build tool basato su Ruby