Kann ich alle CPP-Dateien in src / zu .o in obj / kompilieren und dann in ./ eine Binärdatei verknüpfen?

116

Mein Projektverzeichnis sieht folgendermaßen aus:

/project
    Makefile
    main
    /src
        main.cpp
        foo.cpp
        foo.h
        bar.cpp
        bar.h
    /obj
        main.o
        foo.o
        bar.o

Ich möchte, dass mein Makefile alle .cppDateien im /srcOrdner mit .oDateien im /objOrdner kompiliert und dann alle .oDateien /objin der Ausgabe-Binärdatei im Ordner der obersten Ebene verknüpft /project.

Ich habe so gut wie keine Erfahrung mit Makefiles und bin mir nicht sicher, wonach ich suchen soll, um dies zu erreichen.

Ist dies auch ein "guter" Weg, dies zu tun, oder gibt es einen Standardansatz für das, was ich versuche?

Austin Hyde
quelle
6
@aaa: Ich vermute, das OP möchte eine Lösung, bei der nicht jede Quelldatei explizit aufgelistet werden muss.
Cascabel
7
Ich möchte nicht jede Quelldatei angeben, die ich habe, und ich habe zuvor versucht, dieses Handbuch zu lesen, aber ich finde es unorganisiert und schwer zu verstehen. Ich lerne viel besser aus einem tatsächlichen Beispiel, das das tut, was ich erwarte und gut erklärt ist, als aus trockenen technischen Handbüchern.
Austin Hyde
in Ordnung. Die Dokumentation ist jedoch mit guten Beispielen ausgezeichnet (es handelt sich nicht um ein technisches Handbuch). Sie suchen nach Musterregeln: gnu.org/software/make/manual/make.html#Pattern-Rules
Anycorn
11
Das sieht ein bisschen mehr nach dem aus, was ich will. Meiner Meinung nach ist das Make-Handbuch jedoch etwas trocken, da es eher auf Entwickler ausgerichtet zu sein scheint, die sich auf einem mittleren Niveau mit make befinden, und darüber hinaus sehr umfangreich und ausführlich ist. Vielleicht zu sehr.
Austin Hyde

Antworten:

180

Makefile Teil der Frage

Dies ist ziemlich einfach, es sei denn, Sie müssen nicht verallgemeinern, versuchen Sie etwas wie den folgenden Code (ersetzen Sie jedoch die Leerzeicheneinrückung durch Tabulatoren in der Nähe von g ++).

SRC_DIR := .../src
OBJ_DIR := .../obj
SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp)
OBJ_FILES := $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRC_FILES))
LDFLAGS := ...
CPPFLAGS := ...
CXXFLAGS := ...

main.exe: $(OBJ_FILES)
   g++ $(LDFLAGS) -o $@ $^

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
   g++ $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<

Automatische Erzeugung von Abhängigkeitsgraphen

Ein "Muss" für die meisten Make-Systeme. Mit GCC in kann in einem einzigen Durchgang als Nebeneffekt der Kompilierung ausgeführt werden, indem -MMDdem CXXFLAGSund -include $(OBJ_FILES:.o=.d) dem Ende des Makefile-Körpers ein Flag hinzugefügt wird:

CXXFLAGS += -MMD
-include $(OBJ_FILES:.o=.d)

Und wie bereits erwähnt, haben Sie immer GNU Make Manual dabei , es ist sehr hilfreich.

Bobah
quelle
11
Ah, du hast mich um Sekunden geschlagen. Aber ich schlage vor OBJ_FILES = $(patsubst src/%.cpp,obj/%.o,$(CPP_FILES)).
Beta
1
Ich musste dies ändern, damit es funktioniert: $<sollte $^für die Regel von main.exe gelten und ich denke, es gibt einen Tippfehler mit obj/%.o: src/%cpp.
1
@bobah Ihnen fehlt ein '.' in Ihren Objekten Regel für die cpp
regomodo
1
Die speziellen Variablen sind wahrscheinlich eine Erklärung wert, da sie makefile-
Blake
2
Ich weiß, dass dies eine alte Frage ist, aber ich habe sie entsprechend meinem Projekt ein wenig geändert, aber es funktioniert nicht. Hier ist mein Makefile: pastebin.com/4CksG9Wc Ich bekomme in der Konsole:make: *** No rule to make target '/main.o', needed by 'bin/main'. Pare.
Mateus Felipe
5

Wildcard funktioniert auch für mich, aber ich möchte eine Randnotiz für diejenigen geben, die Verzeichnisvariablen verwenden. Verwenden Sie immer einen Schrägstrich für den Ordnerbaum (keinen Backslash), da dies sonst fehlschlägt:

BASEDIR = ../..
SRCDIR = $(BASEDIR)/src
INSTALLDIR = $(BASEDIR)/lib

MODULES = $(wildcard $(SRCDIR)/*.cpp)
OBJS = $(wildcard *.o)
xesf
quelle
Meinten Sie Schrägstrich? Ihr Beispiel zeigt, was traditionell als Schrägstrich bezeichnet wird. Insbesondere werden diejenigen, die sich nach rechts lehnen, als "vorwärts" und diejenigen, die nach links geneigt sind, als "zurück" betrachtet
Evan Teran
Ja, Sie haben Recht, ich meine nur "Schrägstrich". Ich habe den Beitrag aktualisiert.
XESF