# Make (computerprogramma)

Het computerprogramma make dat als hulpmiddel kan worden gebruikt om grote applicaties automatisch te bouwen voor softwareontwikkeling. De computerbestanden die instructies bevatten voor make worden makefiles genoemd. Make houdt bij welke bestanden zijn gewijzigd sinds de laatste maal dat een project was gebouwd en start de compiler enkel voor deze broncodebestanden en de bestanden die afhankelijk zijn van deze bestanden.
Make wordt met name toegepast bij C/C++ projecten, maar kan in principe ook gebruikt worden voor bijna elk softwareproject.
Make is oorspronkelijk ontwikkeld door Stuart Feldman in 1977 bij Bell Labs. Tegenwoordig hebben IDE's en computertaalspecifieke compilers mogelijkheden om een bouwproces te kunnen beheren, maar make blijft nog veel gebruikt, met name op op Unix gebaseerde platformen.

## Oorsprong

Er zijn diverse bouwhulpmiddelen met dezelfde functionaliteit als make, maar make is een van de meest gebruikte hulpmiddelen, hoofdzakelijk omdat deze standaard opgenomen is bij Unix, sinds PWB/UNIX 1.0, die diverse hulpmiddelen bevatte voor softwareontwikkelingstaken. Make is oorspronkelijk ontwikkeld door Stuart Feldman in 1977 bij Bell Labs. In 2004 ontving Feldman de ACM Software System Award voor het ontwikkelen van dit computerprogramma.
Voordat make geïntroduceerd werd, was er vaak een "make" en "install" shell-script bijgevoegd bij de broncode van Unix-programma's. Omdat het mogelijk is om verschillende bouwdoelen te definiëren in een enkel bestand en afhankelijkheden te definiëren, was het een belangrijke stap in de richting van moderne softwarebouwomgevingen.

## Modernere versies

Make is aantal malen herschreven of van begin af aan opnieuw ontwikkeld met dezelfde functionaliteit en ondersteuning van dezelfde bestandsformaten, maar vaak met eigen, niet-standaard toevoegingen in de loop der tijd. Enkele versies zijn:
* BSD make, dat is afgeleid van het werk van Adam de Boor, en dat de mogelijkheid heeft om doelen parallel te kunnen bouwen. Deze versies leven met diverse aanpassingen voort in FreeBSD, NetBSD en OpenBSD. Met name kent het conditionele statements en lus-operaties die tijdens het parsen van een makefile kunnen worden toegepast, zodat makefiles met één algoritme kunnen worden gegenereerd, inclusief de mogelijkheid om bouwdoelen te genereren tijdens het uitvoeren van make.
* GNU make, dat een onderdeel is van de meeste GNU/Linux-installaties en vaak gebruikt wordt in combinatie met het GNU build system. Het bevat naast de traditionele make-functionaliteit met name ook functies voor het automatisch bepalen van bouwdoelen, afhankelijkheden of verwijzingen naar bestanden in de huidige directory, door middel van opgegeven patronen (Engels: pattern matching).
* Microsoft nmake, dat meegeleverd wordt met Microsoft Visual Studio en/of met de Microsoft Windows SDK. Deze versie biedt weinig functionaliteit in vergelijking met de twee hiervoor genoemde versies. Deze versie is overigens niet compatibel met een ander programma genaamd nmake van AT&T Bell Labs voor Unix.
De POSIX-standaard definieert de basisfunctionaliteit en ondersteunde operaties van make en is geïmplementeerd bij vele Unix-gebaseerde versies van make, in wisselende staat van volledigheid. In het algemeen zijn eenvoudige makefiles redelijk uitwisselbaar tussen verschillende versies. Sommige versies van GNU make en BSD make kijken eerst naar bestanden genaamd "GNUmakefile" of "BSDmakefile", wat de mogelijkheid creëert om implementatie-specifieke makefiles te gebruiken op dezelfde locatie.

## Voordelen en nadelen

Wanneer make gebruikt wordt zonder andere hulpmiddelen moet de programmeur de afhankelijkheden tussen bestanden zelf bijhouden voor een project. Dit proces is erg foutgevoelig, aangezien een vergeten afhankelijkheid kan resulteren in lastig te vinden fouten binnen de software. Het is mogelijk om makefiles te maken die deze afhankelijkheden zelf genereren, maar het is gebruikelijker om aparte hulpmiddelen te gebruiken om deze afhankelijkheden te bepalen, zoals Automake van het GNU project.
Een ander probleem is het bouwproces aan te passen voor een ander platform. Compileropties die gebruikt worden voor het ene platform kunnen vaak niet worden gebruikt voor het andere platform. Dit probleem wordt opgelost door verschillende bouwinstructies op te geven die door make kunnen worden toegepast. Gebruikelijke hulpmiddelen hiervoor zijn Autoconf en CMake.
De syntaxis die gebruikt wordt in make, bevat ook het gebruik van het tabteken, een van de tekens die als witruimteteken wordt gezien. Veel teksteditors kunnen geen duidelijk onderscheid maken tussen spaties en tabs, en de ruimte van een tab kan variëren tussen 2 spaties en 8 spaties. Hierdoor wordt de syntaxis van make gezien als een punt van kritiek. Sommige projecten zoals Apache Ant hebben gepoogd om dit te verbeteren met een betere syntaxis, met wisselend succes. Voor programmeurs die gebruikmaken van generatoren is dit punt minder belangrijk.
Met de opkomst van de Integrated Development Environment, met name bij niet-Unix-platformen, hoeven programmeurs vaak niet meer de afhankelijkheden handmatig bij te houden of een lijst bij te houden van welke files deel zijn van een project. Deze taak wordt vaak geautomatiseerd door de omgeving. Veel modernere programmeertalen hebben taalafhankelijke manieren om afhankelijkheden bij te houden, die efficiënt worden gebruikt door taalspecifieke hulpprogramma's. Het nadeel van deze benaderingen is dat specifieke bouwinstructies beperkt of lastig inpasbaar zijn binnen het bouwproces.

## Structuur van een makefile

Een makefile bestaat uit regels met tekst die één of meerdere bestanden definieert, en de afhankelijkheden definieert tussen één of meerdere bestanden. Uitvoerbestanden worden bijvoorbeeld gekoppeld aan bronbestanden, en bronbestanden worden gekoppeld aan de bestanden die ingevoegd worden binnen dat bestand, zoals headerbestanden. Nadat alle afhankelijkheden zijn gedefinieerd, wordt een aantal regels toegevoegd, voorafgegaan door met tab ingesprongen tekst die definieert hoe de invoerbestanden te vertalen naar het uitvoerbestand. Dit gebeurt enkel wanneer een van invoerbestanden nieuwer is dan het uitvoerbestand of als het uitvoerbestand niet bestaat. Deze regels worden aangeduid met "bouwscripts" en worden uitgevoerd door de shell om het uitvoerbestand te genereren. De basisstructuur is:
Een makefile kan ook variabelen bevatten en andere makefiles invoegen. Variabelen in makefiles kunnen optioneel worden opgegeven vanaf de commandoregel als argument van het make-programma. Hiermee kan de gebruiker ander gedrag opgeven binnen de bouwscripts, hoe programma's worden aangeroepen en voor allerlei andere zaken. Zo wordt de variabele "CC" vaak gebruikt om te verwijzen naar een C-compiler en de gebruiker kan met deze variabele een andere compiler opgeven die moet worden gebruikt.

## Voorbeeld van een makefile

Hieronder staat een eenvoudig voorbeeld van een makefile, die een programma compileert genaamd "hallowereld.c" en gebruikmaakt van cc, een C-compiler. Het PHONY-doel is een technische truc om aan te geven dat bepaalde doelen geen bestanden genereren en als het doel als bestand al bestaat deze te negeren, en daarmee wordt uitvoer van een bepaald doel altijd geforceerd alsof het niet bestaat. De $@ en $< zijn twee zogenaamde automatische variabelen die refereren aan het bouwdoel en aan de bronbestanden. Er zijn diverse andere automatische variabelen.