c makefile tutorial
In deze C ++ Makefile-zelfstudie bespreken we de belangrijkste aspecten van Make-tool en makefile, inclusief de voordelen en toepassingen in C ++:
In elk C ++ -project is een van de belangrijke doelen om het bouwen van het project te vereenvoudigen, zodat we alle afhankelijkheden en projectbestanden op één plek krijgen en ze in één keer uitvoeren, zodat we de gewenste uitvoer krijgen met een enkele opdracht.
Vragen en antwoorden voor Java-ontwikkelaarsinterviews
Tegelijkertijd hoeven we, telkens wanneer een van de projectbestanden wordt gewijzigd, niet de moeite te nemen om het hele project opnieuw op te bouwen, dwz wanneer een of twee bestanden in het project worden gewijzigd, bouwen we alleen deze gewijzigde bestanden opnieuw op en gaan dan verder met de uitvoering.
Lees de Easy C ++ Training Series door.
Dit zijn precies de functies die worden aangepakt door de tool 'make' en 'makefiles' in C ++. In deze tutorial bespreken we alle belangrijke aspecten van makefiles en hun toepassingen in C ++.
Wat je leert:
Gereedschap maken
Make is een UNIX-tool en wordt gebruikt als een tool om het bouwen van een uitvoerbaar bestand uit verschillende modules van een project te vereenvoudigen. Er zijn verschillende regels die zijn gespecificeerd als doelitems in het makefile. De make-tool leest al deze regels en gedraagt zich dienovereenkomstig.
Bijvoorbeeld, als een regel een afhankelijkheid specificeert, zal de make-tool die afhankelijkheid opnemen voor compilatiedoeleinden. Het make commando wordt gebruikt in het makefile om modules te bouwen of om de bestanden op te schonen.
De algemene syntaxis van make is:
Bijvoorbeeld , als we rm-opdrachten willen uitvoeren om bestanden op te schonen, schrijven we:
% make clean #here clean is een target_label gespecificeerd voor rm-opdrachten
C ++ Makefile
Een makefile is niets anders dan een tekstbestand dat wordt gebruikt of waarnaar wordt verwezen door het 'make'-commando om de doelen te bouwen. Een makefile bevat ook informatie zoals afhankelijkheden op bronniveau voor elk bestand, evenals de afhankelijkheden van de bouwvolgorde.
Laten we nu eens kijken naar de algemene structuur van makefile.
Een makefile begint meestal met declaraties van variabelen, gevolgd door een reeks doelitems voor het bouwen van specifieke doelen. Deze doelen kunnen .o of andere uitvoerbare bestanden in C of C ++ en .class-bestanden in Java zijn.
We kunnen ook een set doelitems hebben voor het uitvoeren van een set opdrachten die zijn gespecificeerd door het doellabel.
Dus een generiek makefile is zoals hieronder getoond:
Een eenvoudig voorbeeld van het makefile wordt hieronder getoond.
In het bovenstaande makefile hebben we twee doellabels gespecificeerd, de eerste is het label ‘all’ om een uitvoerbaar bestand op te bouwen van myprogram- en mylib-objectbestanden. Het tweede doellabel ‘clean’ verwijdert alle bestanden met de naam ‘myprogram’.
Laten we een andere variant van het makefile bekijken.
Zoals getoond in het bovenstaande voorbeeld, maken we in dit makefile gebruik van de variabele ‘CC’ die de compilerwaarde bevat die we gebruiken (in dit geval GCC). Een andere variabele ‘CFLAGS’ bevat de compilervlaggen die we zullen gebruiken.
De derde variabele ‘TARGET’ bevat de naam van het programma waarvoor we het uitvoerbare bestand moeten bouwen.
Het meetvoordeel van deze variatie van de makefile is dat we alleen de waarden hoeven te veranderen van de variabelen die we hebben gebruikt telkens als er een wijziging is in de compiler, compilervlaggen of de naam van het uitvoerbare programma.
Voorbeeld van merk en makefile
Beschouw een programmavoorbeeld met de volgende bestanden:
- Main.cpp: Hoofdstuurprogramma
- Punt.h: Header-bestand voor puntklasse
- Point.cpp: CPP-implementatiebestand voor puntklasse
- Square.h: Kopbestand voor vierkante klasse
- Square.cpp; CPP-implementatiebestand voor vierkante klasse
Met de hierboven gegeven .cpp- en .h-bestanden, moeten we deze bestanden afzonderlijk compileren om .o-bestanden te genereren en ze vervolgens linken naar het uitvoerbare bestand met de naam main.
Vervolgens compileren we deze bestanden afzonderlijk.
- g ++ -c main.cpp: genereert main.o
- g ++ -c punt.cpp: genereert een punt. o
- g ++ -c vierkant.cpp: genereert square.o
Vervolgens koppelen we de objectbestanden aan elkaar om het uitvoerbare hoofdbestand te genereren.
g ++ -o main main.o point.o square.o
Vervolgens moeten we beslissen welke van de bestanden we opnieuw moeten compileren en opnieuw moeten genereren wanneer bepaalde delen van het programma worden bijgewerkt. Hiervoor hebben we een afhankelijkheidsgrafiek dat toont verschillende afhankelijkheden voor elk van de implementatiebestanden.
Hieronder vindt u de afhankelijkheidstabel voor de bovenstaande bestanden.
Dus in de bovenstaande afhankelijkheidsgrafiek kunnen we het uitvoerbare ‘main’ in de root zien. Het uitvoerbare ‘main’ bestaat uit objectbestanden, namelijk. main.o, point.o, square.o die wordt gegenereerd door respectievelijk main.cpp, point.cpp en square.cpp te compileren.
Alle cpp-implementaties gebruiken header-bestanden zoals weergegeven in de bovenstaande grafiek. Zoals hierboven getoond, verwijst main.cpp zowel naar point.h als square.h omdat het het stuurprogramma is en punt- en kwadratenklassen gebruikt.
Het volgende bestand point.cpp verwijst naar point.h. Het derde bestand square.cpp verwijst zowel naar square.h als naar point.h, omdat het ook een punt nodig heeft om het vierkant te tekenen.
Uit de afhankelijkheidstabel hierboven is het duidelijk dat wanneer een .cpp-bestand of .h-bestand waarnaar wordt verwezen door .cpp-bestanden, we dat .o-bestand opnieuw moeten genereren. Bijvoorbeeld, wanneer main.cpp verandert, moeten we de main.o opnieuw genereren en de objectbestanden opnieuw koppelen om het hoofduitvoerbare bestand te genereren.
Alle bovenstaande uitleg die we hebben gegeven, zal probleemloos werken als er weinig bestanden in het project zijn. Als het project enorm is en de bestanden groot en te veel, wordt het moeilijk om de bestanden herhaaldelijk opnieuw te genereren.
Daarom gaan we voor het maken van bestanden en gebruiken we om een tool te maken om het project te bouwen en het uitvoerbare bestand te genereren.
We hebben al verschillende onderdelen van een merkbestand gezien. Merk op dat het bestand de naam 'MAKEFILE' of ‘makefile’ moet hebben en in de bronmap moet worden geplaatst.
Nu zullen we het makefile voor het bovenstaande voorbeeld opschrijven.
We zullen variabelen definiëren om de waarden van compiler- en compilervlaggen vast te houden, zoals hieronder wordt weergegeven.
Vervolgens maken we het eerste doel in ons makefile, d.w.z. het uitvoerbare hoofdbestand. Dus we schrijven een doel met zijn afhankelijkheden.
main: main.o point.o square.o
Het commando om dit doel te genereren is dus
Notitie: De bovenstaande opdracht vertaalt zich in feite in g ++ -wall –g –o main main.o point.o square.o
Ons volgende doel is het genereren van objectbestanden, main.o, point.o, square.o
Om nu main.o te genereren, zal het doel worden geschreven als:
Het commando voor dit doel is:
Het volgende bestand point.o kan worden gegenereerd met het onderstaande commando:
In het bovenstaande commando hebben we point.cpp overgeslagen. Dit komt omdat make al weet dat .o-bestanden worden gegenereerd uit de .cpp-bestanden, dus alleen .h (include-bestand) is voldoende.
Evenzo kan square.o worden gegenereerd met het volgende commando.
Het volledige makefile voor dit voorbeeld zal er als volgt uitzien:
We zien dus dat we een compleet makefile hebben dat drie C ++ -bestanden compileert en vervolgens een uitvoerbaar hoofdbestand genereert uit de objectbestanden.
Voordelen van Makefiles
- Als het om grote projecten gaat, helpt het gebruik van makefiles ons om het project op een systematische en efficiënte manier weer te geven.
- Makefiles maken de broncode beknopter en gemakkelijker te lezen en debuggen.
- Makefiles compileert automatisch alleen die bestanden die zijn gewijzigd. We hoeven dus niet het hele project opnieuw te genereren wanneer sommige delen van het project worden gewijzigd.
- Met de Make-tool kunnen we meerdere bestanden tegelijk compileren, zodat alle bestanden in één stap kunnen worden gecompileerd.
Gevolgtrekking
Makefiles zijn een zegen voor softwareontwikkeling. Met behulp van een C ++ makefile kunnen we oplossingen bouwen in minder tijd. Ook wanneer een deel van het project wordt gewijzigd, compileert en regenereert de makefile alleen dat deel zonder het hele project opnieuw te hoeven genereren.
C ++ Makefile stelt ons in staat om het project systematisch en efficiënt weer te geven, waardoor het beter leesbaar en gemakkelijk te debuggen wordt.
In deze C ++ Makefile-zelfstudie hebben we makefile gezien en tools in detail gemaakt. We hebben ook besproken hoe je vanaf nul een makefile kunt schrijven.
Bekijk hier de perfecte C ++ trainingsgids.
Aanbevolen literatuur
- 70+ BESTE C ++ Tutorials om GRATIS C ++ Programmeren te leren
- Dev C ++ IDE: installatie, functies en C ++ ontwikkeling
- Een compleet overzicht van C ++
- VBScript-bestandsobjecten: CopyFile, DeleteFile, OpenTextFile, Read en Write Text File
- Zelfstudie voor Python-bestandsafhandeling: maken, openen, lezen, schrijven
- Unix-bestandssysteemopdrachten Touch, Cat, Cp, Mv, Rm, Mkdir (deel B)
- 12 beste Python IDE's en code-editors in 2021
- Top 15 beste gratis code-editors voor een perfecte codeerervaring