Bibliotheken "vollständig" einbinden

Antworten
cgaertner
Beiträge: 27
Registriert: Sa 10. Okt 2020, 21:54

Bibliotheken "vollständig" einbinden

Beitrag von cgaertner »

Liebe Alle,

ich habe eine Frage, deren Antwort ich schon erfolglos seit Wochen suche. Vermutlich verwende ich die falschen Suchbegriffe, denn sie erscheint mir so simpel, daß ich mir nicht vorstellen kann, daß es da keine Antwort im Netz gibt.

Also: Ich programmiere seit Jahren mit Lazarus/Freepascal unter Windows und habe nun ein Softwarepaket, das ich auch unter Linux laufen lassen möchte. Unter Windows erstelle ich eine einzige exe-Datei, die unter Windows XP, 7, 8, 10 egal ob 32 Bit oder 64 Bit läuft. Die eine externe Bibliothek, die mein Programm braucht (eine Treiber-DLL für ein USB-Meßgerät), liegt im Programmverzeichnis.

Ich habe nun meinen Programmcode mit Compiler-Direktiven so angepaßt [z.B. stdcall <-> cdecl], daß das Programm unter Linux (Debian 10, 32 Bit) erfolgreich läuft. Nun möchte ich das Programm natürlich weitergeben, aber auf einem zweiten Testsystem unter VMware (Ubuntu 20, 64 Bit) läuft es nicht. Wenn ich mit ldd nachschaue, habe ich haufenweise Abhängigkeiten zu "/lib/i386-linux-gnu/*" und vermutlich deshalb läuft mein Programm auf dem anderen Linux nicht. Die Fehlermeldung ist "error while loading shared libraries: libgdk-x11-2.0.so.0: cannot open shared object file: No such file or directory".

Frage 1: Gibt es Compilereinstellungen, um unter Linux die ganzen Libraries in das Programmpaket fix zu intergrieren - so wie bei Windows (mir ist natürlich bewußt, daß das Programm auch unter Windows externe Abhängigkeiten hat, aber die sind für alle Windows-Versionen seit XP kompatibel)?

Frage 2: Die oben erwähnt Fehlermeldung könnte daran liegen, daß im 32 Bit Entwicklungslinux die Library unter ...
/lib/i386-linux-gnu/libgdk-x11-2.0.so.0
... liegt, während am 64 Bit Zielsystem der Pfad ...
/lib/x86_64-linux-gnu/libgdk-x11-2.0.so.0
... ist. Aber nachdem mein Programm den Pfad zur Library nicht fix kodiert hat und die Library ja gleich heißt: warum findet das System die Library nicht?

Frage 3: Wie mache ich ein Programm unter Linux mit Lazarus/Freepacal portabel? Ich habe die Seite "Deploying Your Application" mehrfach gelesen, aber die hilft mir auch nicht weiter. Auch AppImage klingt nett, da finde ich aber für die Lazarus/Freepascal-Ecke auch kaum Informationen im Netz ...

Danke und viele Grüße aus Wien,
Christian

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

Re: Bibliotheken "vollständig" einbinden

Beitrag von Warf »

Zu Frage 1: Nein, unter windows benutzt Lazarus für sachen wie GUIs die Windows API, also die Systembibliothek die direkt von Windows mitgeliefert wird. Linux is im gegensatz zu Windows kein inherent grafisches System, also gibt es keine system bibliothek für GUIs, sodnern GUIs unter Linux benutzen einen Display Server, welcher von Lazarus entweder direkt (CustomDrawn) oder über eine weitere Bibliothek (QT, GTK) angesprochen. Diese bibliotheken müssen auf dem Zielsystem vorhanden sein.
Das gute ist, du musst die nicht selbst mittliefern. Die meisten Linux distros kommen bereits schon schon mit X11 installiert und benutzen meist auch eine GUI lib. Wenn Gnome3 als Desktop verwendet wird, ist meist GTK installiert, bei KDE ists QT5.
Da unter Linux die shared libraries allerdings (im gegensatz zu windows) tatsächlich geshared sind, reicht ein QT programm aus das QT installiert ist und ein GTK programm das GTK installiert ist. Z.B. Wenn du auf Ubuntu mit GNOME 3 KDIFF installiert hast, sollte auch QT5 installiert sein (da KDIFF QT benutzt)

Frage 2: du scheinst das Programm für 32 Bit zu kompilieren, hast aber ein 64 bit. Während du zwar 32 bit programme auf 64 bit Linux verwenden kannst, sind natürlich alle Anwendungen die (vor) installiert sind auch 64 bit und damit auch alle Bibliotheken. Je nach Distro ist es sogar gar nicht so einfach eine 32 Bit version einer Bibliothek zu finden und zu installieren (z.b. Arch). Mein Tipp, kompilier doch einfach für 64 Bit wenn du es auf 64 bit systemen laufen lassen willst.

Frage 3: Programme unter Linux sind wie unter Windows einfach executables, der wichtige unterschied ist aber das der Anwendungspfad nicht zum Suchpfad für Bibliotheken gehört. Du kannst also nicht einfach Bibliotheken mit deiner anwendung mitliefern (das ist so gewollt um die DLL Hell von Windows zu vermeiden). Wenn du dein Programm ausliefern willst soll der Nutzer also alle dependencies mit seinem Favorisierten Packetmanager installieren.
Für DPKG basierte Systeme (z.B. Debian, Ubuntu, etc.) kannst du z.b. einfach eine .deb datei erzeugen die praktisch all diese informationen enthält, die der Nutzer benutzen kann um alle dependencies zu installieren und dann das Programm selbst installiert. Das Problem ist das es im Zoo der Distributionen und Paketmanager keine einheitliche Lösung gibt. Außerdem kann es so zu konflikten kommen, App 1 benutzt ne Lib in version A und App 2 die Lib in Version B und dann hast du den Salat.
Daher gibt es mittlerweile der Containerization die Idee dabei ist die Idee das der Container also alle daten mitbringt die das system zum laufen braucht. Im allgemeinen ist die struktur eines Containers so, dass die dateien strukturiert wären als wäre es ein Leeres Linux System das auf den Root des Containers ge chroot'ed wurde.
Um mal bei Appimage zu bleiben, Siehe: https://docs.appimage.org/packaging-gui ... ref-manual
Sowie in Linux die Libs in /usr/lib liegen muss im AppImage ordner die Libraries für das image in APPIMAGEORDNER/usr/lib abgelegt werden. Binaries die unter Linux in /usr/bin liegen würde müssen in APPIMAGEORDNER/usr/bin abgelegt werden und so weiter.
Wenn du alles bereitgestellt hast, kannst du daraus dann ein AppImage bauen.

Alternative zu containern, Bibliotheken wie GTK und QT kannst du meist annehemen das sie da sind. Alle exotischeren bibliotheken kannst du mitliefern in einem eigenen ordner und den dann über LD_LIBRARY_PATH zum suchpfad hinzufügen. Dafür kannst du einfach einen ordner erstellen:

Code: Alles auswählen

Order/MyApp # die executable die der fpc dir kompiliert
Ordner/libs/... # hier die libraries die du mitliefern willst
Ordner/MyApp.run # bash file
Wobei der inhalt von MyApp.run dann irgendwie sowas ist:

Code: Alles auswählen

#!/bin/bash
APPDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${APPDIR}/libs
${APPDIR}/MyApp $@
Dieses script setzt dann den LD_LIBRARY_PATH sodass die bibliotheken aus libs gefunden werden. Dieses script musst du dann nur noch mit "chmod +x MyApp.run" ausführbar machen, und der benutzer kann dann ganz einfach über dieses script die anwendung starten

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Bibliotheken "vollständig" einbinden

Beitrag von Winni »

Hi!

Oder die kurze Version:

Libraries nach /usr/lib/locale kopieren.

Wundern dass nix funktioniert.
Was regelmässig vergessen wir, ist dem System die neue Library bekannt zu machen.

An der bash:

Code: Alles auswählen

sudo ldconfig


Fertig.

Winni

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

Re: Bibliotheken "vollständig" einbinden

Beitrag von Warf »

Das braucht halt admin rechte, und man sollte immer zu erst schauen ob es die lib nicht im paketmanager gibt. Eine lib nach /lib zu kopieren ist vergleichbar damit eine DLL nach System32 zu kopieren. Das sollte man nur machen wenn der User ganz genau weiß was er macht!

Eine bessere option wäre es hier z.b. einen neuen ordner (z.b. /opt/lib) anzulegen und den in die ldconfig zu legen. somit pfuscht man nicht ausversehen dem paketmanager dazwischen, da das paketmanager verzeichnis (/usr/lib) vorrang hat

PS: du meinst wahrscheinlich /usr/local/lib und nicht /usr/lib/locale denn locale ist der name für lokalisierung und somit hat da nix anderes außer lokalisierungs kram drin zu tun

cgaertner
Beiträge: 27
Registriert: Sa 10. Okt 2020, 21:54

Re: Bibliotheken "vollständig" einbinden

Beitrag von cgaertner »

Guten Morgen,

und vielen Dank für die Antworten - ich bin völlig überrascht, nach ein paar Stunden bereits so detaillierte Antworten zu bekommen!

ad Antwort zu Frage 1) Ich sehe jetzt etwas klarer, was das grafische System von Linux anbelangt. Nachdem Lazarus ja GTK2 verwendet, habe ich z.B. bei einem Benutzer, der Gnome verwendet, in der Regel damit bereits die Bibliotheken auf dem System. Wenn der Benutzer allerdings KDE verwendet, wird QT vorhanden sein und der Benutzer müßte dann das ganze GTK-System (nach-)installieren. Oder? In Richtung CustomDraw von Lazarus habe ich auch schon ein wenig recherchiert und bin da auf fpGui gestoßen, das habe ich aber ehrlich gesagt nur mit einer kleinen Test-Applikation zum Laufen gebracht - bei meinem Programm hätte ich wohl jedes Formular neu kodieren müssen. Könnte ich mit Lazarus eigentlich grafisch Formulare mit z.B. fpGui designen?

ad Antwort zu Frage 2) Ja, ich kompiliere für 32 Bit, da ich die Library derzeit nur in einer 32 Bit Version habe - und ich gedacht habe, wie unter Windows läuft 32 Bit auch auf Systemen mit 64 Bit und daher bin ich mit 32 Bit auf der sicheren Seite für alle Benutzer. Wenn ich Dich richtig verstehe, ist es unter Linux sehr empfehlenswert, getrennte Versionen für 32 Bit und 64 Bit bereitzustellen und nicht wie unter Windows davon auszugehen "32 Bit läuft eh überall"?

ad Antwort zu Frage 3) Deine Antwort fasse ich so auf, daß die Erstellung einer deb-Datei nicht uneingeschränkt empfehlenswert ist (Stichwort Bibliotheken in unterschiedlichen Versionen und unterschiedliche Paketmanager). Wenn ich AppImage verwenden möchte (die verlinkte Seite habe ich bereits ein paar Mal gelesen und kannte mich nicht wirklich aus, aber wenn Du sagst, das ist "the way to go", dann werde ich mich darauf konzentrieren): würdest Du dann ins AppImage-Image die GTK2-Libraries inkludieren? Eigentlich doch schon, da man sich ja nicht darauf verlassen kann, daß sie auf dem Zielsystem vorhanden sind (siehe Antwort zu Frage 1). Ich nehme an, die benötigten Libraries meines Programmes kriege ich mit ldd heraus? Danke auch für den Trick mit LD_LIBRARY_PATH, das werde ich für "meine" Library verwenden.

Viele Grüße,
Christian

Benutzeravatar
theo
Beiträge: 10468
Registriert: Mo 11. Sep 2006, 19:01

Re: Bibliotheken "vollständig" einbinden

Beitrag von theo »

Nur ein paar Aspekte;

Zu 1: Lazarus verwendet nur in der Standardeinstellung GTK2. Man kann aber problemlos auch Qt/Qt5 (wie KDE) verwenden.
Zu 2: 32bit ist auf Linux passé. Das aktuelle Kubuntu wird z.B. nicht mehr als 32bit Version bereitgestellt.
Man kann zwar durch Nachinstallieren von ia32-libs noch 32bit Anwendungen auf 64bit Linux laufen lassen, das ist aber wieder ein extra Schritt und benötigt extra Speicherplatz.
Zu 3: Gimp und Firefox z.B. benutzen GTKx auch auf KDE. Man kann also davon ausgehen, dass das kein Problem darstellt. Eher, dass GTK2 auf einigen Distros bald ausgemustert wird zugunsten von GTK3, was wiederum auf Lazarus nicht so fit ist.

PascalDragon
Beiträge: 825
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Bibliotheken "vollständig" einbinden

Beitrag von PascalDragon »

cgaertner hat geschrieben:
So 11. Okt 2020, 09:55
ad Antwort zu Frage 1) Ich sehe jetzt etwas klarer, was das grafische System von Linux anbelangt. Nachdem Lazarus ja GTK2 verwendet, habe ich z.B. bei einem Benutzer, der Gnome verwendet, in der Regel damit bereits die Bibliotheken auf dem System. Wenn der Benutzer allerdings KDE verwendet, wird QT vorhanden sein und der Benutzer müßte dann das ganze GTK-System (nach-)installieren. Oder? In Richtung CustomDraw von Lazarus habe ich auch schon ein wenig recherchiert und bin da auf fpGui gestoßen, das habe ich aber ehrlich gesagt nur mit einer kleinen Test-Applikation zum Laufen gebracht - bei meinem Programm hätte ich wohl jedes Formular neu kodieren müssen. Könnte ich mit Lazarus eigentlich grafisch Formulare mit z.B. fpGui designen?
Wie theo bereits angedeutet hat werden viele Nutzer wahrscheinlich beides bereits installiert haben. Theoretisch könntest du aber Dank Lazarus dein Paket sowohl in einer Qt als auch einer Gtk Variante bereitstellen.

Und wegen fpGUI: Lazarus unterstützt prinzipiell auch auf fpGUI aufzusetzen (wie Qt, Gtk, etc.), das ist aber weit weniger getestet und ich glaub aktuell funktioniert es mit FPC 3.2.0 auch nicht.
cgaertner hat geschrieben:
So 11. Okt 2020, 09:55
ad Antwort zu Frage 2) Ja, ich kompiliere für 32 Bit, da ich die Library derzeit nur in einer 32 Bit Version habe - und ich gedacht habe, wie unter Windows läuft 32 Bit auch auf Systemen mit 64 Bit und daher bin ich mit 32 Bit auf der sicheren Seite für alle Benutzer. Wenn ich Dich richtig verstehe, ist es unter Linux sehr empfehlenswert, getrennte Versionen für 32 Bit und 64 Bit bereitzustellen und nicht wie unter Windows davon auszugehen "32 Bit läuft eh überall"?
Da unter Linux eh fast alles aus freien Quellen kommt ist dort die Umstellung auf rein 64-bit viel schneller gewesen. Windows wird weiterhin das Windows-on-Windows64 mitschleppen, aber für Linux gehen eigentlich alle großen Distros Richtung rein 64-bit. macOS ist auch mittlerweile rein 64-bit.

PS: Es wäre nett gewesen, wenn du erwähnt hättest, dass du ein Cross-Posting zwischen hier und dem internationalem Forum machst.
FPC Compiler Entwickler

cgaertner
Beiträge: 27
Registriert: Sa 10. Okt 2020, 21:54

Re: Bibliotheken "vollständig" einbinden

Beitrag von cgaertner »

Liebe Alle,

danke für die Antworten. Ich sehe schon, vieles, was ich aus der Windows-Welt einfach so wußte (ohne mehr großartig darüber nachzudenken) muß ich für Linux neu überdenken. Nachdem meine Software für Modelleisenbahner gedacht ist, die als Steuerungscomputer vielfach ältere Hardware weiterverwenden, befürchte ich, daß ich mit einer reinen 64 Bit Variante hier viele Leute ausschließen würde. Damit wird meine To-Do-Liste schon um einiges länger: 32 Bit Version, 64 Bit Version (falls ich die Bibliothek des Herstellers auf 64 Bit kompilieren kann), dann vielleicht auch noch je eine Version für GTK und QT ... hmm, das wird ja ein ganz ordentliches Projekt dann!
PS: Es wäre nett gewesen, wenn du erwähnt hättest, dass du ein Cross-Posting zwischen hier und dem internationalem Forum machst.
Du hast völlig recht, das hätte ich erwähnen sollen. Ich habe nicht dran gedacht, entschuldigt bitte.

LG Christian

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
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: Bibliotheken "vollständig" einbinden

Beitrag von af0815 »

Die Begrenzung sind einmal die externalen Bibliotheken. Wenn man etwas Übung hat, so kann ein Quellcode auf sehr vielen Systemen laufen.

Meiner Erfahrung nach, können Benutzer sehr wohl die benötigten Pakete nachinstallieren. Es muss halt klar sein, was man installieren muss und welche Befehle einzugeben sind.

Da braucht man nicht unnötig Zeit verschwenden um Appimage etc. anzufertigen. Wenn sich die Notwendigkeit ergibt, dann später, wenn klar ist für welche Plattformen.

Gut designte Projekte lassen sich ohne großen Aufwand auch Cross compilieren. Ich entwickle meist auf Win32 und teste das großteils hier. Dann erst kompiliere ich für Linux-x64 und Linux-Arm. Kostet nur 2 Kompilerläufe mehr, also nicht einmal ein paar Minuten.

Für spezielle Hardware, die ich auf einer Plattform nicht habe, versuche ich eine Emulation zu erstellen. Ist zwar ein erheblicher Aufwand, hat sich aber bisher immer bezahlt gemacht. Dadurch kann ich noch besser cross Entwickeln. Zusätzlich rrgeben sich durch die Emulation viel klarer Schnittstellen, da ich immer nur gegen die Schnittstelle programmieren kann und damit der Code automatisch entkoppelt wird. Lässt sich auch sehr gut Testen.

Lass dich einmal nicht von der eigentlichen Idee abbringen und versuche von Null weg immer auf allen Plattformen zu testen. Dann bekommst du schnell heraus was geht und was nicht. Mit, so schnell noch eine Komponente aus dem Netz ist dann nichts. Zuerst schauen ob die überall funktioniert.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Antworten