Da dies für Unix ist, haben die ausführbaren Dateien keine Erweiterungen.
Zu beachten ist, dass root-config
es sich um ein Dienstprogramm handelt, das die richtige Kompilierung und Verknüpfung von Flags bietet. und die richtigen Bibliotheken zum Erstellen von Anwendungen gegen root. Dies ist nur ein Detail, das sich auf die ursprüngliche Zielgruppe dieses Dokuments bezieht.
Mach mich Baby
oder du vergisst nie das erste Mal, dass du gemacht wurdest
Eine einführende Diskussion über make und wie man ein einfaches Makefile schreibt
Was ist Make? Und warum sollte es mich interessieren?
Das Tool Make ist ein Build-Abhängigkeitsmanager. Das heißt, es muss sichergestellt werden, welche Befehle in welcher Reihenfolge ausgeführt werden müssen, um Ihr Softwareprojekt aus einer Sammlung von Quelldateien, Objektdateien, Bibliotheken, Headern usw. usw. zu übernehmen. Einige davon haben sich möglicherweise geändert vor kurzem --- und verwandeln sie in eine korrekte aktuelle Version des Programms.
Eigentlich können Sie Make auch für andere Dinge verwenden, aber darüber werde ich nicht sprechen.
Ein triviales Makefile
Nehmen wir an, dass Sie ein Verzeichnis enthält: tool
tool.cc
tool.o
support.cc
support.hh
und support.o
davon abhängen , welche auf root
und sollen kompiliert werden in ein Programm mit dem Namen tool
, und nehmen wir an, dass Sie schon auf den Quelldateien Hacking (was bedeutet , dass die bestehende tool
ist jetzt veraltet) und wollen Kompilieren Sie das Programm.
Um dies selbst zu tun, könnten Sie
Überprüfen Sie, ob entweder support.cc
oder support.hh
neuer als support.o
, und führen Sie in diesem Fall einen Befehl wie aus
g++ -g -c -pthread -I/sw/include/root support.cc
Überprüfen Sie, ob entweder support.hh
oder tool.cc
neuer als tool.o
, und führen Sie in diesem Fall einen Befehl wie aus
g++ -g -c -pthread -I/sw/include/root tool.cc
Überprüfen Sie, ob tool.o
es neuer als ist tool
, und führen Sie in diesem Fall einen Befehl wie aus
g++ -g tool.o support.o -L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
-lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz -Wl,-framework,CoreServices \
-Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root -lm -ldl
Puh! Was für ein Ärger! Es gibt viel zu beachten und mehrere Möglichkeiten, Fehler zu machen. (Übrigens: Die Einzelheiten der hier gezeigten Befehlszeilen hängen von unserer Softwareumgebung ab. Diese funktionieren auf meinem Computer.)
Natürlich können Sie jedes Mal alle drei Befehle ausführen. Das würde funktionieren, lässt sich aber nicht gut auf eine umfangreiche Software skalieren (wie DOGS, deren Kompilierung auf meinem MacBook von Grund auf mehr als 15 Minuten dauert).
Stattdessen können Sie eine Datei mit dem folgenden Namen schreiben makefile
:
tool: tool.o support.o
g++ -g -o tool tool.o support.o -L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
-lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz -Wl,-framework,CoreServices \
-Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root -lm -ldl
tool.o: tool.cc support.hh
g++ -g -c -pthread -I/sw/include/root tool.cc
support.o: support.hh support.cc
g++ -g -c -pthread -I/sw/include/root support.cc
und geben Sie einfach make
in die Befehlszeile ein. Dadurch werden die drei oben gezeigten Schritte automatisch ausgeführt.
Die hier nicht eingerückten Zeilen haben die Form "Ziel: Abhängigkeiten" und geben an, dass die zugehörigen Befehle (eingerückte Zeilen) ausgeführt werden sollen, wenn eine der Abhängigkeiten neuer als das Ziel ist. Das heißt, die Abhängigkeitslinien beschreiben die Logik dessen, was neu erstellt werden muss, um Änderungen in verschiedenen Dateien zu berücksichtigen. Wenn sich dies support.cc
ändert, support.o
muss dies neu erstellt werden, tool.o
kann aber in Ruhe gelassen werden. Wenn support.o
Änderungen neu erstellt werden tool
müssen.
Die Befehle, die jeder Abhängigkeitszeile zugeordnet sind, werden mit einer Registerkarte abgesetzt (siehe unten). Sie sollten das Ziel ändern (oder zumindest berühren, um die Änderungszeit zu aktualisieren).
Variablen, integrierte Regeln und andere Extras
An diesem Punkt erinnert sich unser Makefile einfach an die Arbeit, die erledigt werden muss, aber wir mussten immer noch jeden einzelnen Befehl in seiner Gesamtheit herausfinden und eingeben. Das muss nicht so sein: Make ist eine leistungsstarke Sprache mit Variablen, Textmanipulationsfunktionen und einer ganzen Reihe integrierter Regeln, die uns dies erheblich erleichtern können.
Variablen erstellen
Die Syntax für den Zugriff auf eine make-Variable lautet $(VAR)
.
Die Syntax für die Zuweisung zu einer Make-Variablen lautet: VAR = A text value of some kind
(oder VAR := A different text value but ignore this for the moment
).
Sie können Variablen in Regeln wie dieser verbesserten Version unseres Makefiles verwenden:
CPPFLAGS=-g -pthread -I/sw/include/root
LDFLAGS=-g
LDLIBS=-L/sw/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint \
-lPostscript -lMatrix -lPhysics -lMathCore -lThread -lz -L/sw/lib -lfreetype -lz \
-Wl,-framework,CoreServices -Wl,-framework,ApplicationServices -pthread -Wl,-rpath,/sw/lib/root \
-lm -ldl
tool: tool.o support.o
g++ $(LDFLAGS) -o tool tool.o support.o $(LDLIBS)
tool.o: tool.cc support.hh
g++ $(CPPFLAGS) -c tool.cc
support.o: support.hh support.cc
g++ $(CPPFLAGS) -c support.cc
Das ist etwas besser lesbar, erfordert aber immer noch viel Tippen
Funktionen ausführen
GNU make unterstützt eine Vielzahl von Funktionen für den Zugriff auf Informationen aus dem Dateisystem oder andere Befehle im System. In diesem Fall interessiert uns, $(shell ...)
welches die Ausgabe der Argumente erweitert und $(subst opat,npat,text)
welches alle Instanzen von opat
durch npat
im Text ersetzt.
Dies auszunutzen gibt uns:
CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)
SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))
tool: $(OBJS)
g++ $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)
tool.o: tool.cc support.hh
g++ $(CPPFLAGS) -c tool.cc
support.o: support.hh support.cc
g++ $(CPPFLAGS) -c support.cc
Das ist einfacher zu tippen und viel besser lesbar.
Beachte das
- Wir geben immer noch explizit die Abhängigkeiten für jede Objektdatei und die endgültige ausführbare Datei an
- Wir mussten die Kompilierungsregel für beide Quelldateien explizit eingeben
Implizite und Musterregeln
Wir würden allgemein erwarten, dass alle C ++ - Quelldateien gleich behandelt werden, und Make bietet drei Möglichkeiten, dies anzugeben:
- Suffixregeln (in GNU make als veraltet angesehen, aber aus Gründen der Abwärtskompatibilität beibehalten)
- implizite Regeln
- Musterregeln
Implizite Regeln sind eingebaut, und einige werden unten diskutiert. Musterregeln werden in einer Form wie angegeben
%.o: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
Dies bedeutet, dass Objektdateien aus C-Quelldateien generiert werden, indem der angezeigte Befehl ausgeführt wird, wobei die "automatische" Variable $<
auf den Namen der ersten Abhängigkeit erweitert wird.
Eingebaute Regeln
Make verfügt über eine ganze Reihe integrierter Regeln, die bedeuten, dass ein Projekt sehr oft tatsächlich mit einem sehr einfachen Makefile kompiliert werden kann.
Die in GNU eingebaute Regel für C-Quelldateien ist die oben gezeigte. Ebenso erstellen wir Objektdateien aus C ++ - Quelldateien mit einer Regel wie $(CXX) -c $(CPPFLAGS) $(CFLAGS)
.
Einzelne Objektdateien werden mit verknüpft $(LD) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)
, dies funktioniert jedoch in unserem Fall nicht, da mehrere Objektdateien verknüpft werden sollen.
Von integrierten Regeln verwendete Variablen
Die integrierten Regeln verwenden eine Reihe von Standardvariablen, mit denen Sie lokale Umgebungsinformationen angeben können (z. B. wo sich die ROOT-Include-Dateien befinden), ohne alle Regeln neu schreiben zu müssen. Die für uns wahrscheinlich interessantesten sind:
CC
- der zu verwendende C-Compiler
CXX
- der zu verwendende C ++ - Compiler
LD
- der zu verwendende Linker
CFLAGS
- Kompilierungsflag für C-Quelldateien
CXXFLAGS
- Kompilierungsflags für C ++ - Quelldateien
CPPFLAGS
- Flags für den c-Präprozessor (enthalten normalerweise in der Befehlszeile definierte Dateipfade und Symbole), die von C und C ++ verwendet werden
LDFLAGS
- Linker-Flags
LDLIBS
- zu verknüpfende Bibliotheken
Ein einfaches Makefile
Indem wir die integrierten Regeln nutzen, können wir unser Makefile vereinfachen, um:
CC=gcc
CXX=g++
RM=rm -f
CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)
SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))
all: tool
tool: $(OBJS)
$(CXX) $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)
tool.o: tool.cc support.hh
support.o: support.hh support.cc
clean:
$(RM) $(OBJS)
distclean: clean
$(RM) tool
Wir haben auch einige Standardziele hinzugefügt, die spezielle Aktionen ausführen (z. B. das Bereinigen des Quellverzeichnisses).
Beachten Sie, dass beim Aufrufen von make ohne Argument das erste in der Datei gefundene Ziel verwendet wird (in diesem Fall alle). Sie können jedoch auch das abzurufende Ziel benennen, wodurch make clean
die Objektdateien in diesem Fall entfernt werden.
Wir haben immer noch alle Abhängigkeiten fest codiert.
Einige mysteriöse Verbesserungen
CC=gcc
CXX=g++
RM=rm -f
CPPFLAGS=-g $(shell root-config --cflags)
LDFLAGS=-g $(shell root-config --ldflags)
LDLIBS=$(shell root-config --libs)
SRCS=tool.cc support.cc
OBJS=$(subst .cc,.o,$(SRCS))
all: tool
tool: $(OBJS)
$(CXX) $(LDFLAGS) -o tool $(OBJS) $(LDLIBS)
depend: .depend
.depend: $(SRCS)
$(RM) ./.depend
$(CXX) $(CPPFLAGS) -MM $^>>./.depend;
clean:
$(RM) $(OBJS)
distclean: clean
$(RM) *~ .depend
include .depend
Beachte das
- Es gibt keine Abhängigkeitslinien mehr für die Quelldateien!?!
- Es gibt eine seltsame Magie im Zusammenhang mit .depend und abhängig
- Wenn Sie das tun ,
make
dann ls -A
sehen Sie eine Datei mit dem Namen , .depend
die Dinge enthält , die wie Make Abhängigkeit Linien aussehen
Andere Lesart
Kennen Sie Fehler und historische Notizen
Die Eingabesprache für Make ist Leerzeichenempfindlich. Insbesondere müssen die Aktionszeilen nach Abhängigkeiten mit einer Registerkarte beginnen . Eine Reihe von Leerzeichen kann jedoch gleich aussehen (und tatsächlich gibt es Editoren, die Tabulatoren stillschweigend in Leerzeichen konvertieren oder umgekehrt), was zu einer Make-Datei führt, die richtig aussieht und immer noch nicht funktioniert. Dies wurde früh als Fehler identifiziert, aber ( die Geschichte geht ) es wurde nicht behoben, da es bereits 10 Benutzer gab.
(Dies wurde aus einem Wiki-Beitrag kopiert, den ich für Physikstudenten geschrieben habe.)