346 Stimmen

Wie man ein SIMPLE C++ Makefile erstellt

Wir müssen ein Makefile verwenden, um alles für unser Projekt zusammenzustellen, aber unser Professor hat uns nie gezeigt, wie das geht.

Ich habe nur eine Datei, a3driver.cpp . Der Treiber importiert eine Klasse von einem Ort, "/user/cse232/Examples/example32.sequence.cpp" .

Das war's. Alles andere ist in der .cpp .

Wie würde ich vorgehen, um ein einfaches Makefile zu erstellen, das eine ausführbare Datei namens a3a.exe ?

14 Stimmen

.EXE, also ist es definitiv Windows. Wenn ich es mir recht überlege... der Pfad ist im Unix-Stil. Wahrscheinlich verwendet er Mingw-32.

3 Stimmen

Seufz. Ich nehme an, man muss die Grundlagen eines jeden Berufs erlernen, auch wenn man sie nie anwenden wird. Man muss einfach verstehen, wie die Dinge funktionieren. Die Chancen stehen allerdings gut, dass Sie immer in einer IDE wie Eclipse entwickeln werden. Sie werden hier eine Antwort auf Ihren einfachen Ein-Zeilen-Fall bekommen, und es gibt jede Menge Web-Tutorials, aber wenn Sie in die Tiefe gehen wollen, kommen Sie um das O'Reilly-Buch nicht herum (das gilt auch für die meisten SW-Themen). amazon.com/Managing-Projects-Make-Nutshell-Handbooks/dp/ Kaufen Sie ein Exemplar aus 2. Hand bei amazon, half.com, betterworldbooks eBay

3 Stimmen

Der von @Dennis gepostete Link ist nicht mehr verfügbar, aber das gleiche Material findet sich in diesem archive.org-Seite .

8voto

John Knoeller Punkte 32285

Ihre Make-Datei wird eine oder zwei Abhängigkeitsregeln haben, je nachdem, ob Sie mit einem einzigen Befehl kompilieren und linken oder mit einem Befehl für die Kompilierung und einem für den Link.

Abhängigkeiten sind ein Baum von Regeln, die wie folgt aussehen (beachten Sie, dass der Einzug doit ein TAB sein):

main_target : source1 source2 etc
    command to build main_target from sources

source1 : dependents for source1
    command to build source1

Dort doit Nach den Befehlen für ein Ziel muss eine Leerzeile stehen, und es muss no eine Leerzeile vor den Befehlen stehen. Das erste Ziel im Makefile ist das Gesamtziel, und andere Ziele werden nur gebaut, wenn das erste Ziel von ihnen abhängt.

Ihr Makefile wird also etwa so aussehen.

a3a.exe : a3driver.obj 
    link /out:a3a.exe a3driver.obj

a3driver.obj : a3driver.cpp
    cc a3driver.cpp

8voto

Jérôme Pouiller Punkte 7648

Ich schlage vor (beachten Sie, dass der Einzug ein TAB ist):

tool: tool.o file1.o file2.o
    $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@

または

LINK.o = $(CXX) $(LDFLAGS) $(TARGET_ARCH)
tool: tool.o file1.o file2.o

Der letzte Vorschlag ist etwas besser, da er die impliziten Regeln von GNU Make wiederverwendet. Um zu funktionieren, muss eine Quelldatei jedoch denselben Namen haben wie die endgültige ausführbare Datei (d.h.: tool.c y tool ).

Beachten Sie, dass es nicht notwendig ist, Quellen zu deklarieren. Objekt-Zwischendateien werden nach der impliziten Regel erzeugt. Folglich ist diese Makefile für C und C++ (und auch für Fortran, etc...) arbeiten.

Beachten Sie auch, dass das Makefile standardmäßig $(CC) als Linker. $(CC) funktioniert nicht für die Verknüpfung von C++-Objektdateien. Wir ändern LINK.o nur aus diesem Grund. Wenn Sie C-Code kompilieren wollen, müssen Sie nicht zwingend die LINK.o Wert.

Natürlich können Sie auch Ihre Kompilierflags mit der Variablen CFLAGS und fügen Sie Ihre Bibliotheken in LDLIBS . Zum Beispiel:

CFLAGS = -Wall
LDLIBS = -lm

Eine Randbemerkung: Wenn Sie externe Bibliotheken verwenden müssen, schlage ich vor, dass Sie pkg-config verwenden um die korrekte Einstellung CFLAGS y LDLIBS :

CFLAGS += $(shell pkg-config --cflags libssl)
LDLIBS += $(shell pkg-config --libs libssl)

Der aufmerksame Leser wird feststellen, dass diese Makefile wird nicht ordnungsgemäß wiederhergestellt, wenn eine Kopfzeile geändert wird. Fügen Sie diese Zeilen hinzu, um das Problem zu beheben:

override CPPFLAGS += -MMD
include $(wildcard *.d)

-MMD ermöglicht die Erstellung von .d-Dateien, die Makefile-Fragmente über Header-Abhängigkeiten enthalten. Die zweite Zeile verwendet sie einfach.

Ein gut geschriebenes Makefile sollte natürlich auch enthalten clean y distclean Regeln:

clean:
    $(RM) *.o *.d

distclean: clean
    $(RM) tool

Hinweis, $(RM) ist das Äquivalent zu rm -f aber es ist eine gute Praxis, nicht aufzurufen rm direkt.

Le site all Regel wird ebenfalls begrüßt. Damit sie funktioniert, sollte sie die erste Regel in Ihrer Datei sein:

all: tool

Sie können auch eine install Regel:

PREFIX = /usr/local
install:
    install -m 755 tool $(DESTDIR)$(PREFIX)/bin

DESTDIR ist standardmäßig leer. Der Benutzer kann es so einstellen, dass sein Programm auf einem anderen System installiert wird (obligatorisch für den Cross-Compilationsprozess). Paketbetreuer für mehrere Distributionen können auch die PREFIX um Ihr Paket zu installieren in /usr .

Ein letztes Wort: Legen Sie die Quelldateien nicht in Unterverzeichnissen ab. Wenn Sie das wirklich tun wollen, halten Sie diese Makefile im Root-Verzeichnis und verwenden Sie vollständige Pfade, um Ihre Dateien zu identifizieren (z. B. subdir/file.o ).

Zusammengefasst sollte Ihr komplettes Makefile also wie folgt aussehen:

LINK.o = $(CXX) $(LDFLAGS) $(TARGET_ARCH)
PREFIX = /usr/local
override CPPFLAGS += -MMD
include $(wildcard *.d)

all: tool
tool: tool.o file1.o file2.o
clean:
    $(RM) *.o *.d
distclean: clean
    $(RM) tool
install:
    install -m 755 tool $(DESTDIR)$(PREFIX)/bin

0 Stimmen

Kurz vor dem Ende: Sollten zwischen den Regeln nicht Leerzeilen stehen? Antwort von John Knoeller behauptete das.

0 Stimmen

Keine Umsetzung von make die ich kenne (GNU Make und BSD Make) benötigen Leerzeilen zwischen den Regeln. Es gibt jedoch tonnenweise make Implementierungen mit ihren eigenen Fehlern^WSpezifika.

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