makefile Zelfstudie
Aan de slag met makefile
Zoeken…
Opmerkingen
Een makefile is een tekstbestand dat de werking van het make
programma bestuurt. Het make
programma wordt meestal gebruikt om het maken van programma's vanuit hun bronbestanden te beheren, maar het kan meer in het algemeen worden gebruikt om elk proces te verwerken waarbij bestanden (of doelen ) opnieuw moeten worden gegenereerd nadat andere bestanden (of vereisten ) zijn gewijzigd. De makefile beschrijft de relatie tussen doelen en vereisten, en specificeert ook de opdrachten die nodig zijn om het doel up-to-date te brengen wanneer een of meer van de vereisten zijn gewijzigd. De enige manier waarop make
bepaalt "out of date-ness" is door de modificatie tijd van target bestanden en hun voorwaarden te vergelijken.
Makefiles zijn enigszins uniek op een paar manieren die aanvankelijk verwarrend kunnen zijn.
Ten eerste bestaat een makefile uit twee volledig verschillende programmeertalen in hetzelfde bestand. Het grootste deel van het bestand is geschreven in een taal die make
kan begrijpen: dit levert variabeletoekenning en expansie, sommige preprocessor mogelijkheden (met inbegrip van andere bestanden, voorwaardelijke parsing secties van het bestand, enz.), Alsmede de definitie van de doelstellingen en hun vereisten. Bovendien kan aan elk doel een recept worden gekoppeld dat aangeeft welke opdrachten moeten worden aangeroepen om ervoor te zorgen dat dat doel wordt bijgewerkt. Het recept is geschreven als een shellscript (standaard POSIX sh). Het make
programma ontleedt dit script niet: het draait een shell en geeft het script door aan de uit te voeren shell. Het feit dat recepten niet per make
worden ontleed, maar in plaats daarvan door een afzonderlijk shell-proces worden verwerkt, staat centraal bij het begrijpen van makefiles.
Ten tweede is een makefile geen procedurele taal zoals een script: aangezien make
het makefile ontleedt, construeert het intern een gerichte grafiek waarbij doelen de knooppunten van de grafiek zijn en de randvereisten de randen zijn. Pas nadat alle makefiles volledig zijn ontleed en de grafiek is voltooid zal make
kiezen het ene knooppunt (doel) en proberen om het up to date te brengen. Om ervoor te zorgen dat een doelwit up-to-date is, moet het er eerst voor zorgen dat alle vereisten van dat doel up-to-date zijn, enzovoort, recursief.
versies
Naam | Ook gekend als | Eerste versie | Versie | Publicatiedatum |
---|---|---|---|---|
POSIX maken | 1992 | IEEE Std 1003.1-2008, 2016-editie | 2016/09/30 | |
NetBSD maken | BLet | 1988 | 20160926 | 2016/09/26 |
GNU maken | gmake | 1988 | 4.2.1 | 2016/06/10 |
SunPro maken | DMaak | 2006 | 2015/07/13 | |
MSVS nmake | 2003 | 2015p3 | 2016/06/27 |
Basis Makefile
Overweeg het schrijven van een "hallo wereld!" programma in c. Laten we zeggen dat onze broncode zich in een bestand met de naam source.c bevindt. Om ons programma te kunnen uitvoeren, moeten we het compileren, meestal op Linux (met gcc) moeten we $> gcc source.c -o output
waar output is de naam van het te genereren uitvoerbare bestand. Voor een basisprogramma werkt dit goed, maar naarmate programma's complexer worden, kan onze compilatieopdracht ook complexer worden. Dit is waar een Makefile binnenkomt, met makefiles kunnen we een vrij complexe set regels schrijven voor het compileren van een programma en het vervolgens eenvoudig compileren door make op de opdrachtregel te typen. Hier is bijvoorbeeld een mogelijk voorbeeld Makefile voor het hallo wold voorbeeld hierboven.
Basis Makefile
Laten we een basis Makefile maken en opslaan op ons systeem in dezelfde map als onze broncode met de naam Makefile . Merk op dat dit bestand de naam Makefile moet hebben, maar de hoofdstad M is optioneel. Dat gezegd hebbende, het is relatief standaard om een capitol M te gebruiken.
output: source.c
gcc source.c -o output
Merk op dat er precies één tabblad is vóór de opdracht gcc op de tweede regel (dit is belangrijk in makefiles). Zodra dit Makefile is geschreven, elke keer dat de gebruikerstypes make (in dezelfde map als de Makefile) make zal controleren of source.c is gewijzigd (controleert de tijdstempel) of het recenter is gewijzigd dan de uitvoer zal uitvoeren de compilatieregel op de volgende regel.
Variabelen in Makefiles
Afhankelijk van het project wilt u misschien enkele variabelen aan uw make-bestand toevoegen. Hier is een voorbeeld van Makefile met aanwezige variabelen.
CFLAGS = -g -Wall
output: source.c
gcc $< $(CFLAGS) -o $@
Laten we nu eens kijken wat hier is gebeurd. In de eerste regel hebben we een variabele met de naam CFLAGS aangegeven die verschillende veelvoorkomende vlaggen bevat die je mogelijk aan de compiler wilt doorgeven. Houd er rekening mee dat je zoveel vlaggen kunt opslaan als je wilt in deze variabele. Dan hebben we dezelfde regel als voorheen aan make vertellen om source.c te controleren om te zien of het recenter is gewijzigd dan output, zo ja, dan wordt de compilatieregel uitgevoerd. Onze compilatieregel is meestal dezelfde als voorheen, maar deze is ingekort met behulp van variabelen, de variabele $<
is ingebouwd in make (aangeduid als een automatische variabele zie https://www.gnu.org/software/make/manual/ html_node / Automatic-Variables.html ) en het staat altijd voor de bron, dus in dit geval source.c . $(CFLAGS)
is onze variabele die we eerder hebben gedefinieerd, maar merk op dat we de variabele tussen haakjes moesten plaatsen met een $ vooraan zoals deze $(someVariable)
. Dit is de syntaxis om Make te vertellen de variabele uit te breiden naar wat u eerder hebt getypt. Eindelijk hebben we het $ @ symbool, wederom is dit een variabele ingebouwd in make, en het staat gewoon voor het doel van de compilatiestap, dus in dit geval staat het voor output .
Schoon
Maak schoon is een ander handig concept om te leren over het maken van bestanden. Laat het Makefile van bovenaf wijzigen
CFLAGS = -g -Wall
TARGETS = output
output: source.c
gcc $< $(CFLAGS) -o $@
clean:
rm $(TARGETS)
Zoals u kunt zien, hebben we eenvoudig nog een regel toegevoegd aan onze Makefile en een extra variabele die al onze doelen bevat. Dit is een enigszins gebruikelijke regel in makefiles, omdat je hiermee snel alle door jou geproduceerde binaire bestanden kunt verwijderen door $> make clean
typen. Door make clean te typen, laat u het make-programma de schoonregel uitvoeren en maakt make vervolgens de opdracht rm om al uw doelen te verwijderen.
Ik hoop dat dit korte overzicht van het gebruik van make u helpt uw workflow te versnellen, Makefiles kan erg complex worden, maar met deze ideeën moet u aan de slag kunnen gaan met make en een beter begrip hebben van wat er gaande is in andere Makefiles- programmeurs. Voor meer informatie over het gebruik van make a excellent resource is https://www.gnu.org/software/make/manual/ .
Regels definiëren
Snelle start
Een regel beschrijft wanneer en hoe bepaalde bestanden ( doelen van de regel) worden gemaakt. Het kan ook dienen om een doelbestand bij te werken als een van de bestanden die nodig zijn voor het maken ervan (de vereisten van het doel) nieuwer is dan het doel.
Regels volgen de onderstaande syntaxis: (Houd er rekening mee dat opdrachten die een regel volgen, worden ingesprongen door een tabblad )
targets: prerequisites
<commands>
waarbij doelen en vereisten bestandsnamen of speciale gereserveerde namen zijn en commando's (indien aanwezig) worden uitgevoerd door een shell om doelen te bouwen / opnieuw op te bouwen die verouderd zijn.
Om een regel uit te voeren, kunt u eenvoudig de opdracht make
in de terminal uitvoeren vanuit dezelfde map waar de Makefile zich bevindt. Als u make
uitvoert zonder het doel op te geven, wordt de eerste regel uitgevoerd die is gedefinieerd in de Makefile . Volgens afspraak wordt de eerste regel in de Makefile vaak alles of standaard genoemd , waarbij gewoonlijk alle geldige builddoelen als voorwaarden worden vermeld.
make
voert de regel alleen uit als het doel verouderd is, wat betekent dat het niet bestaat of dat de wijzigingstijd ouder is dan een van de vereisten. Als de lijst met vereisten leeg is, wordt de regel alleen uitgevoerd wanneer deze voor het eerst wordt opgeroepen om de doelen op te bouwen. Als de regel echter geen bestand maakt en het doel een dummy-variabele is, wordt de regel altijd uitgevoerd.
Patroonregels
Patroonregels worden gebruikt om meerdere doelen op te geven en vereiste namen uit doelnamen samen te stellen. Ze zijn algemener en krachtiger in vergelijking met gewone regels, omdat elk doelwit zijn eigen vereisten kan hebben. In patroonregels wordt een relatie tussen een doel en een voorwaarde opgebouwd op basis van voorvoegsels, inclusief padnamen en achtervoegsels, of beide.
Stel je voor dat we de doelen foo.o
en bar.o
willen bouwen, door respectievelijk C-scripts, foo.c
en bar.c
compileren. Dit kan worden gedaan met behulp van de onderstaande gewone regels:
foo.o: foo.c
cc -c $< -o $@
bar.o: bar.c
cc -c $< -o $@
waar de automatische variabele $<
is de naam van de eerste vereiste en $@
de naam van het doel (Een volledige lijst van de automatische variabelen kunnen worden gevonden hier ).
Omdat de doelen hetzelfde achtervoegsel delen, kunnen de bovenstaande twee regels nu worden vervangen door de volgende patroonregel:
%.o: %.c
cc -c $< -o $@
Impliciete regels
Impliciete regels vertellen make
hoe gebruikelijke methoden gebruiken om bepaalde types van target bestanden, die vaak worden gebruikt op te bouwen. make
gebruikt de doelbestandsnaam om te bepalen welke impliciete regel moet worden aangeroepen.
Het voorbeeld van de patroonregel dat we in de vorige sectie hebben gezien, hoeft eigenlijk niet in een Makefile te worden gedeclareerd omdat make
een impliciete regel voor C-compilatie heeft. In de volgende regel worden dus de vereisten foo.o
en bar.o
gebouwd met behulp van de impliciete regel voor C-compilatie, voordat foo
.
foo : foo.o bar.o
cc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)
Een catalogus van impliciete regels en de door hen gebruikte variabelen vindt u hier .
generieke regel om een bestand te gzipen
als een map 2 bestanden bevat:
$ ls
makefile
example.txt
en makefile
bevatten de volgende tekst
%.gz: %
gzip $<
dan kun je example.txt.gz
verkrijgen door de shell in te typen
$ make -f makefile example.txt.gz
de makefile bestaan uit slechts één regel die instrueren maken hoe u een bestand waarvan de naam eindigen met .gz te maken als er een bestand met dezelfde naam, maar de .gz suffix.
makefile Hallo wereld
C: \ makefile:
helloWorld :
[TAB]echo hello world
resultaten uitvoeren:
C:\>make
echo hello world
hello world
Opmerking: [TAB] moet worden vervangen door een echt tabblad, stackoverflow vervangt tabbladen door spaties en spaties worden niet hetzelfde gebruikt als tabbladen in een maakbestand.