Make: Unterschied zwischen den Versionen
Die Seite wurde neu angelegt: „**`make`** ist ein Build-Automatisierungstool, das häufig in Softwareprojekten verwendet wird, um Programme aus Quellcode zu kompilieren. Das GNU `make`-Programm führt Anweisungen aus, die in einer **Makefile**-Datei definiert sind, und entscheidet, welche Teile eines Projekts neu kompiliert oder neu erstellt werden müssen, indem es Abhängigkeiten zwischen Dateien analysiert und Zeitstempel prüft. Das Hauptziel von `make` ist es, den Build-Prozess zu…“ |
K →Fazit |
||
| (5 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
| Zeile 1: | Zeile 1: | ||
'''make''' ist ein Build-Automatisierungstool, das häufig in Softwareprojekten verwendet wird, um Programme aus Quellcode zu kompilieren. Das GNU `make`-Programm führt Anweisungen aus, die in einer ''Makefile''-Datei definiert sind, und entscheidet, welche Teile eines Projekts neu kompiliert oder neu erstellt werden müssen, indem es Abhängigkeiten zwischen Dateien analysiert und Zeitstempel prüft. Das Hauptziel von `make` ist es, den Build-Prozess zu automatisieren, um sicherzustellen, dass nur notwendige Teile eines Projekts neu erstellt werden, was die Entwicklungszeit erheblich verkürzt. | |||
== Grundkonzepte von `make` == | |||
'''Makefile''': | |||
* Ein Makefile ist eine Datei, die die Regeln und Abhängigkeiten beschreibt, die `make` verwendet, um ein Projekt zu bauen. Es enthält Anweisungen, welche Dateien erstellt werden müssen und wie sie erstellt werden. | |||
* Ein einfaches Makefile könnte so aussehen: | |||
:<syntaxhighlight lang="makefile"> | |||
all: meinprogramm | all: meinprogramm | ||
| Zeile 20: | Zeile 20: | ||
clean: | clean: | ||
rm -f *.o meinprogramm | rm -f *.o meinprogramm | ||
</syntaxhighlight> | |||
: In diesem Beispiel definiert das Makefile Regeln, um die Objektdateien `main.o` und `utils.o` zu erstellen und sie anschließend zu einem ausführbaren Programm namens `meinprogramm` zu verknüpfen. Die Regel `clean` löscht alle generierten Dateien, um das Verzeichnis aufzuräumen. | |||
'''Ziele (Targets)''': | |||
* Ein '''Ziel''' ist eine Datei, die von einer Regel erstellt wird. Zum Beispiel ist `meinprogramm` in dem obigen Makefile ein Ziel. Jedes Ziel ist entweder eine Datei, die erstellt wird, oder eine Aktion, die ausgeführt wird (z.B. `clean`, das keine Datei erzeugt, sondern das Verzeichnis säubert). | |||
'''Abhängigkeiten''': | |||
* Jedes Ziel hat '''Abhängigkeiten'''. Dies sind Dateien, von denen das Ziel abhängt. Wenn eine dieser Abhängigkeitsdateien neuer ist als das Ziel, wird das Ziel neu erstellt. | |||
* Im obigen Beispiel hängt `meinprogramm` von den Dateien `main.o` und `utils.o` ab. Wenn eine dieser Dateien geändert wurde, wird `meinprogramm` neu erstellt. | |||
'''Regeln (Recipes)''': | |||
* Eine '''Regel''' gibt an, wie ein Ziel aus seinen Abhängigkeiten erstellt wird. Jede Regel besteht aus einem Ziel, einer Liste von Abhängigkeiten und den Shell-Befehlen (das '''Recipe'''), die ausgeführt werden, um das Ziel zu erstellen. | |||
* Zum Beispiel gibt die Regel für `meinprogramm` an, dass es durch das Verknüpfen von `main.o` und `utils.o` mit dem Befehl `gcc -o meinprogramm main.o utils.o` erstellt wird. | |||
'''Phony Targets''': | |||
* '''Phony Targets''' sind Ziele, die keine echten Dateien darstellen, sondern Aktionen ausführen. Ein Beispiel ist `clean` im obigen Makefile, das den temporären Dateien wie `.o`-Dateien entfernt. Solche Ziele haben keine Abhängigkeit von einer Datei und werden jedes Mal ausgeführt, wenn sie explizit aufgerufen werden. | |||
* Du kannst ein Phony Target so kennzeichnen: | |||
:<syntaxhighlight lang="makefile"> | |||
.PHONY: clean | |||
clean: | |||
rm -f *.o meinprogramm | |||
</syntaxhighlight> | |||
== Funktionsweise von `make` == | |||
'''Zeitstempel''': | |||
* `make` entscheidet, ob ein Ziel neu gebaut werden muss, indem es die Zeitstempel der Abhängigkeiten und des Ziels vergleicht. Wenn eine Abhängigkeitsdatei neuer ist als das Ziel, wird das Ziel neu erstellt. Dies ist besonders nützlich, um nur die geänderten Teile eines großen Projekts zu kompilieren, was den Build-Prozess beschleunigt. | |||
'''Implizite Regeln''': | |||
* `make` verfügt über viele eingebaute Regeln, um häufig verwendete Aufgaben automatisch zu erledigen. Zum Beispiel weiß `make`, wie `.c`-Dateien zu `.o`-Dateien kompiliert werden können, ohne dass dies explizit in einem Makefile angegeben wird: | |||
:<syntaxhighlight lang="bash"> | |||
gcc -c file.c | gcc -c file.c | ||
</syntaxhighlight> | |||
'''Automatische Variablen''': | |||
* In den Regeln können automatische Variablen verwendet werden, um den Code im Makefile kompakter zu gestalten: | |||
: `$@`: Das aktuelle Ziel. | |||
: `$<`: Die erste Abhängigkeit (Source-Datei). | |||
: `$^`: Die Liste aller Abhängigkeiten. | |||
:: Beispiel: | |||
::<syntaxhighlight lang="makefile"> | |||
meinprogramm: main.o utils.o | meinprogramm: main.o utils.o | ||
gcc -o $@ $^ | gcc -o $@ $^ | ||
</syntaxhighlight> | |||
== Erweiterte Makefile-Features == | |||
'''Variablen''': | |||
* Du kannst Variablen verwenden, um das Makefile flexibler und leichter wartbar zu machen. Zum Beispiel: | |||
:<syntaxhighlight lang="makefile"> | |||
CC = gcc | |||
CFLAGS = -Wall -g | |||
all: meinprogramm | |||
meinprogramm: main.o utils.o | |||
$(CC) $(CFLAGS) -o meinprogramm main.o utils.o | |||
</syntaxhighlight> | |||
: Hier werden `CC` und `CFLAGS` als Variablen definiert und später in den Regeln verwendet. | |||
'''Musterregeln''': | |||
* Du kannst allgemeine Regeln für viele Dateien erstellen, indem du Platzhalter (z.B. `%`) verwendest. | |||
: Ein Beispiel für eine Musterregel: | |||
:<syntaxhighlight lang="makefile"> | |||
%.o: %.c | |||
gcc -c $< -o $@ | |||
</syntaxhighlight> | |||
: Diese Regel sagt `make`, wie es jede `.c`-Datei in eine `.o`-Datei umwandeln kann, ohne dass jede Datei explizit im Makefile aufgeführt werden muss. | |||
'''Include-Dateien''': | |||
* Große Makefiles können unübersichtlich werden, daher kann man Makefiles in kleinere Dateien aufteilen und sie mit `include` einbinden: | |||
:<syntaxhighlight lang="makefile"> | |||
include common.mk | include common.mk | ||
</syntaxhighlight> | |||
'''Bedarfsabhängiger Build (Dependency Generation)''': | |||
* Du kannst `make` so konfigurieren, dass es automatisch Abhängigkeiten für Header-Dateien generiert, sodass Änderungen an Header-Dateien die Kompilierung der betroffenen Quelldateien auslösen: | |||
:<syntaxhighlight lang="makefile"> | |||
depend: | depend: | ||
gcc -MM *.c > depend.mk | gcc -MM *.c > depend.mk | ||
include depend.mk | include depend.mk | ||
</syntaxhighlight> | |||
== Typische Anwendungsfälle von `make` == | |||
'''Kompilieren und Linken von Programmen''': | |||
`make` wird verwendet, um den Prozess des Kompilierens und Linkens großer Projekte mit vielen Quellcode-Dateien zu automatisieren. Wenn nur wenige Dateien geändert werden, kompiliert `make` nur diese Dateien, anstatt das gesamte Projekt neu zu bauen. | |||
'''Verwaltung von Softwareprojekten''': | |||
Projekte mit vielen Komponenten wie C/C++-Dateien, Java-Code oder Dokumentationsquellen (z.B. LaTeX) können mit einem Makefile einfach aufgebaut werden. | |||
'''Automatisierte Tests''': | |||
`make` kann verwendet werden, um Tests automatisch auszuführen, wenn du Änderungen an deinem Code vornimmst. Du könntest zum Beispiel eine Regel erstellen, um Unit-Tests nach jeder Kompilierung auszuführen. | |||
'''Deployment-Skripte''': | |||
Mit `make` können auch Deployment-Skripte oder andere automatisierte Aufgaben erstellt werden. Ein Ziel wie `deploy` könnte erstellt werden, um den Build-Prozess zu automatisieren, Dateien auf einen Server hochzuladen und Dienste neu zu starten. | |||
'''Beispiel für ein fortgeschrittenes Makefile''' | |||
<syntaxhighlight lang="makefile"> | |||
CC = gcc | CC = gcc | ||
CFLAGS = -Wall -O2 | CFLAGS = -Wall -O2 | ||
| Zeile 142: | Zeile 143: | ||
.PHONY: clean | .PHONY: clean | ||
</syntaxhighlight> | |||
* '''CC''' und '''CFLAGS''': Definieren den Compiler und die Kompilierungsoptionen. | |||
* '''SRC''' und '''OBJ''': Listen die Quell- und Objektdateien des Projekts auf. | |||
* Die Regel für `meinprogramm` verknüpft alle Objektdateien und erstellt das endgültige ausführbare Programm. | |||
* Die Musterregel `%.o: %.c` beschreibt, wie `.o`-Dateien aus `.c`-Dateien erstellt werden. | |||
== Fazit == | |||
GNU `make` ist ein vielseitiges und leistungsstarkes Werkzeug, das den Build-Prozess für Softwareprojekte automatisiert und beschleunigt. Durch die Definition von Regeln und Abhängigkeiten in einem Makefile können Entwickler effizient und gezielt nur die Teile eines Projekts neu bauen, die aktualisiert wurden, was sowohl Zeit spart als auch den Entwicklungsprozess optimiert. | GNU `make` ist ein vielseitiges und leistungsstarkes Werkzeug, das den Build-Prozess für Softwareprojekte automatisiert und beschleunigt. Durch die Definition von Regeln und Abhängigkeiten in einem Makefile können Entwickler effizient und gezielt nur die Teile eines Projekts neu bauen, die aktualisiert wurden, was sowohl Zeit spart als auch den Entwicklungsprozess optimiert. | ||
----- | |||
{| style="width: 100%; | |||
| style="width: 33%;" | [[objdump|< Zurück (objdump)]] | |||
| style="width: 33%; text-align:center;" | [[Hauptseite|< Hauptseite >]] | |||
| style="width: 33%; text-align:right;" | | |||
|} | |||
Aktuelle Version vom 24. September 2024, 08:18 Uhr
make ist ein Build-Automatisierungstool, das häufig in Softwareprojekten verwendet wird, um Programme aus Quellcode zu kompilieren. Das GNU `make`-Programm führt Anweisungen aus, die in einer Makefile-Datei definiert sind, und entscheidet, welche Teile eines Projekts neu kompiliert oder neu erstellt werden müssen, indem es Abhängigkeiten zwischen Dateien analysiert und Zeitstempel prüft. Das Hauptziel von `make` ist es, den Build-Prozess zu automatisieren, um sicherzustellen, dass nur notwendige Teile eines Projekts neu erstellt werden, was die Entwicklungszeit erheblich verkürzt.
Grundkonzepte von `make`
Makefile:
- Ein Makefile ist eine Datei, die die Regeln und Abhängigkeiten beschreibt, die `make` verwendet, um ein Projekt zu bauen. Es enthält Anweisungen, welche Dateien erstellt werden müssen und wie sie erstellt werden.
- Ein einfaches Makefile könnte so aussehen:
all: meinprogramm meinprogramm: main.o utils.o gcc -o meinprogramm main.o utils.o main.o: main.c gcc -c main.c utils.o: utils.c gcc -c utils.c clean: rm -f *.o meinprogramm
- In diesem Beispiel definiert das Makefile Regeln, um die Objektdateien `main.o` und `utils.o` zu erstellen und sie anschließend zu einem ausführbaren Programm namens `meinprogramm` zu verknüpfen. Die Regel `clean` löscht alle generierten Dateien, um das Verzeichnis aufzuräumen.
Ziele (Targets):
- Ein Ziel ist eine Datei, die von einer Regel erstellt wird. Zum Beispiel ist `meinprogramm` in dem obigen Makefile ein Ziel. Jedes Ziel ist entweder eine Datei, die erstellt wird, oder eine Aktion, die ausgeführt wird (z.B. `clean`, das keine Datei erzeugt, sondern das Verzeichnis säubert).
Abhängigkeiten:
- Jedes Ziel hat Abhängigkeiten. Dies sind Dateien, von denen das Ziel abhängt. Wenn eine dieser Abhängigkeitsdateien neuer ist als das Ziel, wird das Ziel neu erstellt.
- Im obigen Beispiel hängt `meinprogramm` von den Dateien `main.o` und `utils.o` ab. Wenn eine dieser Dateien geändert wurde, wird `meinprogramm` neu erstellt.
Regeln (Recipes):
- Eine Regel gibt an, wie ein Ziel aus seinen Abhängigkeiten erstellt wird. Jede Regel besteht aus einem Ziel, einer Liste von Abhängigkeiten und den Shell-Befehlen (das Recipe), die ausgeführt werden, um das Ziel zu erstellen.
- Zum Beispiel gibt die Regel für `meinprogramm` an, dass es durch das Verknüpfen von `main.o` und `utils.o` mit dem Befehl `gcc -o meinprogramm main.o utils.o` erstellt wird.
Phony Targets:
- Phony Targets sind Ziele, die keine echten Dateien darstellen, sondern Aktionen ausführen. Ein Beispiel ist `clean` im obigen Makefile, das den temporären Dateien wie `.o`-Dateien entfernt. Solche Ziele haben keine Abhängigkeit von einer Datei und werden jedes Mal ausgeführt, wenn sie explizit aufgerufen werden.
- Du kannst ein Phony Target so kennzeichnen:
.PHONY: clean clean: rm -f *.o meinprogramm
Funktionsweise von `make`
Zeitstempel:
- `make` entscheidet, ob ein Ziel neu gebaut werden muss, indem es die Zeitstempel der Abhängigkeiten und des Ziels vergleicht. Wenn eine Abhängigkeitsdatei neuer ist als das Ziel, wird das Ziel neu erstellt. Dies ist besonders nützlich, um nur die geänderten Teile eines großen Projekts zu kompilieren, was den Build-Prozess beschleunigt.
Implizite Regeln:
- `make` verfügt über viele eingebaute Regeln, um häufig verwendete Aufgaben automatisch zu erledigen. Zum Beispiel weiß `make`, wie `.c`-Dateien zu `.o`-Dateien kompiliert werden können, ohne dass dies explizit in einem Makefile angegeben wird:
gcc -c file.c
Automatische Variablen:
- In den Regeln können automatische Variablen verwendet werden, um den Code im Makefile kompakter zu gestalten:
- `$@`: Das aktuelle Ziel.
- `$<`: Die erste Abhängigkeit (Source-Datei).
- `$^`: Die Liste aller Abhängigkeiten.
- Beispiel:
meinprogramm: main.o utils.o gcc -o $@ $^
Erweiterte Makefile-Features
Variablen:
- Du kannst Variablen verwenden, um das Makefile flexibler und leichter wartbar zu machen. Zum Beispiel:
CC = gcc CFLAGS = -Wall -g all: meinprogramm meinprogramm: main.o utils.o $(CC) $(CFLAGS) -o meinprogramm main.o utils.o
- Hier werden `CC` und `CFLAGS` als Variablen definiert und später in den Regeln verwendet.
Musterregeln:
- Du kannst allgemeine Regeln für viele Dateien erstellen, indem du Platzhalter (z.B. `%`) verwendest.
- Ein Beispiel für eine Musterregel:
%.o: %.c gcc -c $< -o $@
- Diese Regel sagt `make`, wie es jede `.c`-Datei in eine `.o`-Datei umwandeln kann, ohne dass jede Datei explizit im Makefile aufgeführt werden muss.
Include-Dateien:
- Große Makefiles können unübersichtlich werden, daher kann man Makefiles in kleinere Dateien aufteilen und sie mit `include` einbinden:
include common.mk
Bedarfsabhängiger Build (Dependency Generation):
- Du kannst `make` so konfigurieren, dass es automatisch Abhängigkeiten für Header-Dateien generiert, sodass Änderungen an Header-Dateien die Kompilierung der betroffenen Quelldateien auslösen:
depend: gcc -MM *.c > depend.mk include depend.mk
Typische Anwendungsfälle von `make`
Kompilieren und Linken von Programmen: `make` wird verwendet, um den Prozess des Kompilierens und Linkens großer Projekte mit vielen Quellcode-Dateien zu automatisieren. Wenn nur wenige Dateien geändert werden, kompiliert `make` nur diese Dateien, anstatt das gesamte Projekt neu zu bauen.
Verwaltung von Softwareprojekten: Projekte mit vielen Komponenten wie C/C++-Dateien, Java-Code oder Dokumentationsquellen (z.B. LaTeX) können mit einem Makefile einfach aufgebaut werden.
Automatisierte Tests: `make` kann verwendet werden, um Tests automatisch auszuführen, wenn du Änderungen an deinem Code vornimmst. Du könntest zum Beispiel eine Regel erstellen, um Unit-Tests nach jeder Kompilierung auszuführen.
Deployment-Skripte: Mit `make` können auch Deployment-Skripte oder andere automatisierte Aufgaben erstellt werden. Ein Ziel wie `deploy` könnte erstellt werden, um den Build-Prozess zu automatisieren, Dateien auf einen Server hochzuladen und Dienste neu zu starten.
Beispiel für ein fortgeschrittenes Makefile
CC = gcc
CFLAGS = -Wall -O2
LDFLAGS = -lm
SRC = main.c utils.c
OBJ = $(SRC:.c=.o)
all: meinprogramm
meinprogramm: $(OBJ)
$(CC) -o $@ $(OBJ) $(LDFLAGS)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OBJ) meinprogramm
.PHONY: clean
- CC und CFLAGS: Definieren den Compiler und die Kompilierungsoptionen.
- SRC und OBJ: Listen die Quell- und Objektdateien des Projekts auf.
- Die Regel für `meinprogramm` verknüpft alle Objektdateien und erstellt das endgültige ausführbare Programm.
- Die Musterregel `%.o: %.c` beschreibt, wie `.o`-Dateien aus `.c`-Dateien erstellt werden.
Fazit
GNU `make` ist ein vielseitiges und leistungsstarkes Werkzeug, das den Build-Prozess für Softwareprojekte automatisiert und beschleunigt. Durch die Definition von Regeln und Abhängigkeiten in einem Makefile können Entwickler effizient und gezielt nur die Teile eines Projekts neu bauen, die aktualisiert wurden, was sowohl Zeit spart als auch den Entwicklungsprozess optimiert.
| < Zurück (objdump) | < Hauptseite > |