Globale SVN-Revisionsnummer im Projekt - und zwar richtig!
Wenn man ein Projekt aufsetzt, dann hat man meist eine Versionsnummer im Format
Und wird von SVN beim Commit ersetzt zu
Vorausgesetzt natürlich, dass die Datei die entsprechenden SVN-Keywords gesetzt hat:
So weit, so gut. In dem Beispiel oben ist die Revisionsnummer 178. Wenn es jetzt aber noch eine zweite Datei gibt und Änderungen an dieser comitted werden, dann bleibt in main.cpp die 178 stehen. Warum? Weil die SVN-Revisionsnummer dateibezogen ist - nicht projektbezogen! Das ist ja jetzt nicht ganz das, was wir haben wollten. Zum Glück, gibt es aber ein Tool, welches genau für unsere Zwecke gedacht ist: svnversion! Um eine globale Revisionsnummer zu erhalten erstellt man eine leere Datei revision.h, checkt sie nicht in SVN ein und schreibt folgendes in die *.pro-Projektdatei eines Qt-Projekts:
Zur Erklärung:
Als erstes wird qmake mitgeteilt, dass es eine zusätzliche Abhängigkeit gibt (PRE_TARGETDEPS, Zeile 1) - nämlich besagte revision.h-Datei.
Dann werden ein paar Variablen mit den SVN-Revisionsinformationen gefüllt.
Mit dem Kommando
a.b.c.d
, mita
= Hauptversionsnummer, ändert sich eigentlich nur bei massiven Änderungenb
= zeigt an, dass neue Features hinzugekommen sindc
= zeigt an, dass etwas gepatched bzw. geupdated wurded
= gibt den Revisionsstand der Software im Versionsverwaltungssystem an.
- /*!
- *******************************************************************************
- * File identification: $Id:$
- * Revision of last commit: $Rev:$
- * Author of last commit: $Author:$
- * Date of last commit: $Date:$
- *******************************************************************************
- */
- /*!
- *******************************************************************************
- * File identification: $Id: main.cpp 178 2016-02-08 14:42:36Z cypax $
- * Revision of last commit: $Rev: 178$
- * Author of last commit: $Author: cypax $
- * Date of last commit: $Date: 2016-02-08 15:42:36 +0100 (Mo, 08 Feb 2016) $
- *******************************************************************************
- */
So weit, so gut. In dem Beispiel oben ist die Revisionsnummer 178. Wenn es jetzt aber noch eine zweite Datei gibt und Änderungen an dieser comitted werden, dann bleibt in main.cpp die 178 stehen. Warum? Weil die SVN-Revisionsnummer dateibezogen ist - nicht projektbezogen! Das ist ja jetzt nicht ganz das, was wir haben wollten. Zum Glück, gibt es aber ein Tool, welches genau für unsere Zwecke gedacht ist: svnversion! Um eine globale Revisionsnummer zu erhalten erstellt man eine leere Datei revision.h, checkt sie nicht in SVN ein und schreibt folgendes in die *.pro-Projektdatei eines Qt-Projekts:
- PRE_TARGETDEPS += $$PWD/code/revision.h
- # Obtain SVN revision
- SVN_REVISION = $$system(svnversion -n)
- # split into list by ':'
- REVISION_LIST = $$split(SVN_REVISION,:)
- # get last item of list
- HEAD_REVISION = $$last(REVISION_LIST)
- # remove M (modified working copy)
- HEAD_REVISION = $$replace(HEAD_REVISION,M,)
- # remove S (switched working copy)
- HEAD_REVISION = $$replace(HEAD_REVISION,S,)
- # remove P (partial working copy, from a sparse checkout)
- HEAD_REVISION = $$replace(HEAD_REVISION,P,)
- QMAKE_EXTRA_TARGETS += revtarget
- revtarget.target = $$PWD/code/revision.h
- unix {
- revtarget.commands = "$$system(echo \'/* generated file - do not edit */\' > $$revtarget.target)"
- revtarget.commands += "$$system(echo \'$${LITERAL_HASH}ifndef REVISION_H\' >> $$revtarget.target)"
- revtarget.commands += "$$system(echo \'$${LITERAL_HASH}define REVISION_H\' >> $$revtarget.target)"
- revtarget.commands += "$$system(echo \'$${LITERAL_HASH}define SVN_REVISION \"$$SVN_REVISION\"\' >> $$revtarget.target)"
- revtarget.commands += "$$system(echo \'$${LITERAL_HASH}define HEAD_REVISION $$HEAD_REVISION\' >> $$revtarget.target)"
- revtarget.commands += "$$system(echo \'$${LITERAL_HASH}define HEAD_REVISION_STRING \"$$HEAD_REVISION\"\' >> $$revtarget.target)"
- revtarget.commands += "$$system(echo \'$${LITERAL_HASH}endif // REVISION_H\' >> $$revtarget.target)"
- }
- win32 {
- revtarget.commands = "$$system(echo '/* generated file - do not edit */' > $$revtarget.target)"
- revtarget.commands += "$$system(echo '$${LITERAL_HASH}ifndef REVISION_H' >> $$revtarget.target)"
- revtarget.commands += "$$system(echo '$${LITERAL_HASH}define REVISION_H' >> $$revtarget.target)"
- revtarget.commands += "$$system(echo '$${LITERAL_HASH}define SVN_REVISION \"$$SVN_REVISION\"' >> $$revtarget.target)"
- revtarget.commands += "$$system(echo '$${LITERAL_HASH}define HEAD_REVISION $$HEAD_REVISION' >> $$revtarget.target)"
- revtarget.commands += "$$system(echo '$${LITERAL_HASH}define HEAD_REVISION_STRING \"$$HEAD_REVISION\"' >> $$revtarget.target)"
- revtarget.commands += "$$system(echo '$${LITERAL_HASH}endif // REVISION_H' >> $$revtarget.target)"
- }
- revtarget.depends = FORCE
- QMAKE_DISTCLEAN += $$revtarget.target
svnversion -n
(Zeile 4) erhält man die SVN-Revisionsnummer. Der Parameter -n bewirkt, dass die Ausgabe keinen Zeilenumbruch enthält.
Die Variable SVN_REVISION enthält somit die Ausgabe von svnversion, ausgehend vom Pfad, in der die Projektdatei liegt.
Wenn die lokale Arbeitskopie allerdings modifiziert, unvollständig ausgecheckt oder zu einer anderen Revision geswitched wurde, ist die Revisionsnummer nicht einfach eine Zahl, sondern nach dem Schema [abc:]xyz[M|S|P] aufgebaut, wobei xyz die Headrevision ist (für Details einfach mal in der Konsole svnversion -help
eingeben).
Aus diesem Grund teilen wir die Ausgabe anhand des Trennzeichens ":" auf (Zeile 6), nehmen das letzte Element dieser Liste (Zeile 8) und entfernen alle M-, S- und P-Zeichen (Zeilen 10 - 14).
In Zeile 16 wird qmake mitgeteilt, dass es ein zusätzliches Target revtarget gibt (QMAKE_EXTRA_TARGETS), welches die, im Unterordner /code befindliche, revision.h-Datei ist und welche stets neu zu erstellen ist (Zeile 39).
Das Befüllen der revision.h erfolgt in den Zeilen 19 - 37. Zu beachten ist, dass die erste echo-Ausgabe mit einem einfachen >
umgeleitet wird. Dadurch wird der der Inhalt der Datei überschrieben. Anhängen weiterer Zeilen erfolgt mit >>
.
Die echo-Anweisungen für Unix müssen übrigens deshalb extra escaped werden, weil ein echo /* generated file - do not edit */
erst alle Dateien unter / auflisten würde, dann "generated file - do not edit" ausgibt und dann alle Dateien im aktuellen Verzeichnis auflistet.
Wer ein Hobby mit Computern und Elektronik hat weiß, dass der Umgang mit technischen Dingen beileibe nicht für die Mehrheit der Leute zu den Lieblingsbeschäftigungen gehört - insbesondere, wenn das technische Ding nicht tut was es soll.
Das zeigt sich nämlich immer dann, wenn die liebe Verwandt- und Bekanntschaft wieder auf der Matte steht mit einem fahrlässig, mutwillig oder ahnungslos malträtiertem Gerät in der Hand und dem Spruch
Und meistens handelt es sich dann um spannende und präzise formulierte Problemstellungen wie
"Mein Windows ist total komisch geworden ..."
"Ich krieg das Programm nicht ins Internet installiert ..."
"Das Handy geht irgendwie nicht mehr ..."
Super nervig, so was.
Aber manchmal, ganz selten nur, gibt es dann doch mal was Interessantes. - So hatte ich jüngst dieses Gefährt bekommen, um es zu reparieren:
Dieser kleine Panzer nennt sich "Camper Trolley" und ist eine Einparkhilfe für Wohnanhänger: der Anhänger wird oben angekoppelt und per Fernsteuerung navigiert man das ungleiche Gespann zur gewünschten Stelle auf dem Campingplatz. Das klingt zwar vielleicht erst mal etwas obskur, aber der Campingpanzer hat es durchaus in sich und bringt laut Hersteller eine enorme Zugkraft von 1500kg mit sich. - Das haben wir mit Abschleppseil und Bobbycar natürlich auch umgehend ausprobiert. Und außerdem macht es irre Spaß, damit durch den Sandkasten auf dem Spielplatz zu pflügen. Abseits von Spiel&Spaß und dem eigentlichen Verwendungszweck böte sich so ein kleines Monster aber auch prima als Basisplattform für einen Roboter an. Der Preis wäre mir für eine Roboterbastelei dann allerdings doch etwas zu hoch (um die 1k €, gebraucht, in der Bucht). Und leider ist das Teil ebenso langsam wie stark. Also wird das nix mit uns - ist repariert und geht zurück an die Besitzer. PS: Und was war nun eigentlich kaputt an dem Ding? ⇒ Die Senderbatterie war leer ;-)
Du kennst dich doch mit so was aus ...
... kannst du da nicht irgendwas machen?
Dieser kleine Panzer nennt sich "Camper Trolley" und ist eine Einparkhilfe für Wohnanhänger: der Anhänger wird oben angekoppelt und per Fernsteuerung navigiert man das ungleiche Gespann zur gewünschten Stelle auf dem Campingplatz. Das klingt zwar vielleicht erst mal etwas obskur, aber der Campingpanzer hat es durchaus in sich und bringt laut Hersteller eine enorme Zugkraft von 1500kg mit sich. - Das haben wir mit Abschleppseil und Bobbycar natürlich auch umgehend ausprobiert. Und außerdem macht es irre Spaß, damit durch den Sandkasten auf dem Spielplatz zu pflügen. Abseits von Spiel&Spaß und dem eigentlichen Verwendungszweck böte sich so ein kleines Monster aber auch prima als Basisplattform für einen Roboter an. Der Preis wäre mir für eine Roboterbastelei dann allerdings doch etwas zu hoch (um die 1k €, gebraucht, in der Bucht). Und leider ist das Teil ebenso langsam wie stark. Also wird das nix mit uns - ist repariert und geht zurück an die Besitzer. PS: Und was war nun eigentlich kaputt an dem Ding? ⇒ Die Senderbatterie war leer ;-)
Neues vom Roboterclub
Der Roboterclub-Freiburg hat sich wieder getroffen und es gab ein paar neue Basteleien zu bewundern.
So wie diesen fernsteuerbaren WALL-E aus Lego und Pappe.
Und auch Roboter aus dem 3D-Drucker sind jetzt keine Seltenheit mehr im Club:
Und auch Roboter aus dem 3D-Drucker sind jetzt keine Seltenheit mehr im Club:
Heimatkunde aus dem 3D-Drucker
Nachdem ich dieses Jahr bereits eine 3D-Karte im Miniformat gedruckt hatte, habe ich nun den Maßstab etwas erhöht:
Sechs Kacheln á 20 x 20 cm, aneinander geklebt und mit Airbrush und Pinsel bemalt: Zur Orientierung: Freiburg liegt im Zentrum. Links der Rhein mit ein paar Baggerseen. Aus der Rheinebene ehebt sich der Kaiserstuhl. Ganz oben links befindet sich Sélestat. Links unten kann man noch die östlichen die Ausläufer von Mulhouse erkennen. Rechts auf der Karte der Südschwarzwald mit dem Schluchsee. Links vom Schluchsee der Feldberg und unterhalb von Freiburg der Schauinsland.
Sechs Kacheln á 20 x 20 cm, aneinander geklebt und mit Airbrush und Pinsel bemalt: Zur Orientierung: Freiburg liegt im Zentrum. Links der Rhein mit ein paar Baggerseen. Aus der Rheinebene ehebt sich der Kaiserstuhl. Ganz oben links befindet sich Sélestat. Links unten kann man noch die östlichen die Ausläufer von Mulhouse erkennen. Rechts auf der Karte der Südschwarzwald mit dem Schluchsee. Links vom Schluchsee der Feldberg und unterhalb von Freiburg der Schauinsland.