Make / Makefiles

by Chris Heitkamp aka SuperVirus

Was ist Make

  • Make ist ein Build-Management-Tool
  • Teil des Posix-Standards
  • Für viele OS und Architekturen verfügbar
  • Es gibt verschiedene Make
    • Teilweise kompatibel
    • Hier wird GNU Make behandelt

Wozu ist Make gut?

  • Build-Vorgang vereinfachen
  • Build-Vorgang beschleunigen, es wird nur das Nötige neu gebaut
  • Universell, nicht nur für C, C++
  • Automatisierung

Funktionsweise

  • Make wird über eine Textdatei (das Makefile) gesteuert
  • Make sucht im aktuellen Verzeichnis nach einer Datei "Makefile"
  • Das Makefile enthält Bauanweisung(en)
  • Das Makefile beschreibt Abhängigkeiten
  • "Neubau" basiert auf Timestamps der Dateien

Beispiel


# Variables
CC = gcc
CFLAGS += -W -I .

# Default target
all: simple_main

# Normal target
simple_main: simple_main.o simple_sub.o

# Normal target, with action
dummy.o: dummy.c
	${CC} -c dummy.c -o dummy.o

.PHONY: clean
clean:
	${RM} simple_main *.o *.a
		

Ziele

Ein Ziel beschreibt normalerweise, was gebaut werden soll (z.B. das ausführbare Programm oder eine Bibliothek).

Syntax:


Ziel: Abhängigkeit1 Abhängigkeit2 Abhängigkeit3 …
[TAB] Aktion1
[TAB] Aktion2
		

Beispiel:


dummy.bin: dummy.o
	gcc dummy.o -o dummy.bin
		

Aktionen

Die Aktionen dienen dazu, aus den Abhängigkeiten das Ziel zu erstellen. Dies sind Befehle, die nacheinander ausgeführt werden.

  • Das Zeichen - vor einer Aktion bewirkt, dass evtl. auftretende Fehler ignoriert werden.
  • Das Zeichen @ vor einer Aktion bewirkt, dass die Aktion selber nicht auf dem Bildschirm ausgegeben wird.

Standardziel

Das erste Ziel im Makefile hat eine Sonderrolle:

Wird beim Aufruf von Make kein Ziel angegeben, so wird automatisch dieses Ziel genommen (oft "all").

Sonderfall: Pseudo-Ziele (phony targets)

Es gibt Fälle, in denen ein Ziel immer neu erzeugt werden soll, egal von welchen Ziele diese abhängen. Solche Ziele werden als phony targets bezeichnet. Make würde in dem Beispiel unten ein "make clean" grundsätzlich ausführen, selbst wenn im Ordner eine Datei mit dem Namen "clean" existieren sollte.


OBJ = file1.o file2.o
BIN = simple_main

.PHONY: clean
clean:
       rm -rf $(BIN) $(OBJ)
		

Variablen

Man kann in Makefiles Variablen definieren und benutzen, wobei diese überlicherweise groß geschrieben werden.

Gebräuchlich sind unter anderem folgende Variablen:

  • CC - Der C-Compiler
  • CFLAGS - Optionen für den C-Compiler
  • LDFLAGS - Optionen für den Linker

Variablen können auch beim Aufruf von Make gesetzt werden:


make CC=gcc CFLAGS="-Wall"
		

Einfache Zuweisung :=

Mit diesem Operator kann man einer Variablen Werte zuweisen. Beispiel:


CC := gcc
		
Bei einer einfachen Zuweisung wird der Wert ausgewertet und gespeichert, sobald die erste Definition gefunden wird.

Rekursive Zuweisung =

Bei diesem Operator wird der Wert der Variablen nicht sofort ausgewertet, sonder jedes mal wenn dieser in einer Aktion benutzt wird. Beispiel:


CC = gcc
CFLAGS = -I . -Wall

dummy: dummy.c
	${CC} ${CFLAGS} -c dummy.c -o dummy.o
		

Es würde zum Bauen also "gcc -I . -Wall -c dummy.c -o dummy.o" aufgerufen. Wenn z.B. CC später geändert würde, dann ändert sich der Aufruf entsprechend!

Bedingte Zuweisung ?=

Bei diesem Operator wird der Wert der Variablen nur gesetzt, wenn diese vorher noch keinen Wert hatte. Beispiel:


DEBUGFLAGS ?= -DDEBUG
		

Die Variable DEBUGFLAGS wird nur auf dem Wert "-DDEBUG" gesetzt, wenn diese noch keinen Wert hatte.

Anhängen +=

Bei diesem Operator wird der Wert an den vorhanden Wert der Variablen angehängt. Beispiel:


CFLAGS = -I
CFLAGS += -Wall
		

CFLAGS hat im Beispiel jetzt den Wert "-I -Wall"

Pattern Matching

Wie bei den Regeln kann auch hier das %-Zeichen für Pattern Matching benutzt werden. Beispiel:


OBJ = dummy1.o dummy2.o dummy3.o
SRC = $(OBJ:%.o=%.c)
		

Die Variable SRC hat danach den Wert "dummy1.c dummy2.c dummy3.c".

Pattern Matching

Das Zeichen % kann als Joker-Zeichen für Pattern Matching benutzt werden, um allgemeine Ziele zu erstellen. Beispiel:


%.o: %.c
	Aktionen

OBJ = dummy1.o dummy2.o dummy3.o dummy4.o dummy5.o
SRC = $(OBJ:%.o=%.c)
		

Sobald ein % in der Abhängigkeiten-Liste auftaucht wird dieses durch den selben String ersetzt, der benutzt wurde um die Ersetzung im Ziel durchzuführen.

Spezielle Variablen

Innerhalb von Aktionen können spezielle Variablen für die Angabe der Dateinamen benutzt werden. Einige davon sind:

  • $@ - kompletter Name des aktuellen Ziele
  • $? - alle Abhängigkeiten, die aktueller sind als das aktuelle Ziel
  • $* - Liefert der String, der dem %-Zeichen im Ziel entspricht
  • $< - Name der ersten Abhängigkeit
  • $+ - Name aller Abhängigkeiten, durch Leerzeichen getrennt (mit Duplikaten)
  • $^ - Name aller Abhängigkeiten, durch Leerzeichen getrennt (ohne Duplikate)

Automatische Abhängigkeiten

Folgendes Makefile dient dazu, automatisch die Abhängigkeiten von den Header-Datei zu berücksichtigen:


OBJ = dummy1.o dummy2.o dummy3.o dummy4.o dummy5.o
SRC = $(OBJ:%.o=%.c)
DEPFILE = .depend

.PHONY: depends
dep: $(SRC)
	$(CC) -MM $(SRC) > $(DEPFILE)

-include $(DEPFILE)
		

Durch die Option -MM gibt der Präprozessor eine Liste der #includes im passenden Format für make aus, welche dann in eine Datei umgelenkt wird.

Am Ende das Makefiles wird diese Datei eingebunden. Das -include sorgt dafür, dass es zu keinem Fehler kommt falls diese Datei fehlt. Durch folgenden Aufruf kann man diese Datei aktualisieren lassen:


make dep
		

Fallstricke

  • Tab / Space vertauscht
  • Falsches Datum/Uhrzeit
  • Alte Datei wiederhergestellt (VCS)
  • Geänderte Compilerflags
  • Windows: shell

Alternativen

SCons

  • Python-basiert
  • SConstruct-Datei ist im Prinzip ein Python-Skript
  • Enthält autoconf/automake ähnliche Funktionalitäten
  • Projekte, die dieses System einsetzen:
    • Blender
    • MongoDB
    • Doom 3
  • http://www.scons.org/

Rake

  • Ruby-basiert
  • Rakefiles benutzen Ruby-Syntax
  • Seit Ruby 1.9 Bestandteil von Ruby
  • Projekte, die dieses System einsetzen:
    • Viele Ruby-Projekte
  • http://rake.rubyforge.org/

Apache Ant

CMake

  • Erstellt aus CMakeLists.txt Makefiles
  • Projekte, die dieses System einsetzen:
    • KDE
    • KiCad
    • MySQL
  • http://www.cmake.org/

Make / Makefiles

by Chris Heitkamp aka SuperVirus