2016-06-21 16 views
0

Ich habe einige Regeln wie dieseZielname in Makefile Voraussetzung

foo_%: $(BIN_DIR) $(LIB_DIR) $(OBJ_DIR) 
    gcc stuff 

Verzeichnis Variablen wie folgt aus:

BIN_DIR := $(BUILD_DIR)/[email protected]/$(TARGET)/bin 

Und in der Regel, um die Verzeichnisse zu machen:

$(BIN_DIR) $(LIB_DIR) $(OBJ_DIR): 
    mkdir -p [email protected] 

Ich möchte der (erweiterte) foo_% Teil ersetzt die [email protected] im Verzeichnisnamen, aber gerade jetzt [email protected] wird mit nichts ersetzt.

Jetzt konnte ich einfach ersetzen [email protected] mit % im BIN_DIR var:

BIN_DIR := $(BUILD_DIR)/%/$(TARGET)/bin 

aber dies lässt die foo_ Teil, den ich schließen will.

Last Resort ist drei mkdir -p Anweisungen in jeder Regel enthalten, aber ich würde lieber nicht!

Antwort

1

Die Erweiterung kann nicht ausgeführt werden, da die Listen mit Voraussetzungen und Zielen in Regeln bei der Syntaxverarbeitung erweitert werden. Mit anderen Worten, statisch zur "Kompilierzeit" der Makefile-Regeln. Während der Parameter [email protected] dynamisch ist; Es übernimmt Werte im Makefile "Laufzeit", wenn der Regelbaum ausgewertet wird. Zu diesem Zeitpunkt kann es nicht in Ziele und Voraussetzungen substituiert werden.

Da dies nur dafür sorgt, dass einige Verzeichnisse existieren, können Sie die make -p in das Rezept verschieben, und tun Sie es so. Beachten Sie, dass wir immer noch die BIN_DIR := Zuordnung in die Nicht-Erweiterung BIN_DIR = Zuordnung ändern müssen:

TARGET := target 
LIB_DIR := lib_dir 
OBJ_DIR := obj_dir 
BUILD_DIR := build_dir 

BIN_DIR = $(BUILD_DIR)/[email protected]/$(TARGET)/bin 

foo: | $(LIB_DIR) $(OBJ_DIR) # see text below for explanation of | symbol 
     mkdir -p $(BIN_DIR) 
     echo other steps 

$(LIB_DIR) $(OBJ_DIR): 
     mkdir -p [email protected] 

Hier stellen wir die Marke Regelverarbeitung verwenden $(LIB_DIR) und $(OBJ_DIR) zu erstellen. Aber $(BIN_DIR) wird in einem Fußgängerweg gehandhabt, nur indem man eine mkdir -p im Rezept laufen lässt. Die Erweiterung von [email protected] funktioniert hier, weil BIN_DIR eine traditionelle nicht expandierte Stil-Variable ist, die eine Expansion erfährt, wenn sie substituiert wird. Es wird immer noch statisch erweitert, wenn die Regelsyntax verarbeitet wird, aber der Punkt ist, dass es das nicht erweiterte [email protected] enthält, das in die make -p Rezepturzeile eingefügt wird. Weil das [email protected] in der Rezeptzeile ist, funktioniert es. Es funktioniert einfach nicht in der Liste der Ziele oder Voraussetzungen.

Ich habe das | Symbol verwendet, um $(LIB_DIR)$(OBJ_DIR) als reine Bestellvoraussetzungen zu bezeichnen. Read about this in the GNU Make manual. Nur-Bestellanforderungen werden nur aktualisiert, wenn sie fehlen. Wenn sie bereits existieren, werden sie ignoriert.

Wenn wir diese Verzeichnisse nicht auf Order-Only setzen, werden sie jedes Mal, wenn sich ihr Zeitstempel ändert, eine Neuerstellung des Ziels auslösen, so dass sie neuer als das Ziel ist.

Es ist wahrscheinlich am besten, die Verzeichnisse nicht als Voraussetzung zu benennen, und fügen Sie einfach den Fall mkdir -p in das Rezept ein.Wie in einfach wie folgt:

TARGET := target 
LIB_DIR := lib_dir 
OBJ_DIR := obj_dir 
BUILD_DIR := build_dir 

BIN_DIR = $(BUILD_DIR)/[email protected]/$(TARGET)/bin 

foo: 
     mkdir -p $(LIB_DIR) $(OBJ_DIR) $(BIN_DIR) 
     echo other step 

Run:

 
$ make 
mkdir -p lib_dir obj_dir build_dir/foo/target/bin 
echo other steps 
other steps 
+0

erstaunliche Antwort, vielen Dank. Warum können wir '%' in '$ (BUILD_DIR)' haben, aber nicht '$ @'? Ist '%' nicht weniger dynamisch als '$ @' (oder sogar der einzige dynamische Teil des Ziels)? –

+0

@DmitryNarkevich '%' in Ziel-/Vorbereitungszeilen ist speziell; Es ist die Grundlage für Musterregeln. Z.B. '% .o:% c:' Eine Regel, die verwendet wird, um '.o' aus' .c' zu machen, wenn keine spezifischere Regel für das gegebene Objekt gefunden wird. – Kaz

+0

Hmm dann scheint es mir merkwürdig, dass wir den passenden Teil des Ziels bekommen können, aber nicht das gesamte Ziel. Scheint wie ein Versehen! –