Forum: Compiler & IDEs einbinden von __DATE__ __TIME__ in ein binary


von H. R. (hacker_r)


Lesenswert?

Hi
ich wurde gerne compile time und date in mein binary drin haben.

Dazu habe ich ein extra file: compile_time_date.c wo steht:

static const char  compileDate[12] = _DATE_;
static const char  compileTime[12] = _TIME_;

Nun wurde ich gerne den Compiler dazu bringen diese Datei jedes Mal neu 
zu compilieren, dass tut es aber nicht. Weil compile_time_date.c sich ja 
nicht geändert hat, auch wenn die Zeit sich geändert hat.

Gibt es da ein weg?
Danke

von Teo D. (teoderix)


Lesenswert?


von H. R. (hacker_r)


Lesenswert?

ein clean ist in meine Anwendung keine option. Compile time = 2h.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

H. R. schrieb:
> Gibt es da ein weg?

Mehrere.

Erstens kannst du natürlich deinem make sagen, dass das Target 
compile_time_date.o nicht nur von compile_time_date.c abhängt, sondern 
auch von einem fiktiven ("phony") target, welches stets zuvor gebaut 
werden muss.
1
all: foo.o
2
3
foo.o: foo.c dummy
4
        cc -O -c foo.c
5
6
dummy: 
7
8
.PHONY: dummy

Zweitens könntest du natürlich stattdessen auch die passenden Strings 
für Datum und Uhrzeit gleich irgendwie in der Shell ermitteln lassen und 
dann die zu compilierende Datei jedesmal neu bauen lassen. Hat den 
zusätzlichen Vorteil, dass du in der Wahl des Datums- und Zeitformats 
völlig frei bist.
1
all: foo.o
2
3
foo.o: foo.c
4
5
foo.c: dummy
6
        echo 'static const char tstamp[] = "'$$(date +'%Y-%m-%dT%H%M%S')'";' > foo.c
7
8
dummy:
9
10
.PHONY: dummy

von Dr. Sommer (Gast)


Lesenswert?

H. R. schrieb:
> ich wurde gerne compile time und date in mein binary drin haben.

Bei so etwas sollte man vorsichtig sein. Dadurch unterscheiden sich zu 
einem späteren Zeitpunkt gebaute Binaries, auch wenn sie funktional 
identisch sind. Besonders hinterhältig ist es, wenn ein Binary aus 
vielen einzelnen Dateien besteht (z.B. ein Embedded Linux oder Android 
Image), die alle einen eigenen Timestamp haben, der aber auch noch 
unterschiedlich ist (da nicht alle Dateien in der selben Sekunde 
kompiliert werden). Da die Build-Reihenfolge nicht fix ist, lässt sich 
selbst durch Modifizieren der Systemzeit ein Build-Image nicht 100% 
reproduzieren.

Jörg W. schrieb:
> Hat den
> zusätzlichen Vorteil, dass du in der Wahl des Datums- und Zeitformats
> völlig frei bist.

Da muss man aber genau aufpassen, dass der String immer gleich lang 
ist (bei _DATE_ zum Glück der Fall), denn sonst kann z.B. je nach 
Monats/Tag-Namen oder führenden Nullen das Datum eine andere Länge 
haben, wodurch dann die Länge des Binary variieren kann, was ein binäres 
Vergleichen (z.B. mit vbindiff) stark erschwert, auch weil sich dann 
alle Adressen ändern.

Ähnlich tückisch ist das Einbinden von git-Revisions-Hashes: Wenn eine 
Codebasis mehrere Dateien produziert (z.B. Module aus dem 
Linux-Source-Code), ändern sich durch Commits alle erzeugten Dateien, 
inkl. Modulen, obwohl der Inhalt ggf. sonst komplett identisch ist.

Genau diese Probleme hatte ich mal - ein Embedded-Linux-Image, dessen 
zugrundeliegender Sourcecode/Konfiguration nicht mehr exakt erhalten 
war. Mit viel Fummelei konnte ich dann die Konfiguration reverse 
engineeren, aber das Image war dank zahlreicher Timestamps trotzdem 
unterschiedlich. Ich musste die Datums-Strings hartkodieren um 
feststellen zu können, ob ich jetzt die Konfiguration vollständig 
korrekt hatte...

Wenn also ein Datum gebraucht wird, sollte man dies wirklich nur an 
genau eine Stelle des Image packen. Dann kann man auch mehrere Binaries 
vergleichen und relativ leicht einen alten Build reproduzieren.

H. R. schrieb:
> Compile time = 2h.

Klingt nach einem kompletten Linux-System - dann vielleicht die 
Datums-Erzeugung in das Tool integrieren, welches das System-Image 
zusammenpackt (Partitionen+Bootloader). Man könnte das Datum vor den 
Bootloader packen o.ä.

von Harry L. (mysth)


Lesenswert?

Ein simples

touch <fname.c>

Bei dem anschließenden "make" wird nur diese eine C-Datei neu compiliert 
und anschließend das Projekt neu gelinkt.

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Dr. Sommer schrieb:
> wodurch dann die Länge des Binary variieren kann, was ein binäres
> Vergleichen (z.B. mit vbindiff) stark erschwert

Naja, wenn man sowas vorhat, dann sollte man auf Kinkerlitzchen wie ein 
Compiledatum sinnvollerweise verzichten. Das bringt weniger Information 
als man zuerst glauben mag. Git revision könnte da schon mehr bringen.

Ansonsten bliebe der Weg, sich per Linkerscript darum zu kümmern, dass 
der so generierte String stets als allerletztes im Binary landet. Dann 
kann man den bindiff vom Anfang immer noch durchführen.

Übrigens gibt mein date-Kommando da oben den Timestamp im ISO8601-Format 
aus, sodass er wirklich immer gleich lang ist.

von Dr. Sommer (Gast)


Lesenswert?

Jörg W. schrieb:
> Naja, wenn man sowas vorhat, dann sollte man auf Kinkerlitzchen wie ein
> Compiledatum sinnvollerweise verzichten.

Die Notwendigkeit für binäres Diff ergibt sich typischerweise nachdem 
man schon diverse Images erstellt hat; absichtlich Einplanen tut man das 
wohl kaum. Für den Fall dass es nötig werden könnte muss man sich aber 
vorher Gedanken machen.

Jörg W. schrieb:
> Ansonsten bliebe der Weg, sich per Linkerscript darum zu kümmern, dass
> der so generierte String stets als allerletztes im Binary landet. Dann
> kann man den bindiff vom Anfang immer noch durchführen.

Das geht auch, aber die genaue Position des Datums ist nicht so relevant 
wenn es immer gleich lang ist, und es auch nur genau eins davon gibt.

Idealerweise gibt es im Build-Prozess eine zentrale Stelle, an der das 
Build-Datum einmal erzeugt wird. Wenn man mehrere Timestamps hat, 
sollten die alle dieses Datum nehmen, welches dann auch überall gleich 
ist. Das kann man dann zu Testzwecken auch manuell auf ein (altes) Datum 
setzen. Leider unterstützt z.B. das Android-Build-System so etwas nicht; 
wenn man da 2x das gleiche Image kompilieren will, hat man riesige 
Unterschiede, weil an zig Stellen unterschiedliche Timestamps stehen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.