Ich möchte cmake verwenden, um VERSION im Falle von Release-Builds auf eine Release-Version und ansonsten auf die Kompilierzeit festzulegen.
Bei der Verwendung von make für Entwicklungs-Builds war das Abrufen der Kompilierzeit einfach über
-DVERSION=`date +%Y-%m-%d_%H:%M`
die direkt von c/c++ Quellcode verwendet werden könnte. Leider habe ich nicht herausgefunden, wie das gleiche mit cmake erreicht werden kann.
string(TIMESTAMP VERSION "%Y-%m-%d %H:%M")
add_definitions(-DVERSION="${VERSION}")
setzt VERSION auf die Zeit, zu der cmake ausgeführt wurde. Wie kann ich VERSION auf die Kompilierzeit setzen, wenn ich cmake verwende (um zu vermeiden, mit __DATE__ und __TIME__ in Abwesenheit eines RELEASE-Flags)?
Hier ist eine nützliche Antwort für Ihr Problem. Sie müssen sicherstellen, dass Sie einen Befehl wie haben date verfügbar mit Ihrer Host-Build-Umgebung. Eine generische Lösung mit der __DATE__ und __TIME__ Makros wären auch einfach, indem Sie einfach eine Header-Datei mit den erforderlichen Definitionen bereitstellen, die bei jedem Build generiert (oder zumindest berührt) wird (als Pre-Build-Aktion).
– πάντα ῥεῖ
18. Juni 2014 um 19:06 Uhr
Im Allgemeinen besteht der Zweck einer Versionsnummer darin, dies zu können Reproduzieren Sie die genauen Quelldateien, mit denen eine Binärdatei erstellt wurde. Verwenden Sie daher den Zeitstempel der Zusammenstellung ist ein sehr, sehr schlechte Wahl. Weisen Sie korrekte Versionsnummern zu und pflegen Sie sie, oder verwenden Sie etwas aus Ihrer Versionskontrollsoftware (Zweig / Revision für SVN, Hashcode für GIT), wenn Sie sich nicht darum kümmern können. Verwenden Sie einfach keinen Zeitstempel für die Kompilierung, es ist sogar noch schlimmer, als gar keine Version zu haben, weil Sie eine neuere Kompilation älterer Quellen haben könnten, was für alle, einschließlich Sie selbst, verwirrend wäre.
– DevSolar
14. Juli 2015 um 8:43 Uhr
@DevSolar Ich denke, Sie mischen hier verschiedene Ideen. Der Zweck der Revision, nicht der Version, ist es, die exakten Quelldateien reproduzieren zu können. Der Zweck der Build-ID besteht darin, die genauen Build-Artefakte auf unserem Build-/Entwicklungscomputer finden zu können. Der Zweck der App/Lib-Version ist eigentlich breit gefächert, angefangen bei Marketingzwecken bis hin zu Abwärtskompatibilitätsproblemen. Die App/Lib-Version kann eine Build-ID oder Revision enthalten oder nicht. Es liegt an den Entwicklern (Ops), wie eine bestimmte Version zum Erstellen oder Überarbeiten nachverfolgt wird. Der Zeitstempel kann sehr gut als Build-ID für Entwickler-Builds dienen.
– Alex Che
18. Oktober 2021 um 15:50 Uhr
@AlexChe: Das Problem mit einer Zeitstempel-Build-ID besteht darin, dass ein Zeitstempel es nicht erlaubt, die Binärdatei zu ihren Quellen zurückzuverfolgen, es sei denn, Sie arbeiten nur mit einem einzigen Codezweig – und selbst dann müssen Sie mit dem VCS herumspielen, das Sie sind verwenden. Eine VCS-Revision ist besser, verliert aber immer noch an Aussagekraft, wenn Sie zB Ihr VCS migrieren müssen (oder wollen). IMHO sollten Sie eine Produktversion und Komponentenversionen haben und idealerweise eine VCS-spezifische Methode verwenden, um die Quellen zu markieren, die in einen Komponenten-Build eingeflossen sind, den Sie bei Bedarf auf ein anderes VCS migrieren könnten.
string(TIMESTAMP ... wird zwischengespeichert, bis Sie ihn bearbeiten CMakeLists.txt
– Tomilov Anatoliy
14. Juni 2018 um 13:11 Uhr
dbnet
Meine plattformübergreifende Lösung erstellt beim ersten Lauf von CMake eine Datei timestamp.cmake im Binärverzeichnis und definiert ein Ziel timestamp die die generierte Datei ausführt. Die Datei timestamp.cmake bildet eine ISO 8601-Zeitstempelzeichenfolge mit der STRING CMake-Befehl und schreibt ihn in eine Datei timestamp.h mit einer #define _TIMEZ_ Präprozessordirektive vorangestellt (Definitionen mit einem führenden Unterstrich sind in Ordnung; Definitionen mit zwei führenden Unterstrichen sollten nicht benutzerdefiniert sein).
Dann nutzen Sie die ADD_DEPENDENCIES CMake-Befehl, um Ihr Hauptziel (wahrscheinlich die ausführbare Hauptdatei) von der timestamp Ziel. Es wird von CMake immer als veraltet angesehen, daher wird es jedes Mal aktualisiert, wenn das Hauptziel neu erstellt wird, wodurch die Erstellungszeit wie angefordert aktualisiert wird.
Mit diesem Befehl können Sie bei Bedarf mehrere zusätzliche Abhängigkeiten angeben, die durch Leerzeichen getrennt sind.
Dann kannst du eben #include "timestamp.h" (vorausgesetzt, das CMake-Binärverzeichnis befindet sich im Include-Pfad, was normalerweise der Fall ist. Wenn nicht, ist das einfach: INCLUDE_DIRECTORIES (${CMAKE_BINARY_DIR})) und verwenden _TIMEZ_ wann immer Sie den Build-Zeitstempel im ISO 8601-Format haben möchten (oder was auch immer Sie möchten: Sie können es selbst festlegen, siehe CMake-Dokumentation für STRING Befehlsverwendung).
Dies hätte einfacher gemacht werden können, indem die Datei direkt (von Hand) erstellt wurde timestamp.cmake und es zu Ihrem Code-Repository hinzufügen, aber ich habe es als nicht sauber genug angesehen. Es ist ein allgemeiner Nachteil von CMake, dass Sie nicht auf das Verfahren zum Erstellen von Zeitstempelzeichenfolgen zugreifen können (das in der STRING CMake-Befehl) in der Phase, in der das Backend von CMake, was auch immer es ist (z. B. GNU make), ausgeführt wird, sodass man eine separate CMake-Datei verwenden und in dieser Phase aufrufen muss. Dies hätte viel einfacher und sauberer gemacht werden können, wenn Sie die CMake-Zeitstempel-String-Bildungsprozedur im “CMake-Befehlsmodus” aufrufen könnten (cmake -E Art des Aufrufs), zum Beispiel so: cmake -E date [format] [UTC], aber leider. Ich habe hat ein Ticket im Bugtracker Mantis von CMake eingereicht.
Sie können dazu beitragen, indem Sie meine Feature-Anfrage unterstützen und einige Kommentare posten, die zeigen, wie sehr Sie dies benötigen.
Definiert mit führendem Unterstrich und dann ein Großbuchstabe ist eigentlich nicht ok. (Nicht, dass das zu wichtig wäre.)
– Praxeolit
24. Mai 2016 um 14:11 Uhr
(das ist alt, aber) so verstehe ich das alle (unscoped) Symbole, die mit einem führenden Unterstrich beginnen, sind der Implementierung vorbehalten.
– jwm
1. Juni 2020 um 20:24 Uhr
Vielleicht könnten Sie die Compiler-Makros verwenden __DATE____TIME__ in Ihrem Code, anstatt es von cmake zu bekommen. Erwähnenswert ist, dass Sie clean/make ausführen müssen, um diese Werte zu aktualisieren (da GCC es einbettet, wird es nicht erneut kompiliert, wenn das Objekt bereits kompiliert ist, also keine Datums-/Uhrzeitänderung)
Dies ist ein vernünftiger Ratschlag, hat aber den Nachteil, dass vollständig reproduzierbare Builds seit dem verhindert werden __DATE__ und __TIME__ ändert sich je nach Kompilierzeit. Stattdessen kann es besser sein, diese Werte zur Kompilierzeit als verschiedene Makros zu übergeben.
– ddavella
17. November 2021 um 14:24 Uhr
Ein paar Jahre später stimme ich dir wirklich zu. Mit DATUM und ZEIT man wird nicht in der Lage sein, eine 1:1-Binärdatei von einer bestimmten Version zu erstellen.
Ich bin vor einiger Zeit auf dasselbe Problem gestoßen und habe schließlich geschrieben dieses Repo als Lösung. Fügen Sie es einfach als CMake-Unterverzeichnis hinzu und build_date_str wird die enthalten Linkzeit Ihres Programms.
Für den Fall, dass github vor dem Stackoverflow offline geht, ist die Idee dieser Lösung:
Ein … kreieren BUILD_TIME CMake-Variable mit string(TIMESTAMP ... wie in den obigen Lösungen.
Stellen Sie eine kleine Bibliothek zusammen, die die aufzeichnet BUILD_TIME in eine globale Variable (die Sie drucken können oder was auch immer) aus Ihrem Programm.
Machen Sie das Erstellen dieser Bibliothek von einem benutzerdefinierten Ziel abhängig, mit dem die Variable aus dem CMake-Cache entfernt wird cmake -U BUILD_TIME.
Dies bedeutet, dass jedes Mal, wenn Sie Ihr Projekt erstellen, die Abhängigkeiten überprüft und der CMake-Cache gelöscht wird, wodurch CMake für diese Zeitstempelbibliothek erneut ausgeführt wird. Ein Nachteil dieser Lösung ist, dass Sie bei einem CI-System alle Parameter, die Sie an Ihren CMake-Schritt übergeben, daran denken müssen, sie auch an Ihren Build-Schritt zu übergeben.
13846700cookie-checkKompilieren Sie Datum und Uhrzeit mit cmakeyes
Hier ist eine nützliche Antwort für Ihr Problem. Sie müssen sicherstellen, dass Sie einen Befehl wie haben
date
verfügbar mit Ihrer Host-Build-Umgebung. Eine generische Lösung mit der__DATE__
und__TIME__
Makros wären auch einfach, indem Sie einfach eine Header-Datei mit den erforderlichen Definitionen bereitstellen, die bei jedem Build generiert (oder zumindest berührt) wird (als Pre-Build-Aktion).– πάντα ῥεῖ
18. Juni 2014 um 19:06 Uhr
Im Allgemeinen besteht der Zweck einer Versionsnummer darin, dies zu können Reproduzieren Sie die genauen Quelldateien, mit denen eine Binärdatei erstellt wurde. Verwenden Sie daher den Zeitstempel der Zusammenstellung ist ein sehr, sehr schlechte Wahl. Weisen Sie korrekte Versionsnummern zu und pflegen Sie sie, oder verwenden Sie etwas aus Ihrer Versionskontrollsoftware (Zweig / Revision für SVN, Hashcode für GIT), wenn Sie sich nicht darum kümmern können. Verwenden Sie einfach keinen Zeitstempel für die Kompilierung, es ist sogar noch schlimmer, als gar keine Version zu haben, weil Sie eine neuere Kompilation älterer Quellen haben könnten, was für alle, einschließlich Sie selbst, verwirrend wäre.
– DevSolar
14. Juli 2015 um 8:43 Uhr
@DevSolar Ich denke, Sie mischen hier verschiedene Ideen. Der Zweck der Revision, nicht der Version, ist es, die exakten Quelldateien reproduzieren zu können. Der Zweck der Build-ID besteht darin, die genauen Build-Artefakte auf unserem Build-/Entwicklungscomputer finden zu können. Der Zweck der App/Lib-Version ist eigentlich breit gefächert, angefangen bei Marketingzwecken bis hin zu Abwärtskompatibilitätsproblemen. Die App/Lib-Version kann eine Build-ID oder Revision enthalten oder nicht. Es liegt an den Entwicklern (Ops), wie eine bestimmte Version zum Erstellen oder Überarbeiten nachverfolgt wird. Der Zeitstempel kann sehr gut als Build-ID für Entwickler-Builds dienen.
– Alex Che
18. Oktober 2021 um 15:50 Uhr
@AlexChe: Das Problem mit einer Zeitstempel-Build-ID besteht darin, dass ein Zeitstempel es nicht erlaubt, die Binärdatei zu ihren Quellen zurückzuverfolgen, es sei denn, Sie arbeiten nur mit einem einzigen Codezweig – und selbst dann müssen Sie mit dem VCS herumspielen, das Sie sind verwenden. Eine VCS-Revision ist besser, verliert aber immer noch an Aussagekraft, wenn Sie zB Ihr VCS migrieren müssen (oder wollen). IMHO sollten Sie eine Produktversion und Komponentenversionen haben und idealerweise eine VCS-spezifische Methode verwenden, um die Quellen zu markieren, die in einen Komponenten-Build eingeflossen sind, den Sie bei Bedarf auf ein anderes VCS migrieren könnten.
– DevSolar
20. Oktober 2021 um 11:49 Uhr