Ich habe ein Makefile, das ein anderes Makefile erstellt und dann aufruft. Da dieses Makefile mehr Makefiles aufruft, die die Arbeit erledigen, ändert es sich nicht wirklich. Daher wird immer daran gedacht, dass das Projekt erstellt und auf dem neuesten Stand ist.
dnetdev11 ~ # make
make: `release' is up to date.
Wie zwinge ich das Makefile, das Ziel neu zu erstellen?
clean = $(MAKE) -f ~/xxx/xxx_compile.workspace.mak clean
build = svn up ~/xxx \
$(clean) \
~/cbp2mak/cbp2mak -C ~/xxx ~/xxx/xxx_compile.workspace \
$(MAKE) -f ~/xxx/xxx_compile.workspace.mak $(1) \
release:
$(build )
debug:
$(build DEBUG=1)
clean:
$(clean)
install:
cp ~/xxx/source/xxx_utility/release/xxx_util /usr/local/bin
cp ~/xxx/source/xxx_utility/release/xxxcore.so /usr/local/lib
Hinweis: Namen wurden entfernt, um die Unschuldigen zu schützen
Edit: Final Fixed version:
clean = $(MAKE) -f xxx_compile.workspace.mak clean;
build = svn up; \
$(clean) \
./cbp2mak/cbp2mak -C . xxx_compile.workspace; \
$(MAKE) -f xxx_compile.workspace.mak $(1); \
.PHONY: release debug clean install
release:
$(call build,)
debug:
$(call build,DEBUG=1)
clean:
$(clean)
install:
cp ./source/xxx_utillity/release/xxx_util /usr/bin
cp ./dlls/Release/xxxcore.so /usr/lib
.PHONY
als wäre es nicht Ihr einziges Problem, und Sie sollten die Lösung nicht wirklich in die Frage einarbeiten oder zumindest nicht mehr.)Antworten:
Sie können eines oder mehrere Ihrer Ziele als falsch deklarieren .
quelle
:
, nicht nur auf das Endergebnis, das Sie erstellen möchten (z. B. Ihre Binärdatei). In der Frage,release
,debug
,clean
, undinstall
sind die Make - Ziele, nichtxxx_util
oderxxxcore.so
oder irgendetwas anderes.Der zu
-B
machende Schalter, dessen lange Form ist--always-make
, weistmake
an, Zeitstempel zu ignorieren und die angegebenen Ziele zu setzen. Dies kann den Zweck der Verwendung von make zunichte machen, aber es kann das sein, was Sie brauchen.quelle
Ein Trick, für den früher in einem Sun-Handbuch dokumentiert wurde,
make
ist die Verwendung eines (nicht vorhandenen) Ziels '.FORCE'. Sie können dies tun, indem Sie eine Datei force.mk erstellen, die Folgendes enthält:Angenommen, Ihr vorhandenes Makefile wird aufgerufen
makefile
, können Sie Folgendes ausführen:Da
.FORCE
es nichts gibt, ist alles, was davon abhängt, veraltet und wird neu aufgebaut.All dies funktioniert mit jeder Version von
make
; Unter Linux haben Sie GNU Make und können daher das .PHONY-Ziel wie beschrieben verwenden.Es ist auch erwägenswert, warum
make
die Veröffentlichung als aktuell angesehen wird. Dies kann daran liegen, dass Sie einentouch release
Befehl unter den ausgeführten Befehlen haben. Dies kann daran liegen, dass eine Datei oder ein Verzeichnis mit dem Namen "release" vorhanden ist, keine Abhängigkeiten aufweist und daher auf dem neuesten Stand ist. Dann gibt es den eigentlichen Grund ...quelle
Jemand anderes schlug vor .PHONY, was definitiv richtig ist. .PHONY sollte für jede Regel verwendet werden, für die ein Datumsvergleich zwischen Eingabe und Ausgabe ungültig ist. Da hast du keine Ziele des Formulars
output: input
, sollten Sie .PHONY für ALLE verwenden!Trotzdem sollten Sie wahrscheinlich einige Variablen oben in Ihrem Makefile für die verschiedenen Dateinamen definieren und echte Make-Regeln definieren, die sowohl Eingabe- als auch Ausgabeabschnitte enthalten, damit Sie die Vorteile von make nutzen können, nämlich, dass Sie nur tatsächlich kompilieren Dinge, die notwendig sind, um zu kopieren!
Bearbeiten: Beispiel hinzugefügt. Ungetestet, aber so machen Sie .PHONY
quelle
.PHONY
Ziels spielt keine Rolle. Es kann überall in der seinMakefile
.Wenn ich mich richtig erinnere, verwendet 'make' Zeitstempel (Änderungszeit der Datei), um festzustellen, ob ein Ziel aktuell ist oder nicht. Eine übliche Methode, um eine Neuerstellung zu erzwingen, besteht darin, diesen Zeitstempel mit dem Befehl 'touch' zu aktualisieren. Sie können versuchen, 'touch' in Ihrem Makefile aufzurufen, um den Zeitstempel eines der Ziele (möglicherweise eines dieser Sub-Makefiles) zu aktualisieren, wodurch Make möglicherweise gezwungen wird, diesen Befehl auszuführen.
quelle
Diese einfache Technik ermöglicht es dem Makefile, normal zu funktionieren, wenn kein Forcen gewünscht wird. Erstellen Sie am Ende Ihres Makefiles ein neues Ziel namens force . Das Force- Ziel berührt eine Datei, von der Ihr Standardziel abhängt. Im folgenden Beispiel habe ich touch myprogram.cpp hinzugefügt . Ich habe auch einen rekursiven Aufruf hinzugefügt zu machen . Dies führt dazu, dass das Standardziel jedes Mal festgelegt wird, wenn Sie make force eingeben .
quelle
Ich habe es versucht und es hat bei mir funktioniert
Fügen Sie diese Zeilen zu Makefile hinzu
speichern und jetzt anrufen
und es wird alles wieder neu kompilieren
Was ist passiert?
1) 'neue' Anrufe sauber. 'clean' do 'rm' entfernt alle Objektdateien mit der Erweiterung '.o'.
2) 'neue' Anrufe 'machen'. 'make' stellt sicher, dass keine '.o'-Dateien vorhanden sind, sodass alle' .o 'erneut erstellt werden. Dann verknüpft der Linker die gesamte O-Datei mit einer ausführbaren Ausgabe
Viel Glück
quelle
new
bessere Verwendung$(MAKE)
alsmake
Gemäß Millers rekursivem Make als schädlich sollten Sie einen Anruf vermeiden
$(MAKE)
! In dem Fall, den Sie zeigen, ist es harmlos, da dies nicht wirklich ein Makefile ist, sondern nur ein Wrapper-Skript, das genauso gut in Shell geschrieben worden sein könnte. Aber Sie sagen, dass Sie bei tieferen Rekursionsstufen so weitermachen, also sind Sie wahrscheinlich auf die Probleme gestoßen, die in diesem augenöffnenden Aufsatz gezeigt werden.Natürlich ist es mit GNU umständlich zu vermeiden. Und obwohl sie sich dieses Problems bewusst sind, ist es ihre dokumentierte Art, Dinge zu tun.
OTOH, makepp wurde als Lösung für dieses Problem erstellt. Sie können Ihre Makefiles auf Verzeichnisebene schreiben, sie werden jedoch alle zu einer vollständigen Ansicht Ihres Projekts zusammengefasst.
Legacy-Makefiles werden jedoch rekursiv geschrieben. Es gibt also eine
$(MAKE)
Problemumgehung, bei der nur die Unteranforderungen an den Haupt-Makepp-Prozess zurückgeleitet werden. Nur wenn Sie redundante oder, schlimmer noch, widersprüchliche Dinge zwischen Ihren Submakes tun, müssen Sie dies anfordern--traditional-recursive-make
(was natürlich diesen Vorteil von makepp bricht). Ich kenne Ihre anderen Makefiles nicht, aber wenn sie sauber geschrieben sind, sollten mit makepp notwendige Neuerstellungen automatisch erfolgen, ohne dass hier von anderen vorgeschlagene Hacks erforderlich sind.quelle
:
), wird es bei Bedarf immer neu erstellt.Wenn Sie keine der bereits erfolgreich kompilierten Ausgaben beibehalten müssen
baut alle wieder auf
quelle
Es hängt tatsächlich davon ab, was das Ziel ist. Wenn es sich um ein falsches Ziel handelt (dh das Ziel ist NICHT mit einer Datei verbunden), sollten Sie es als .PHONY deklarieren.
Wenn das Ziel jedoch kein falsches Ziel ist, sondern es nur aus irgendeinem Grund neu erstellen möchte (ein Beispiel ist die Verwendung des Vorverarbeitungsmakros __TIME__), sollten Sie das in den Antworten hier beschriebene FORCE-Schema verwenden.
quelle
http://www.gnu.org/software/make/manual/html_node/Force-Targets.html#Force-Targets
quelle
Es wurde bereits erwähnt, dachte aber, ich könnte zur Verwendung hinzufügen
touch
Wenn Sie
touch
alle zu kompilierenden Quelldateien haben,touch
ändert der Befehl die Zeitstempel einer Datei in die Systemzeit, zu der dertouch
Befehl ausgeführt wurde.Der Zeitstempel der Quelldatei ist was
make
verwendet, um zu "wissen", dass sich eine Datei geändert hat und neu kompiliert werden mussBeispiel: Wenn das Projekt ein C ++ - Projekt war, führen Sie es aus
touch *.cpp
, führen Sie esmake
erneut aus, und make sollte das gesamte Projekt neu kompilieren.quelle
make clean
löscht alle bereits kompilierten Objektdateien.quelle
Wie abernier betonte, gibt es im GNU-Handbuch eine empfohlene Lösung, bei der ein "falsches" Ziel verwendet wird, um den Wiederaufbau eines Ziels zu erzwingen:
Dies wird unabhängig von anderen Abhängigkeiten sauber ausgeführt.
Ich habe der Lösung aus dem Handbuch das Semikolon hinzugefügt, andernfalls ist eine leere Zeile erforderlich.
quelle
Auf meinem Linux-System (Centos 6.2) gibt es einen signifikanten Unterschied zwischen dem Deklarieren des Ziels .PHONY und dem Erstellen einer gefälschten Abhängigkeit von FORCE, wenn die Regel tatsächlich eine Datei erstellt, die dem Ziel entspricht. Wenn die Datei jedes Mal neu generiert werden muss, ist sowohl die gefälschte Abhängigkeit FORCE für die Datei als auch .PHONY für die gefälschte Abhängigkeit erforderlich.
falsch:
richtig:
quelle