Versionsinformation beim kompilieren in Datei speichern

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
Antworten
Ich934
Lazarusforum e. V.
Beiträge: 317
Registriert: So 5. Mai 2019, 16:52
OS, Lazarus, FPC: ArchLinux und Windows mit FPCUPdeluxe (L: 2.0.X, FPC 3.2.0)
CPU-Target: x86_64, i386
Wohnort: Bayreuth

Versionsinformation beim kompilieren in Datei speichern

Beitrag von Ich934 »

Guten morgen,

ich pglege die Versionsinformationen bei meinen Programmen an sich sehr zuverlässig und nutze diese auch für die Updatesteuerung. Bei Linuxprogrammen bzw. verteilen Programmen benötige ich diese Information dann jedoch in einer extra Datei, welche ich bisher immer manuell pflege.

Ich kann in Lazarus ja Programme nach dem kompilieren anstarten lassen. Gibt es eine Option, diese Nummer hier in eine Datei schreiben zu lassen oder muss ich mir hier ein Programm schreiben?

Vielen Dank.
Tipp für PostgreSQL: www.pg-forum.de

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6208
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Versionsinformation beim kompilieren in Datei speichern

Beitrag von af0815 »

Innerhalb von Lazarus / FPC ist mir nichts bekannt. Lazarus verwendet ein eigens Tool um die svn/git infos als include einzubinden. Somit musst du entweder ein eigenes kleines Tool schreiben müssen oder das im Quelltext beim starten der Applikation erledigen dürfen.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Ich934
Lazarusforum e. V.
Beiträge: 317
Registriert: So 5. Mai 2019, 16:52
OS, Lazarus, FPC: ArchLinux und Windows mit FPCUPdeluxe (L: 2.0.X, FPC 3.2.0)
CPU-Target: x86_64, i386
Wohnort: Bayreuth

Re: Versionsinformation beim kompilieren in Datei speichern

Beitrag von Ich934 »

Naja die Uprdateprüfung gegen den Server hab ich schon. Das ist nicht das Problem. Nur der Server muss ja auch wissen, welche Version er dort liegen hat. Aber dann bau ich einfach ein Programm dass aus der Projektdatei die Werte ausliest und dann speichert und rufe dies nach dem Kompilieren auf.

Danke trotzdem.
Tipp für PostgreSQL: www.pg-forum.de

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1435
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Versionsinformation beim kompilieren in Datei speichern

Beitrag von fliegermichl »

Also unter Windows kann man bei Projekt -> Projekteinstellungen -> Knoten Projekteinstellungen -> Unterknoten Versionsinformationen das Häkchen "Versionsinfo in ausführbare Datei einfügen" anwählen.
Dann werden diese Informationen als Versionsresource in der exe gespeichert und kann per GetFileVersionInfo abgefragt werden. Unter anderen Betriebssystemen geht das wohl nicht so einfach.

sstvmaster
Beiträge: 576
Registriert: Sa 22. Okt 2016, 23:12
OS, Lazarus, FPC: W10, L 2.2.6
CPU-Target: 32+64bit
Wohnort: Dresden

Re: Versionsinformation beim kompilieren in Datei speichern

Beitrag von sstvmaster »

Wäre es da nicht sinnvoll wenn es in der IDE in den Projekteinstelleungen -> Versionsinformationen ein Feld
gibt wo man sagen kann ich möchte diese Infos in einer Datei im Projektordner speichern, zb. prjversion.xml oder json?

Die IDE weis ja diese Infos wenn Compiliert wird.

Nur so ein Gedanke von mir.
LG Maik

Windows 10,
- Lazarus 2.2.6 (stable) + fpc 3.2.2 (stable)
- Lazarus 2.2.7 (fixes) + fpc 3.3.1 (main/trunk)

Ich934
Lazarusforum e. V.
Beiträge: 317
Registriert: So 5. Mai 2019, 16:52
OS, Lazarus, FPC: ArchLinux und Windows mit FPCUPdeluxe (L: 2.0.X, FPC 3.2.0)
CPU-Target: x86_64, i386
Wohnort: Bayreuth

Re: Versionsinformation beim kompilieren in Datei speichern

Beitrag von Ich934 »

Die Versionsinfo im Programm ist nicht das Problem. Da steht diese drinnen. Das hilft mir aber nichts wenn ich über das Internet ein check auf eine neue Version mache.

Da benötige ich eine Lösung wie von sstvmaster. Ich brauche die Versionsnummer gesondert einfach in einer Datei. Format ist mir egal. XML, JSON oder einfach nur eine Textdatei. Das kann ich für einen Updateprozess alles parsen. Aber ein ganzen Programm runter laden nur um dann darin die Versionsnummer zu finden ist suboptimal.

Die Information steht übrigens in der .lpi-Datei. Ich schreib jetzt ein kleines Programm das diese dort extrahiert und in eine extra Datei überführt. Problem damit gelöst für mich.
Tipp für PostgreSQL: www.pg-forum.de

Warf
Beiträge: 1909
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Versionsinformation beim kompilieren in Datei speichern

Beitrag von Warf »

So würde ich ein update system voll automatisiert bauen:
Sagen wir mal du hast ein Programm mit mehreren assets (Bildern, DLL's, whatever) dem du einen autoupdater verpassen willst. In dem hauptprojekt solltest du dann irgendwo eine Konstante "Version" mit der Versionsnummer rumliegen haben.
Zunächst einmal gilt es das deployment zu automatisieren. Dafür würde ich ein Deploy script z.B. in python schreiben was folgendes macht:
1. Finde die Versions konstante in der Pascal datei, lese sie aus, inkrementiere sie und schreibe den neuen Wert in die pascal datei
2. baue das projekt (sowie das updater projekt, mehr dazu unten) mit lazbuild
3. Lokalisiere alle deployment dateien (das neu kompilierte Programm, den updater, Bilder, DLL's, whatever) und bilde einen Hash (md5, crc, whatever hauptsache schnell, geht hier nicht um security) von ihnen und erzeuge eine neue Datei version.txt mit folgendem inhalt:

Code: Alles auswählen

VERSIONSNUMMER
relativer/pfad/zu/datei1=Hash von datei1
relativer/pfad/zu/datei2=Hash von datei2
...
relativer/pfad/zu/dateiN:Hash von dateiN

3.b (Optional) gzippe alle dateien (außer der version.txt)
4. Lade alle (gzip) dateien sowie die version.txt hoch
Als nächstes schreibst du ein programm updater, welches das folgende macht:
1. Lese die version.txt die dem programm übergeben wird, ignoriere dabei die erste zeile
2. Für jede datei überprüfe den Hash, wenn dieser nicht übereinstimmt lade die neue version herunter und überschreibe die alte
3. Wenn alles geupdated ist starte das hauptprogramm
In deinem Hauptprogramm hast du dann deine Update routine die das folgende macht:
0. (Optional) Warte bis das hauptprogramm geschlossen ist (manchmal reicht ein sleep 1 sekunde vollkommen aus da braucht man keine komplexe logik)
1. Lade die version.txt runter
2. checker die erste zeile gegen die Versions konstante. Wenn die werte nicht übereinstimmen lade das updater programm runter (somit kann immer garantiert werden das du immer die aktuellste version des updates hast)
3. Starte den update und übergib ihm die version.txt, sowie beende das aktuelle programm

Und tada, immer wenn du einen Release build fertig hast musst du einmal das deploy script ausführen und alles wird automatisch gemacht. Leider kann man dem FPC keine defines mit werten übergeben, daher muss man das suchen in den Source dateien nach der Konstanten machen, was ziemlich hässlich ist (eine andere option wäre die versionsnummer in einer C datei zu speichern der du das als makro übergeben kannst du dann gegen linkst, das wird aber noch unschöner).

Ich934
Lazarusforum e. V.
Beiträge: 317
Registriert: So 5. Mai 2019, 16:52
OS, Lazarus, FPC: ArchLinux und Windows mit FPCUPdeluxe (L: 2.0.X, FPC 3.2.0)
CPU-Target: x86_64, i386
Wohnort: Bayreuth

Re: Versionsinformation beim kompilieren in Datei speichern

Beitrag von Ich934 »

Wie gesagt das Update ist nicht das Problem. Das hab ich. Mir ging es nur darum, ob ich automatisiert die version.txt erstellen kann. Dem scheint nicht der Fall zu sein, weshalb ich jetzt schnell ein Quick&Dirty Programm geschrieben hab, was genau das für mich mach.

Bei jedem Kompilieren wird jetzt die version.txt neu erzeugt. Damit muss ich mich um diese nicht mehr kümmern. Ich lad dann nur die Binaries zzgl. der version.txt auf den Deploy-Server und fertig.

Zu finden ist das Programm hier.
Tipp für PostgreSQL: www.pg-forum.de

Warf
Beiträge: 1909
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Versionsinformation beim kompilieren in Datei speichern

Beitrag von Warf »

Ich934 hat geschrieben:Zu finden ist das Programm hier.


So nur mal am rande, Pascal für so ein programm ist kompletter overkill, für so kleine sachen sind Scriptsprachen viel angenehmer, schau dir mal dieses python script an:

Code: Alles auswählen

#!/usr/bin/env python3
import xml.etree.ElementTree as ET
import argparse
from pathlib import Path
 
def getProjectVersion(project):
  tree = ET.parse(project)
  versionInfo = tree.find("ProjectOptions/VersionInfo")
  if (versionInfo is None) or (versionInfo.find("UseVersionInfo[@Value='True']") is None):
    return (0,0,0,0)
  majorVersion = versionInfo.find("MajorVersionNr").attrib["Value"]
  minorVersion = versionInfo.find("MinorVersionNr").attrib["Value"]
  revision = versionInfo.find("RevisionNr").attrib["Value"]
  build = versionInfo.find("BuildNr").attrib["Value"]
  return (majorVersion, minorVersion, revision, build)
 
def main():
  parser = argparse.ArgumentParser()
  parser.add_argument("target", help="The directory of the target project")
  args = parser.parse_args()
  projectDir = Path(args.target)
  for proj in projectDir.glob('**/*.lpi'):
    version = getProjectVersion(proj)
    print(f"{proj}: {version[0]}.{version[1]}.{version[2]}.{version[3]}")
 
if __name__ == "__main__":
  main()


Macht praktisch das selbe was dein Pascal programm mit mehr als 100 zeilen macht, in knapp unter 30 und muss es nicht kompiliert werden

PS: du hattest wohl noch nie ein Projekt was aus mehreren Lazarus projekten bestanden hat oder?

Code: Alles auswählen

else if FileList.Count > 1 then
begin
  ErrorMsg := 'Es wurden mehrere .lpi-Dateien gefunden. (' +
  FileList.Count.ToString() + ')';

Ich hab ne ganze reihe an projekten, bei denen das script also nicht funktionieren würde

PPS: Noch ein paar tipps

Code: Alles auswählen

  // Fehlerbehandlung
  if ErrorMsg <> '' then begin
    ShowException(Exception.Create(ErrorMsg));
    Terminate;
    Exit;
  end;

Warum erstellst du erst eine error message, um die dann auszulesen um sie dann in eine Execption zu schreiben, welche du dann ausgeben lassen kannst? Mach doch direkt eine exception:

Code: Alles auswählen

  try
    // falsche Anzahl von Parameter
    if ParamCount <> 1 then
    begin
      raise EParameterException.Create('Invalid parameter Count');
    end;
    // ungültiger Pfad
    if not DirectoryExists(ParamStr(1)) then
    begin
      raise EParameterException.Create('Invalid parameter Directory');
    end;
 
    // Verzeichnis nach .lpi-Datei scannen
    try
      FileList := FindAllFiles(ParamStr(1), '*.lpi', false);
      // keine .lpi-Datei gefunden
      if FileList.Count = 0 then
      begin
        raise EParameterException.Create('Directory does not contain lpi');
      end
      // mehrere .lpi-Dateien gefunden
      else if FileList.Count > 1 then
      begin
        raise EParameterException.Create('Directory contains multiple lpi');
      end
      // Dateiname übernehmen
      else begin
        lpiFileName := FileList[0];
      end;
    finally
      FileList.Free;
    end;
  Except
    on E: EParameterException do
    begin
      ShowException(E);
      Terminate;
      Exit;
    end;
  end;

Ich weiß zwar nicht genau wie der FPC Exceptions implementiert, wenn der aber x86 exceptions verwendet, sind exceptions wahrscheinlich sogar schneller als dein Code

Außerdem

Code: Alles auswählen

WriteLn(verFile,
    cfg.GetValue('ProjectOptions/VersionInfo/MajorVersionNr/Value', '0') +
    '.' + cfg.GetValue('ProjectOptions/VersionInfo/MinorVersionNr/Value', '0') +
    '.' + cfg.GetValue('ProjectOptions/VersionInfo/RevisionNr/Value', '0') +
    '.' + cfg.GetValue('ProjectOptions/VersionInfo/BuildNr/Value', '0'));

Writeln kann per komma beliebig viele argumente entgegen nehmen. Das hat den vorteil das nicht zu erst ein String zusammengebaut werden muss, der dann in die datei geschrieben wird, sondern einfach jedes argument nach einander reingeschrieben wird.

PPPS: warum benutzt du eine TCustomApplication wenn du absolut keine der Features der Klasse benutzt? Du könntest dir locker 50 Zeilen sparen. So würde ich es dementsprechend machen:

Code: Alles auswählen

program LazarusBuildExtractor;
 
{$mode objfpc}{$H+}
 
uses
  Classes,
  SysUtils,
  FileUtil,
  xmlconf;
 
type
  EParameterException = class(Exception);
 
begin
  try
    // falsche Anzahl von Parameter
    if ParamCount <> 1 then
    begin
      raise EParameterException.Create('Invalid parameter Count');
    end;
    // ungültiger Pfad
    if not DirectoryExists(ParamStr(1)) then
    begin
      raise EParameterException.Create('Invalid parameter Directory');
    end;
 
    // Verzeichnis nach .lpi-Datei scannen
    try
      FileList := FindAllFiles(ParamStr(1), '*.lpi', False);
      // keine .lpi-Datei gefunden
      if FileList.Count = 0 then
      begin
        raise EParameterException.Create('Directory does not contain lpi');
      end
      // mehrere .lpi-Dateien gefunden
      else if FileList.Count > 1 then
      begin
        raise EParameterException.Create('Directory contains multiple lpi');
      end
      // Dateiname übernehmen
      else
      begin
        lpiFileName := FileList[0];
      end;
    finally
      FileList.Free;
    end;
  except
    on E: EParameterException do
    begin
      WriteLn('Usage: ', ParamStr(0), ' target');
      WriteLn('target: directory containing the .lpr file');
      Exit;
    end;
  end;
 
  // Versionsdatei öffnen
  AssignFile(verFile, ExtractFileDir(lpiFileName) + PathDelim + 'version.txt');
    try
    Rewrite(verFile);
 
    // Konfiguration einlesen und in Datei speichern
    cfg := TXMLConfig.Create(nil);
    cfg.Filename := lpiFileName;
    WriteLn(verFile,
      cfg.GetValue('ProjectOptions/VersionInfo/MajorVersionNr/Value', '0'),
      '.', cfg.GetValue('ProjectOptions/VersionInfo/MinorVersionNr/Value', '0'),
      '.' + cfg.GetValue('ProjectOptions/VersionInfo/RevisionNr/Value', '0'),
      '.', cfg.GetValue('ProjectOptions/VersionInfo/BuildNr/Value', '0'));
  finally   
    cfg.Free;
 
    // Versionsdatei schließen
    Close(verFile);
  end;
end

Immernoch doppelt so lang wie das python script, aber nur halb so lang wie dein Code

Ich934
Lazarusforum e. V.
Beiträge: 317
Registriert: So 5. Mai 2019, 16:52
OS, Lazarus, FPC: ArchLinux und Windows mit FPCUPdeluxe (L: 2.0.X, FPC 3.2.0)
CPU-Target: x86_64, i386
Wohnort: Bayreuth

Re: Versionsinformation beim kompilieren in Datei speichern

Beitrag von Ich934 »

Warf hat geschrieben:So nur mal am rande, Pascal für so ein programm ist kompletter overkill, für so kleine sachen sind Scriptsprachen viel angenehmer, schau dir mal dieses python script an:


Muss ich auf Windows erst zusätzlich etwas installieren, das pflegen etc. Zusätzlicher Aufwand... Ausserdem hätte ich mich dann in Python einarbeiten müssen. Noch mehr Aufwand

Warf hat geschrieben:PS: du hattest wohl noch nie ein Projekt was aus mehreren Lazarus projekten bestanden hat oder?


Nein. Hier auch nicht nötig.

Warf hat geschrieben:Immernoch doppelt so lang wie das python script, aber nur halb so lang wie dein Code


Wie geschrieben Quick&Dirty aus den Standard Assistenten. Aber es ist GPL und in Github. Check es aus, schreib es um und mach nen Commit drauf und die Welt ist besser. :lol:
Tipp für PostgreSQL: www.pg-forum.de

Warf
Beiträge: 1909
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Versionsinformation beim kompilieren in Datei speichern

Beitrag von Warf »

Ich934 hat geschrieben:Muss ich auf Windows erst zusätzlich etwas installieren, das pflegen etc. Zusätzlicher Aufwand... Ausserdem hätte ich mich dann in Python einarbeiten müssen. Noch mehr Aufwand

So kleiner scripts braucht man immer mal wieder, darum lohnt es sich mMn sowas wie python zu lernen. Ist echt nicht schwer, und wenn ich mir für jedes kleine script ein pascal programm schreiben würde, würde ich mich dumm und dämlich programmieren.
Auch noch eine Sache die ich persönlich zum Programmieren sehr angenehm finde ist es ein MSYS oder Cygwin zu installieren, das stellt dir unter Windows die typischen Linux tools inklusive paketmanager und eine schöne Konsole zur verfügung. Du hast kein Python, einfach "pacman -S python3" eintippen und fertig


Warf hat geschrieben:Nein. Hier auch nicht nötig.

Hab es halt runtergeladen und ausgetestet, und direkt beim ersten projekt von mir gings in die Hose :mrgreen:
Ich hab halt öfter die Projektstruktur das ich mehrere Projekte habe, und alle Projektdateien (lpi, lpr, lps) in einem Order Projects aufbewahre

Warf hat geschrieben:Wie geschrieben Quick&Dirty aus den Standard Assistenten. Aber es ist GPL und in Github. Check es aus, schreib es um und mach nen Commit drauf und die Welt ist besser. :lol:

Ja schon klar, sind nur so ein paar sachen die mir aufgefallen sind als ich drüber geschaut habe, dachte mir wenn ich eh schon Lazarus offen hab kann ich auch noch ein paar kleinigkeiten fixen :wink:

Ich934
Lazarusforum e. V.
Beiträge: 317
Registriert: So 5. Mai 2019, 16:52
OS, Lazarus, FPC: ArchLinux und Windows mit FPCUPdeluxe (L: 2.0.X, FPC 3.2.0)
CPU-Target: x86_64, i386
Wohnort: Bayreuth

Re: Versionsinformation beim kompilieren in Datei speichern

Beitrag von Ich934 »

Naja, wie man unter Linux ein Paket installiert ist mir schon klar. ;-) Übrigens ist hier auch Python vorhanden. Aber auf Windows müsste ich das extra nachinstallieren.

Davon abgesehen würde ich dann aber eher PHP nehmem weil ich da einfach das Know-How hab. Aber auch das hab ich nicht unter Windows.

Es geht nicht darum, das man hier Hilfsprogramme hat die schnell sind, sondern die einen auch dann überall zur Verfügung stehen ohne dass man erst Voraussetzungen schaffen muss. Aber wir werden off topic...

Deinen Code habe ich jetzt überigens in Git überführt wenn du das nicht machen willst...
Tipp für PostgreSQL: www.pg-forum.de

Warf
Beiträge: 1909
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Versionsinformation beim kompilieren in Datei speichern

Beitrag von Warf »

Ich934 hat geschrieben:Naja, wie man unter Linux ein Paket installiert ist mir schon klar. ;-) Übrigens ist hier auch Python vorhanden. Aber auf Windows müsste ich das extra nachinstallieren.


Ging darum das du mit Msys für windows die ganzen linux tools + paketmanager auch für Windows bekommst. Das heisst, einmal msys installieren, und dann kannst du die meisten Entwickler tools (C-Compiler, Python, vim, git, etc.) einfach über den mitgelieferten Paketmanager installieren und musst nicht immer zu erst die website besuchen, dann den installer downloaden, und dann evenutell die sachen noch zu PATH hinzufügen.

MSYS ist mittlerweile das erste was ich auf nem neu installierten windows installiere, da es programmieren einfach viel einfacher macht

Antworten