2 Stimmen

Verzögern oder Wiederholen einer Voraussetzung in GNU make

Ich versuche, meine Subversion-Revisionsnummer in ein C++-Projekt einzubetten und habe Probleme, GNU make dafür einzurichten. Mein Makefile sieht derzeit etwa so aus:

check-svnversion:
  ../shared/update-svnversion-h.pl

../shared/svnversion.h: check-svnversion

shared/svnversion.o: ../shared/svnversion.h

.PHONY: check-svnversion

svnversion.o hängt ab von svnversion.cpp (über eine Musterregel) und svnversion.h (explizit aufgeführt, weil die Abhängigkeitsüberprüfung es aus irgendeinem Grund nicht erkennt). svnversion.h wird erstellt und gepflegt von der update-svnversion-h.pl Skript (das im Grunde nur Folgendes ausführt svnversion und mischt die Ausgabe in eine C++-Datei).

Zurzeit muss ich Folgendes ausführen make zweimal, um die Datei auf den neuesten Stand zu bringen. Das erste Mal, make läuft update-svnversion-h.pl (da es als Voraussetzung aufgeführt ist), prüft aber nicht den Zeitstempel von svnversion.h anschließend zu sehen, dass sie von update-svnversion-h.pl so dass sie nicht neu erstellt wird svnversion.o . Beim zweiten Mal prüft es den Zeitstempel, führt update-svnversion-h.pl (was dieses Mal nichts bringt, da svnversion.h auf dem neuesten Stand ist), kompiliert dann neu svnversion.cpp zu machen svnversion.o .

Gibt es eine Möglichkeit, GNU make anzuweisen, eine einzelne Voraussetzung zweimal zu überprüfen oder die Überprüfung des Zeitstempels einer Voraussetzung zu verzögern, bis die Befehle dieser Voraussetzung beendet sind?

Oder gibt es eine bessere Möglichkeit, eine Revisionsnummer in meinen Quellcode einzubetten? (Aus Geschwindigkeitsgründen versuche ich, Lösungen zu vermeiden, die eine Neukompilierung bei jedem Build erfordern würden).

2voto

CesarB Punkte 41671

Dies scheint ähnlich zu sein wie das, was Autotools für seinen config.h-Header verwendet.

Ein kurzer Blick auf automake's remake-hdr.am zeigt, wie der Trick funktioniert:

%CONFIG_H%: %STAMP%
## Recover from removal of CONFIG_HEADER
    @if test ! -f $@; then \
      rm -f %STAMP%; \
      $(MAKE) $(AM_MAKEFLAGS) %STAMP%; \
    else :; fi

%STAMP%: %CONFIG_H_DEPS% $(top_builddir)/config.status
    @rm -f %STAMP%
    cd $(top_builddir) && $(SHELL) ./config.status %CONFIG_H_PATH%

Und config.status erstellt die Stempeldatei.

Der Hauptunterschied zwischen diesem automake-Beispiel und Ihrem Beispiel scheint darin zu bestehen, dass automake die Stempeldatei berührt, während sie in Ihrem Beispiel nicht einmal eine echte Datei ist.

2voto

Jamie Punkte 6506

Hier ist ein Ziel, das ich in meine Make-Dateien aufgenommen habe. Es erzeugt eine Reihe von Funktionen, die verschiedene Build-Telemetrien als Strings zurückgeben. Das Schöne daran ist, dass die Telemetrie das letzte Mal verlinkt ist, nicht wenn ein Objekt gebaut wird.

##
## on every build, record the working copy revision string
##
svn_version.c: $(C_SRC:.c=.o) Makefile
    @echo -n 'const char* build_date(void);\n'  > $@
    @echo -n 'const char* build_date(void)\n{ static const char* build_date = __DATE__ ; '  >> $@
    @echo 'return build_date; }\n'                                                          >> $@
    @echo -n 'const char* build_time(void);\n'                                              >> $@
    @echo -n 'const char* build_time(void)\n{ static const char* build_time = __TIME__ ; '  >> $@
    @echo 'return build_time; }\n'                                                          >> $@
    @echo -n 'const char* svnid_build(void);\n'                                             >> $@
    @echo -n 'const char* svnid_build(void)\n{ static const char* SVN_Version = "\\n<SVN_PID>'    >> $@
    @svnversion -cn .                                                                       >> $@
    @echo '</svn_pid>\\n"; return SVN_Version; }\n'                                         >> $@
    @echo -n 'const char* svnid_build_str_only(void);\n'                                    >> $@
    @echo -n 'const char* svnid_build_str_only(void)\n{ static const char* SVN_Version = "' >> $@
    @svnversion -cn .                                                                       >> $@
    @echo '"; return SVN_Version; }\n'                                                      >> $@
    @$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $(@:.c=.o) $@

Stellen Sie sicher, dass Sie die Abhängigkeit von Ihren Objektdateien in Ihrem endgültigen Ziel durch "svn_version.c" ersetzen. Bsp.

final-target: svn_version.c
    $(CC) $(C_SRC:.c=.o) $(<:.c=.o) -o $@

1voto

coppro Punkte 14158

Sie können die Schlüsselwortsubstitution von Subversion verwenden, um die Versionsnummer in Ihren Code einzufügen.

Es ist [im Buch] detailliert beschrieben, aber kurz gesagt, müssen Sie die svn:keywords Eigenschaft für die einzuschließende Datei Rev und setzen dann $Rev$ irgendwo in Ihrem Code. SVN ersetzt dies automatisch durch $Rev: #$ , donde # ist die Revisionsnummer. Sie müssen die resultierende Zeichenkette analysieren, um die tatsächliche Nummer zu erhalten, aber es sollte ein einfaches Parsen sein (lassen Sie einfach die ersten sechs Zeichen und das letzte Zeichen weg).

Beachten Sie, dass dies die letzte geänderte Revision dieser Datei ist, nicht die letzte geänderte Revision des Projektarchivs. Das ist etwas komplexer und wird auf der Buchseite ausführlich beschrieben.

1voto

Josh Kelley Punkte 52169

Ich habe das Problem gelöst, indem ich meine check-svnversion-Regel svnversion.o löschen ließ, um zu erzwingen, dass sie bei Bedarf neu kompiliert wird. Das ist nicht gerade elegant, aber es funktioniert; es sieht ähnlich aus wie die autotools-Lösung, die in CesarB's Antwort .

../shared/svnversion.h: check-svnversion

check-svnversion:
    ../shared/update-svnversion-h.pl
    @#Force recreation of svnversion.o.  Otherwise, make won't notice that
    @#svnversion.h has changed until the next time it's invoked.
    @if [ ../shared/svnversion.h -nt shared/svnversion.o ] ; then rm shared/svnversion.o ; fi

shared/svnversion.o: ../shared/svnversion.h

.PHONY: check-svnversion

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