c makefile tutorial
In diesem C ++ Makefile-Tutorial werden die wichtigsten Aspekte des Make-Tools und des Makefiles einschließlich seiner Vorteile und Anwendungen in C ++ erläutert:
In jedem C ++ - Projekt besteht eines der wichtigen Ziele darin, die Erstellung des Projekts so zu vereinfachen, dass alle Abhängigkeiten und Projektdateien an einem Ort abgerufen und auf einmal ausgeführt werden, sodass wir mit einem einzigen Befehl die gewünschte Ausgabe erhalten.
wie man doppelt verknüpfte Liste in Java implementiert
Gleichzeitig müssen wir uns nicht die Mühe machen, das gesamte Projekt erneut zu erstellen, wenn eine oder zwei Dateien im Projekt geändert werden. Wenn also eine oder zwei Dateien im Projekt geändert werden, erstellen wir nur diese geänderten Dateien neu und fahren dann fort mit der Ausführung.
=> Lesen Sie die Easy C ++ - Schulungsserie durch.
Dies sind genau die Funktionen, die vom Tool 'make' und 'makefiles' in C ++ angesprochen werden. In diesem Tutorial werden alle wichtigen Aspekte von Makefiles sowie deren Anwendungen in C ++ erläutert.
Was du lernen wirst:
Werkzeug herstellen
Make ist ein UNIX-Tool und wird als Tool verwendet, um das Erstellen von ausführbaren Dateien aus verschiedenen Modulen eines Projekts zu vereinfachen. Es gibt verschiedene Regeln, die als Zieleinträge im Makefile angegeben werden. Das make-Tool liest alle diese Regeln und verhält sich entsprechend.
Zum Beispiel, Wenn eine Regel eine Abhängigkeit angibt, enthält das make-Tool diese Abhängigkeit für Kompilierungszwecke. Der Befehl make wird im Makefile verwendet, um Module zu erstellen oder die Dateien zu bereinigen.
Die allgemeine Syntax von make lautet:
%make target_label #target_label is a specific target in makefile
Zum Beispiel Wenn wir rm-Befehle ausführen möchten, um Dateien zu bereinigen, schreiben wir:
% make clean #here clean ist ein target_label, das für rm-Befehle angegeben wurde
C ++ Makefile
Ein Makefile ist nichts anderes als eine Textdatei, die vom Befehl 'make' zum Erstellen der Ziele verwendet oder referenziert wird. Ein Makefile enthält auch Informationen wie Abhängigkeiten auf Quellenebene für jede Datei sowie die Abhängigkeiten der Erstellungsreihenfolge.
Lassen Sie uns nun die allgemeine Struktur von Makefile sehen.
Ein Makefile beginnt normalerweise mit Variablendeklarationen, gefolgt von einer Reihe von Zieleinträgen zum Erstellen bestimmter Ziele. Diese Ziele können O- oder andere ausführbare Dateien in C oder C ++ und Klassendateien in Java sein.
Wir können auch eine Reihe von Zieleinträgen zum Ausführen einer Reihe von Befehlen haben, die durch die Zielbezeichnung angegeben sind.
Ein generisches Makefile sieht also wie folgt aus:
# comment target: dependency1 dependency2 ... dependencyn command # (note: the in the command line is necessary for make to work)
Ein einfaches Beispiel für das Makefile ist unten dargestellt.
# a build command to build myprogram executable from myprogram.o and mylib.lib all:myprogram.o mylib.o gcc –o myprogram myprogram.o mylib.o clean: $(RM) myprogram
Im obigen Makefile haben wir zwei Zielbezeichnungen angegeben. Die erste ist die Bezeichnung 'all', mit der eine ausführbare Datei aus myprogram- und mylib-Objektdateien erstellt werden soll. Die zweite Zielbezeichnung 'sauber' entfernt alle Dateien mit dem Namen 'myprogram'.
Sehen wir uns eine weitere Variante des Makefiles an.
# the compiler: gcc for C program, define as g++ for C++ CC = gcc # compiler flags: # -g - this flag adds debugging information to the executable file # -Wall - this flag is used to turn on most compiler warnings CFLAGS = -g -Wall # The build target TARGET = myprogram all: $(TARGET) $(TARGET): $(TARGET).c $(CC) $(CFLAGS) -o $(TARGET) $(TARGET).c clean: $(RM) $(TARGET)
Wie im obigen Beispiel gezeigt, verwenden wir in diesem Makefile die Variable 'CC', die den von uns verwendeten Compilerwert enthält (in diesem Fall GCC). Eine andere Variable 'CFLAGS' enthält die Compiler-Flags, die wir verwenden werden.
Die dritte Variable 'TARGET' enthält den Namen des Programms, für das wir die ausführbare Datei erstellen müssen.
Der Messvorteil dieser Variation des Makefiles besteht darin, dass wir nur die Werte der Variablen ändern müssen, die wir verwendet haben, wenn sich der Compiler, die Compiler-Flags oder der Name des ausführbaren Programms ändern.
Beispiel für Make und Makefile
Betrachten Sie ein Programmbeispiel mit den folgenden Dateien:
- Main.cpp: Haupttreiberprogramm
- Point.h: Header-Datei für Punktklasse
- Point.cpp: CPP-Implementierungsdatei für Punktklasse
- Square.h: Header-Datei für quadratische Klasse
- Square.cpp; CPP-Implementierungsdatei für die Quadratklasse
Mit den oben angegebenen .cpp- und .h-Dateien müssen wir diese Dateien separat kompilieren, um .o-Dateien zu generieren und sie dann in die ausführbare Datei mit dem Namen main zu verknüpfen.
Als nächstes kompilieren wir diese Dateien separat.
- g ++ -c main.cpp: generiert main.o.
- g ++ -c point.cpp: erzeugt einen point.o
- g ++ -c square.cpp: erzeugt square.o
Als nächstes verknüpfen wir die Objektdateien miteinander, um die ausführbare Hauptdatei zu generieren.
g ++ -o main main.o point.o square.o
Als nächstes müssen wir entscheiden, welche der Dateien neu kompiliert und neu generiert werden müssen, wenn bestimmte Teile des Programms aktualisiert werden. Dafür haben wir eine Abhängigkeitsdiagramm Das zeigt verschiedene Abhängigkeiten für jede der Implementierungsdateien.
Unten ist das Abhängigkeitsdiagramm für die obigen Dateien angegeben.
In der obigen Abhängigkeitsübersicht sehen wir also die ausführbare Datei 'main' im Stammverzeichnis. Die ausführbare Datei 'main' besteht aus Objektdateien, d. H. main.o, point.o, square.o, die durch Kompilieren von main.cpp, point.cpp bzw. square.cpp generiert werden.
Alle cpp-Implementierungen verwenden Header-Dateien, wie in der obigen Tabelle gezeigt. Wie oben gezeigt, verweist main.cpp sowohl auf point.h als auch auf square.h, da es das Treiberprogramm ist und Punkt- und Quadratklassen verwendet.
Die nächste Datei point.cpp verweist auf point.h. Die dritte Datei square.cpp verweist sowohl auf square.h als auch auf point.h, da zum Zeichnen des Quadrats ebenfalls ein Punkt erforderlich ist.
Aus der obigen Abhängigkeitstabelle geht hervor, dass wir diese O-Datei immer dann neu generieren müssen, wenn sich eine CPP-Datei oder eine H-Datei ändert, auf die durch eine CPP-Datei verwiesen wird. Zum Beispiel, Wenn sich main.cpp ändert, müssen wir die Datei main.o neu generieren und die Objektdateien erneut verknüpfen, um die ausführbare Hauptdatei zu generieren.
Alle oben genannten Erklärungen funktionieren reibungslos, wenn das Projekt nur wenige Dateien enthält. Wenn das Projekt riesig ist und die Dateien groß und zu viele sind, wird es schwierig, die Dateien wiederholt neu zu generieren.
Daher erstellen wir Dateien und erstellen ein Tool zum Erstellen des Projekts und zum Generieren der ausführbaren Datei.
Wir haben bereits verschiedene Teile einer make-Datei gesehen. Beachten Sie, dass die Datei den Namen 'MAKEFILE' oder 'makefile' haben und im Quellordner abgelegt werden sollte.
Jetzt werden wir das Makefile für das obige Beispiel aufschreiben.
Wir werden Variablen definieren, die die Werte von Compiler- und Compiler-Flags enthalten, wie unten gezeigt.
CC = g++ CFLAGS = -wall -g
Dann erstellen wir das erste Ziel in unserem Makefile, d. H. Das ausführbare Hauptziel. Also schreiben wir ein Ziel mit seinen Abhängigkeiten.
main: main.o point.o square.o
Somit lautet der Befehl zum Generieren dieses Ziels
$(CC) $(CFLAGS) –o main main.o point.o square.o
Hinweis: Der obige Befehl übersetzt tatsächlich in g ++ -wall –g –o main main.o point.o square.o
Unser nächstes Ziel wird es sein, Objektdateien zu generieren, main.o, point.o, square.o
Um main.o zu generieren, wird das Ziel wie folgt geschrieben:
Main.o: main.cpp point.h square.h
Der Befehl für dieses Ziel lautet:
$(CC) $(CFLAGS) –c main.cpp
Die nächste Datei point.o kann mit dem folgenden Befehl generiert werden:
$(CC) $(CFLAGS) –c point.h
Im obigen Befehl haben wir point.cpp übersprungen. Dies liegt daran, dass make bereits weiß, dass .o-Dateien aus den .cpp-Dateien generiert werden, sodass nur .h (Include-Datei) ausreicht.
Ebenso kann square.o mit dem folgenden Befehl generiert werden.
$(CC) $(CFLAGS) –c square.h point.h
Das gesamte Makefile für dieses Beispiel sieht wie folgt aus:
# Makefile for Writing Make Files Example # ***************************************************** # Variables to control Makefile operation CC = g++ CFLAGS = -Wall -g # **************************************************** # Targets needed to bring the executable up to date main: main.o Point.o Square.o $(CC) $(CFLAGS) -o main main.o Point.o Square.o # The main.o target can be written more simply main.o: main.cpp Point.h Square.h $(CC) $(CFLAGS) -c main.cpp Point.o: Point.h Square.o: Square.h Point.h
Wir sehen also, dass wir ein vollständiges Makefile haben, das drei C ++ - Dateien kompiliert und dann aus den Objektdateien eine ausführbare Hauptdatei generiert.
Vorteile von Makefiles
- Wenn es um große Projekte geht, hilft uns die Verwendung von Makefiles, das Projekt systematisch und effizient darzustellen.
- Makefiles machen den Quellcode übersichtlicher und einfacher zu lesen und zu debuggen.
- Makefiles kompilieren automatisch nur die Dateien, die geändert werden. Daher müssen wir nicht das gesamte Projekt neu generieren, wenn einige Teile des Projekts geändert werden.
- Mit dem Make-Tool können wir mehrere Dateien gleichzeitig kompilieren, sodass alle Dateien in einem einzigen Schritt kompiliert werden können.
Fazit
Makefiles sind ein Segen für die Softwareentwicklung. Mit einem C ++ - Makefile können wir Lösungen in kürzerer Zeit erstellen. Auch wenn ein Teil des Projekts geändert wird, kompiliert das Makefile nur diesen Teil neu und generiert ihn neu, ohne dass das gesamte Projekt neu generiert werden muss.
Mit C ++ Makefile können wir das Projekt systematisch und effizient darstellen, wodurch es lesbarer und einfacher zu debuggen ist.
In diesem C ++ Makefile-Tutorial haben wir Makefile und Make-Tools im Detail gesehen. Wir haben auch besprochen, wie man ein Makefile von Grund auf neu schreibt.
=> Lesen Sie hier den perfekten C ++ - Schulungsleitfaden.
Literatur-Empfehlungen
- Über 70 BEST C ++ - Tutorials zum kostenlosen Erlernen der C ++ - Programmierung
- Dev C ++ IDE: Installation, Funktionen und C ++ - Entwicklung
- Ein vollständiger Überblick über C ++
- VBScript-Dateiobjekte: CopyFile, DeleteFile, OpenTextFile, Read and Write Text File
- Tutorial zur Handhabung von Python-Dateien: Erstellen, Öffnen, Lesen, Schreiben
- Unix-Dateisystembefehle Touch, Cat, Cp, Mv, Rm, Mkdir (Teil B)
- 12 besten Python-IDEs und Code-Editoren im Jahr 2021
- Top 15 der besten kostenlosen Code-Editoren für ein perfektes Codierungserlebnis