2 Stimmen

korrekte Verwendung von makefile

Ich versuche also, Makefiles zu verstehen. Im Moment habe ich ein Projekt mit einigen Modulen, die mehr oder weniger nicht voneinander abhängig sind.

Mein Verzeichnisbaum sieht folgendermaßen aus:

root/
- Source/ <-- referenced as $(INPUTPATH)
- Build/ <-- referenced as $(BUILDPATH)
- Release/ <-- referenced as $(OUTPUTPATH)
- Makefile

Ich möchte, dass die Quelle ( .cpp/ .h) auf dem Source/, die Objekte auf dem Build/ und die ausführbare Datei auf dem Release/*.

Meine Idee war also, mehrere verschiedene Ziele zu haben und sie so zu verwenden:

all: maps auxiliars methods
    @echo "linking...";\
    $(CC) $(CFLAGS) $(OBJS) $(CLIBS) -o ${OUTPUTPATH}/MainProgram

dependency1: $(INPUTPATH)/foo.cpp
    @echo "compiling ArbPrecision...";\
    cd ${BUILDPATH};\
    $(CC) $(CFLAGS) $(CINCLUDE) -c ../$?

dependency2: dependency1 $(INPUTPATH)/bar.cpp
    @echo "compiling saddleConstructor...";\
    cd ${BUILDPATH};\
    $(CC) $(CFLAGS) $(CINCLUDE) -c ../$(INPUTPATH)/bar.cpp

maps: dependency2 $(INPUTPATH)/*Map.cpp
    @echo "compiling maps...";\
    cd ${BUILDPATH};\
    $(CC) $(CFLAGS) $(CINCLUDE) -c ../$(INPUTPATH)/*Map.cpp
... (auxiliars and methods)

Die $CINCLUDE und CFLAGS sind nur Compilerkram wie Header und externe Bibliotheken.

Alles funktioniert fast perfekt: Bei jedem Ziel wird nach den Abhängigkeiten zu anderen Zielen und nach der *cpp in der Quelle gefragt. Wenn diese nicht vorhanden ist, ruft es das Ziel auf und kompiliert die *cpp. Die ausführbare Datei wird ohne Fehler erstellt.

Wenn ich jedoch "make" zweimal aufrufe, ist die Kompilierzeit beim ersten und zweiten Mal gleich, auch wenn ich keine Änderungen am Quellcode vornehme. Offenbar habe ich also die Abhängigkeiten nicht richtig gesetzt.

Kann mir jemand den richtigen Weg zu dieser Zusammenstellung zeigen? Ich mache irgendetwas falsch, und ich verstehe nicht, was es ist.

Danke, Jorge

3voto

Josh Kelley Punkte 52169

Stellen Sie sicher, dass Sie mit folgenden Daten arbeiten Dateien . Für jede Regel wird geprüft, ob das Ziel Datei die von dieser Regel genannt wird, (1) existiert und (2) aktuell ist (d.h. nach einer ihrer Abhängigkeiten geändert wurde). Wenn die Datei nicht auf dem neuesten Stand ist, wird die Regel ausgeführt, um sie auf den neuesten Stand zu bringen.

Wenn Sie also Ihr Makefile so schreiben, wie es derzeit geschrieben ist, werden Sie beim Ausführen von make Make macht Folgendes:

  • all ist die erste Regel, wenn Sie also keine Argumente angeben, müssen Sie die Prozesse der all Regel.
  • Keine Datei namens all existiert, so dass die all Regel ausgeführt werden muss.
  • all hängt von der dependency1 Regel. Keine Datei namens dependency1 existiert, so dass die dependency1 Regel ausgeführt werden muss.
  • dependency1 hängt von der dependency2 Regel. Keine Datei namens dependency2 existiert, so dass die dependency2 Regel ausgeführt werden muss.

Was Sie stattdessen wollen, ist etwas Ähnliches wie das Folgende:

OBJS := foo.o bar.o Map.o

all: $(OUTPUTPATH)/MainProgram

$(OUTPUTPATH)/MainProgram: $(OBJS)
    $(CC) $(CFLAGS) $(OBJS) $(CLIBS) -o $(OUTPUTPATH)/MainProgram

%.o: %.cpp
    $(CC) $(CFLAGS) $(CINCLUDE) $< -c $@

.PHONY: all

Beachten Sie das Folgende:

  • Da Make mit Dateien arbeitet, werden die Ziele und Abhängigkeiten der Regeln, soweit möglich, nach Dateinamen aufgelistet.
  • Anstatt die .cpp-Dateien einzeln aufzulisten, wird eine Musterregel wird zur Erstellung jeder .o-Datei verwendet. Innerhalb der Musterregel wird die $< y $@ automatische Variablen werden verwendet, um die erste Voraussetzung (Datei) bzw. das Ziel (Datei) anzugeben.
  • Make gibt seine Befehle standardmäßig als Echo aus, so dass es nicht nötig ist, die echo selbst.
  • Für GNU Make, all ist gelistet als falsches Ziel um Make davon abzuhalten, nach einer Datei namens all .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X