SelfLinux Programmierung Make Abschnitt 2 | SelfLinux-0.13.0

| Make | Autor Formatierung GFDL

#### 3 Makros

#### 3.1 Syntax

Man kann auch Variablen innerhalb von Makefiles verwenden. Sie werden dort als Makros bezeichnet und meistens gross geschrieben. Mit

    CC = gcc

wird ein Makro CC mit dem Wert gcc angelegt. Der Wert darf dabei auch aus mehreren Wörtern bestehen (Beispiel: CC = gcc -O). Die Definition darf sich auch über mehrere Zeilen erstrecken, wenn die Zeile mit \ aufhört (Achtung: bitte darauf achten, dass das \ tatsächlich das letzte Zeichen in der Zeile ist und kein Tabulator- oder Leerzeichen dahintersteht!).

Der Aufruf des Makros CC kann mit

    $(CC)
    ${CC}

erfolgen.

#### 3.2 Vordefinierte Makros

make kennt schon eine Reihe von vordefinierten Makros. So ist zum Beispiel die Makrodefinition CC = cc dem make-Kommando bereits bekannt. Mit

user@linux $ make -p -f /dev/null

können die internen Makros und Regeln abgefragt werden. Ist man nur an den Makros interessiert, kann man diese mit Hilfe des grep- und sort-Kommandos ausfiltern und sortieren:

user@linux $ make -p -f /dev/null | grep " = " | sort

#### 3.3 Makro-Übergabe

Makros können schon vordefiniert sein, Makros können im Makefile gesetzt werden, Makros können aber auch beim Aufruf von make übergeben werden:

user@linux $ make love CC=gcc

Soll das Makro aus mehreren Wörtern bestehen, so muss es beim Aufruf gequotet (d.h. mit einfachen oder doppelten Anführungszeichen umgeben) werden:

user@linux $ make love CFLAGS="-O -DNDEBUG"

#### 3.4 Umgebungs-Variablen

Umgebungs-Variablen werden innerhalb eines Makefiles genauso wie ein Makro angesprochen. Damit kann man zum Beispiel eine Variable CXX setzen, die den GNU-C++-Compiler enhalten soll:

Bash:

user@linux $ export CXX=g++

C-Shell:

user@linux $ setenv CXX g++

Die Umgebungs-Variable CXX steht damit im Makefile als Makro zur Verfügung, was in der folgenden Regel ausgenutzt wird:

    hello : hello.cpp
            $(CXX) hello.cpp -o hello

#### 3.5 Prioritäts-Regeln

Wenn man dasselbe Makro auf verschiedene Weisen definieren kann, ist es wichtig, zu wissen, welches Makro im Falle eines Konfliktes gewinnt. Makros werden nach folgender Reihenfolge aufgelöst:

1. vordefinierte Makros
2. Umgebungs-Variablen
3. interne Makros
4. Makros über die Kommandozeile

Die Priorität ist aufsteigend, das heisst Makros, die über die Kommandozeile gesetzt werden, gewinnen immer.

#### 3.6 String-Substitution

Makros dürfen sich auf andere Makros beziehen. Betrachten wir dazu folgendes Beispiel:

    C_FILES   = daddy.c mummy.c
    H_FILES   = children.h
    SRC_FILES = $(C_FILES) $(H_FILES)
    OBJ_FILES = daddy.o mummy.o

Das Mako SRC_FILES bezieht sich dabei auf die beiden Makros C_FILES und H_FILES. Vergleichen wir jetzt das Makro C_FILES mit OBJ_FILES, so stellen wir fest, dass sie bis auf die Endung (.c bzw. .o) identisch sind. Damit wir nicht jedes Mal die OBJ_FILES anpassen müssen, wenn sich C_FILES ändert, gibt es die String-Substitution:

    OBJ_FILES = $(C_FILES:.c=.o)

Damit hängt OBJ_FILES direkt von C_FILES ab, das heißt wenn in C_FILES eine neue .c-Datei aufgenommen wird, müssen wir OBJ_FILES nicht ändern.

#### 3.7 Interne Makros

Neben den vordefinierten Makros gibt es eine Reihe von internen Makros, die manche Regel vereinfachen können:

$@ | Name des aktuellen Zieles
$? | Name der abhängigen Dateien, die neuer als das Ziel sind
$< | Name der abhängigen Dateien, die neuer als das Ziel sind. (mit Endung)
$* | Name der abhängigen Dateien, die neuer als das Ziel sind. (ohne Endung)
$% | Name der entsprechenden Objekt-Datei (.o), falls das Ziel eine Bibliothek ist.

Beispiel:

    children: $(OBJ_FILES)
            $(CC) $(CFLAGS) $(OBJ_FILES) -o $@

In diesem Beispiel wird von make $@ durch den Namen des Ziels (children) ersetzt.

Will man auf den Dateinamen oder Verzeichnisnamen zugreifen, kann man dies (ausser bei $?) über die Modifier F (wie File) oder D (wie Directory).

Beispiel:

    $(*D), $(@F)