Bibliothek statisch linken??

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

Bibliothek statisch linken??

Beitrag von cgaertner »

Liebe Alle,

dank eurer Antworten auf meine andere Frage habe ich mittlerweile einiges über shared libraries gelernt und und warum ich diese nicht direkt in mein Programm einbinden kann/soll/werde (meine andere Frage bezog sich auf die Linux Basis- und GTK2-Libraries).

Mein Projekt hat aber noch eine einzelne zusätzliche spezielle Library, die es benötigt: das ist die "libiowkit" von Code Mercenaries. Diese Bibliothek liegt im Quelltext (C) vor und ich möchte sie gerne in mein Freepascal-Programm einbinden, um dem Verwender meines Programmes zu ersparen, die Bibliothek selbst kompilieren und installieren zu müssen. Die Bibliothek ist seit längerem unverändert, also ist das Risiko von verpaßten Updates auch eher gering.

Ich kann bzw. muß diese Bibliothek mit make install kompilieren und dann erhalte ich in /usr/lib/ folgende Dateien:
libiowkit.a
libiowkit.la
libiowkit.so.1.0.5
libiowkit.so => libiowkit.so.1.0.5
libiowkit.so.1 => libiowkit.so.1.0.5

Im Quellverzeichnis der Bibliothek entstehen zusätzlich noch "iowkit.lo" und "iowkit.o". Mein Programm bzw. eine abgespeckte Testversion davon funktioniert mit der dynamisch gelinkten Bibliothek problemlos, doch beim statischen Linken sehe ich mich leider einfach nicht mehr raus. :-(

Folgende Optionen bzw. Einstellungsmöglichkeiten überfordern mich:

1) {$LINKLIB ****irgendwas****}
2) {$L ****irgendwas****}
3) Funktionsdeklaration, z.B. function IowKitVersion: PChar; stdcall; external ****irgendwas**** name 'IowKitVersion';

Ich habe viel recherchiert, unzählige Kombinationen von "****irgendwas****" ausprobiert (die library, das object file, das library a file), aber entweder bekomme ich nach dem Kompilieren mit ldd immer noch einen Verweis auf die shared library oder ich kann gar nicht kompilieren, weil der Pfad zu einer Datei (eben eines der "****irgendwas****") ungültig ist bzw. die Datei nicht gefunden werden kann. Vermutlich müßte ich auch noch irgendwelche Pfade im Kompiler setzen.

Ich bitte euch um eure Hilfe und/oder Hinweise, was ich falsch mache bzw. nicht verstanden habe.

Danke und viele Grüße aus Wien,
Christian

PascalDragon
Beiträge: 73
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: Bibliothek statisch linken??

Beitrag von PascalDragon »

Mit $LinkLib linkst du eine statische Bibliothek (in deinem Fall wäre das libiowkit.a), mit $L (oder $Link) linkst du eine Objektdatei (in deinem Fall wäre das iowkit.o). Du musst auf jeden Fall eine der beiden Varianten verwenden (okay, du kannst es auch auf der Kommandozeile des Compilers angeben, aber es in der Unit zu haben ist sinnvoller).

Deine Funktionen musst du dann wie folgt deklarieren:

Code: Alles auswählen

function IowKitVersion: PChar; cdecl; external;
Beachte dabei die folgenden Punkte:
  • du darfst keinen Bibliotheksnamen angeben, das ist sonst dynamisches Linken mit der *.so-Datei
  • du musst die richtige Calling Convention wählen, für Linux ist das meist cdecl, da solltest du aber nochmal in deinen C Quellen nachschauen
  • in den meisten Fällen musst du keinen name-Clause angeben, da der Compiler die Funktion richtig mangled, ansonsten musst du schauen, dass du tatsächlich den richtigen Funktionsnamen in der statischen Bibliothek/in der Objectdatei verwendest und nicht den im Quelltext (unter Linux haben C Funktionen meist einen Unterstrich als Präfix)
FPC Compiler Entwickler

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

Re: Bibliothek statisch linken??

Beitrag von cgaertner »

Großartig, vielen Dank!! Sowohl für die schnelle Antwort als auch natürlich dafür, daß mein Programm jetzt funktioniert!

Mit dem cdcel statt stdcall hast Du selbstverständlich recht, das brauche ich für die Windows-Version meines Programmes und das habe ich beim Kopieren übersehen.

Es funktionieren - so wie Du gesagt hast - beide Varianten, entweder mit dem Verweis auf die o-Datei oder die a-Datei. Die entsprechende Datei muß in /usr/lib/ (die a-Datei) sein oder im Quellverzeichnis meines Programmes (gilt für die a-Datei oder die o-Datei).

Da die Library iowkit ihrerseits von von libc und libpthread abhängt, mußte ich nach dem $LINK bzw. $LINKLIB noch diese beiden Zeilen einfügen:
{$LINKLIB libpthread}
{$LINKLIB libc}

Obiges ist für die Profis sicherlich ohnehin klar, aber ich schreibe es zwecks Vollständigkeit hier rein, falls irgendwer mal auf diesen Thread stößt.

Danke nochmals!

Viele Grüße,
Christian

PascalDragon
Beiträge: 73
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: Bibliothek statisch linken??

Beitrag von PascalDragon »

cgaertner hat geschrieben:
Sa 17. Okt 2020, 14:13
Großartig, vielen Dank!! Sowohl für die schnelle Antwort als auch natürlich dafür, daß mein Programm jetzt funktioniert!
Freut mich zu lesen. :)
cgaertner hat geschrieben:
Sa 17. Okt 2020, 14:13
Es funktionieren - so wie Du gesagt hast - beide Varianten, entweder mit dem Verweis auf die o-Datei oder die a-Datei. Die entsprechende Datei muß in /usr/lib/ (die a-Datei) sein oder im Quellverzeichnis meines Programmes (gilt für die a-Datei oder die o-Datei).
Du kannst auch mit -FlXXX einen Pfad für die Suche nach statischen Bibliotheken und mit -FoXXX einen Pfad für die Suche nach Objektdateien hinzufügen.
cgaertner hat geschrieben:
Sa 17. Okt 2020, 14:13
Da die Library iowkit ihrerseits von von libc und libpthread abhängt, mußte ich nach dem $LINK bzw. $LINKLIB noch diese beiden Zeilen einfügen:
{$LINKLIB libpthread}
{$LINKLIB libc}
Korrekter ist

Code: Alles auswählen

{$LinkLib pthread}
{$LinkLib c}
FPC fügt den lib-Präfix automatisch hinzu.

Alternativ könntest du in deinem Hauptprogramm die cthreads Unit hinzufügen, diese sorgt auch dafür, dass pthread und c mit reingelinkt werden und sorgt zusätzlich auch dafür, dass die Threading Funktionalität der RTL vorhanden ist.
FPC Compiler Entwickler

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

Re: Bibliothek statisch linken??

Beitrag von cgaertner »

PascalDragon hat geschrieben:
Sa 17. Okt 2020, 15:08
Alternativ könntest du in deinem Hauptprogramm die cthreads Unit hinzufügen, diese sorgt auch dafür, dass pthread und c mit reingelinkt werden und sorgt zusätzlich auch dafür, dass die Threading Funktionalität der RTL vorhanden ist.
Das habe ich jetzt auch ausprobiert, funktioniert erwartungsgemäß ebenfalls. Wenn ich die beiden Bibliotheken wie ursprünglich mit $LINKLIB einbinde, habe ich als Abhängigkeiten libpthread und libc; wenn ich mit "uses cthreads" arbeite, habe ich als Abhängigkeiten libdl und libc. Hat die eine oder andere Variante unter diesem Gesichtspunkt Vorteile?

Noch eine Zusatzfrage: unter Windows funktioniert das doch im Prinzip genauso, nur daß ich dann halt keine *.a-Datei bzw. *.o-Datei habe, sondern eine *.lib-Datei. Brauche ich sonst noch eine Datei? Der Hersteller liefert zwar eine *.lib-Datei in seinem SDK mit, allerdings scheint mir die etwas seltsam zu sein. Als Magic Bytes hat sie nämlich "!<ARCH>", was laut Wikipedia eigentlich ein deb-Paket ist?!?! Ich habe mal im Herstellerforum angefragt - hoffentlich bekomme ich dort eine Antwort. Welches Format müßte denn die *.lib-Datei haben, damit Freepascal sie versteht? Es gibt ja COFF und noch eines (den Namen finde ich grade nicht mehr) ...

Danke und viele Grüße,
Christian

PascalDragon
Beiträge: 73
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: Bibliothek statisch linken??

Beitrag von PascalDragon »

cgaertner hat geschrieben:
Sa 17. Okt 2020, 20:03
PascalDragon hat geschrieben:
Sa 17. Okt 2020, 15:08
Alternativ könntest du in deinem Hauptprogramm die cthreads Unit hinzufügen, diese sorgt auch dafür, dass pthread und c mit reingelinkt werden und sorgt zusätzlich auch dafür, dass die Threading Funktionalität der RTL vorhanden ist.
Das habe ich jetzt auch ausprobiert, funktioniert erwartungsgemäß ebenfalls. Wenn ich die beiden Bibliotheken wie ursprünglich mit $LINKLIB einbinde, habe ich als Abhängigkeiten libpthread und libc; wenn ich mit "uses cthreads" arbeite, habe ich als Abhängigkeiten libdl und libc. Hat die eine oder andere Variante unter diesem Gesichtspunkt Vorteile?
Nicht wirklich, da diese drei Bibliotheken alle recht eng miteinander verbandelt sind. Hauptvorteil der Variante mit der cthreads Unit ist dass die RTL von Free Pascal dann auch threadaware ist.
cgaertner hat geschrieben:
Sa 17. Okt 2020, 20:03
Noch eine Zusatzfrage: unter Windows funktioniert das doch im Prinzip genauso, nur daß ich dann halt keine *.a-Datei bzw. *.o-Datei habe, sondern eine *.lib-Datei. Brauche ich sonst noch eine Datei? Der Hersteller liefert zwar eine *.lib-Datei in seinem SDK mit, allerdings scheint mir die etwas seltsam zu sein. Als Magic Bytes hat sie nämlich "!<ARCH>", was laut Wikipedia eigentlich ein deb-Paket ist?!?! Ich habe mal im Herstellerforum angefragt - hoffentlich bekomme ich dort eine Antwort. Welches Format müßte denn die *.lib-Datei haben, damit Freepascal sie versteht? Es gibt ja COFF und noch eines (den Namen finde ich grade nicht mehr) ...
Ich nehme mal an, dass die statischen Bibliotheken für die Windows Variante mit MSVC erstellt wurden. Die statischen Bibliotheken sind dabei leicht unterschiedlich zu denen, die GCC/MinGW erstellt. Der interne Linker von FPC unterstützt aktuell nur die von GCC/MinGW erstellten. Du müsstest also den externen Linker mittels -Xe verwenden (GNU ld unterstützt nämlich glaube ich das MSVC auch, zumindest zum Einlesen), wobei dies zu langsamerem Linken führt und eventuell auch das SmartLinken im Zusammenhang mit Debug Informationen beeinflusst (es gibt 'nen Grund warum wir für Windows 'nen internen Linker geschrieben haben ;) ).
FPC Compiler Entwickler

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

Re: Bibliothek statisch linken??

Beitrag von cgaertner »

Hallo PascalDragon,

ja - die Bibliothek wurde mit Visual Studio 2017 erstellt. Ich habe es mir mittlerweile installiert und kann mit dem vorhandenen Sourcecode aus dem SDK, das der Hersteller zur Verfügung stellt, auch die dll neu erstellen (und da entstehen dann auch gleich die *.lib-Datei und eine *.exp-Datei mit). Trotzdem ändert das nichts an den Fehlern in Freepascal - was aber auch logisch ist, denn Du sagst ja, MSVC ist das falsche Format für statische Libraries unter Freepascal.

Ich habe dann in Freepascal den externen Linker aktiviert (in der Datei fpc.cfg die Option "-Xe" eingefügt) und damit ändert sich das Fehlerbild signifikant. Hatte ich vorher ein allgemeines "Error: Import library not found for iowkit", so wird es jetzt deutlich ausführlicher. Ich bekomme für jede der 12 eingebundenen Funktionen aus der externen Bibliothek eine Meldung in der Form ...

C:\...\RCL\lib\i386-win32\RCL.o:RCL.lpr:(.text.n__main+0x11): undefined reference to `P$RCL_$$_IOWKITVERSION$$PCHAR'

... und am Ende "Error: Error while linking". Die obige Funktion habe ich mit "function IowKitVersion: PChar; stdcall; external;" eingebunden (so heißt sie laut Hersteller-Dokumentation und so funktioniert sie mit der dynamisch gelinkten Bibliothek auch). Und die ganze Bibliothek habe ich mit "{$LINKLIB iowkit}" (das ist der Name der *.dll-Datei und der *.lib-Datei) angegeben.

Es tut mir leid, daß ich da nicht von alleine weiterkomme - darf ich Dich hier nochmal um Deine Hilfe bitten?

Danke und viele Grüße,
Christian

PS: Eine andere Idee hatte ich auch noch: da ich den Quellcode der Bibliothek ja aus dem SDK habe, wäre es ja auch möglich, die Bibliothek mit Visual Studio 2017 unter Verwendung eines externen Compilers/Linkers (nämlich GCC/MinGW) neu zu erstellen - dann müßte das Format für FreePascal ja passen. Laut Microsoft ist es ganz einfach möglich, einen anderen Compiler/Linker in Visual Studio 2017 einzubinden. Aber es zeigte sich für mich, daß die Auffassung, was "einfach möglich" ist, sehr sehr unterschiedlich sein kann. :-(

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

Re: Bibliothek statisch linken??

Beitrag von af0815 »

Das mit den Problemen beim Einbinden hat auch damit zu tun, das grosse Hersteller dazu neigen, die Software für ihre Kundschaft zu optimieren, das die nicht in Versuchung geführt werden andere Software zu benötigen. :shock:


Aber das zieht sich in den C Bereich genauso, siehe
http://www.mingw.org/wiki/msvc_and_mingw_dlls
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

PascalDragon
Beiträge: 73
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: Bibliothek statisch linken??

Beitrag von PascalDragon »

cgaertner hat geschrieben:
Mo 19. Okt 2020, 00:38
Ich habe dann in Freepascal den externen Linker aktiviert (in der Datei fpc.cfg die Option "-Xe" eingefügt) und damit ändert sich das Fehlerbild signifikant. Hatte ich vorher ein allgemeines "Error: Import library not found for iowkit", so wird es jetzt deutlich ausführlicher. Ich bekomme für jede der 12 eingebundenen Funktionen aus der externen Bibliothek eine Meldung in der Form ...

C:\...\RCL\lib\i386-win32\RCL.o:RCL.lpr:(.text.n__main+0x11): undefined reference to `P$RCL_$$_IOWKITVERSION$$PCHAR'

... und am Ende "Error: Error while linking". Die obige Funktion habe ich mit "function IowKitVersion: PChar; stdcall; external;" eingebunden (so heißt sie laut Hersteller-Dokumentation und so funktioniert sie mit der dynamisch gelinkten Bibliothek auch). Und die ganze Bibliothek habe ich mit "{$LINKLIB iowkit}" (das ist der Name der *.dll-Datei und der *.lib-Datei) angegeben.
Dann nutze bitte doch

Code: Alles auswählen

function IowKitVersion: PChar; stdcall; external name 'IowKitVersion';
Vielleicht ist der Name aber auch _IowKitVersion, da müsstest du dir zum Beispiel mit objdump (ist bei FPC dabei) mal die statische Bibliothek oder die .obj-Dateien anschauen.
cgaertner hat geschrieben:
Mo 19. Okt 2020, 00:38
PS: Eine andere Idee hatte ich auch noch: da ich den Quellcode der Bibliothek ja aus dem SDK habe, wäre es ja auch möglich, die Bibliothek mit Visual Studio 2017 unter Verwendung eines externen Compilers/Linkers (nämlich GCC/MinGW) neu zu erstellen - dann müßte das Format für FreePascal ja passen. Laut Microsoft ist es ganz einfach möglich, einen anderen Compiler/Linker in Visual Studio 2017 einzubinden. Aber es zeigte sich für mich, daß die Auffassung, was "einfach möglich" ist, sehr sehr unterschiedlich sein kann. :-(
Ja, das wäre die andere Möglichkeit...
FPC Compiler Entwickler

Antworten