• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

C++: Dynamische Bibliotheken einbinden

Hallo allerseits,

ich habe ein Programm (/program/program.cpp) einige Bibliotheksroutinen eingebunden (gsl,fftw,...). Nun hätte ich gerne, dass das Programm auf jedem Linux-System läuft. Dazu hab ich mal
Code:
ldd program
eingegeben, und alle Bibliotheken die da standen in einen Unterordner "/program/lib/" kopiert. zusätzlich hab ich alle benutzten Header in ein Unterverzeichnis "/program/include/" kopiert. Dann hab ich die Flags im makefile verändert, so dass diese Ordner eingebunden werden (also -L./lib und -I./include hinzugefügt).
Und jetzt hab ich eigentlich gehofft, dass ich das Programm auf nem fremden System kompilieren kann...

Nur geht leider nicht. Nicht nur, dass das kompilieren ewig dauert, zusätzlich kommen nach drei Minuten etliche Fehlermeldungen (~5 Seiten).
Wenn ich das Programm auf meinem System kompiliere (in der Hoffnung dass nur die Bibliotheken in den Unterverzeichnissen verlinkt werden) gehts genauso wenig, dann findet er auf dem fremden System die Libraries im Ordner /lib nicht.

Hat jemand einen guten Rat ?
Danke im Voraus,
Gruß David
 
Hallo,

zu sowas hab' ich mal geschrieben:
7. Linking the Program against Libraries

When you use the "#include"-directive, the program is linked against some library.

You can check the libraries used by an executable with the "ldd"-command. For example shows

ldd ./hello

the libraries, an executable "hello" is linked against.

Some standard libraries like "libc.so.6" are recognized by "gcc" automatically. But the names of other libraries have to be passed to "gcc" manually.
If, for example, you want to use the math-library "libm.so.6" in a program "printsin.c", that prints the sinus of 45 degrees:

#include <stdio.h>
#include <math.h>

int main(void)
{
printf("%f\n", sin(45));
return 0;
}

compilation with

gcc -Wall -W -ansi -pedantic -o prsin printsin.c

doesn't work, because the math-library isn't found. You have to tell "gcc", that the program needs this library.

You can do that, using the "-l"-option:

Directly after the "-l", you have to pass the library-name: It's got to be just the part of the name between "lib" and ".so.6". So to link against "libm.so.6", it's just "-lm". Not more:

gcc -Wall -W -ansi -pedantic -o prsin printsin.c -lm

compiles the program above.

When "-l" is used, "gcc" searches its default-path for the library.
Several directories like "/lib" and "/usr/lib" are in this path. That's why the compilation above already worked.
But you could ask "gcc" to search for a library in a certain other directory using the "-L"-option. Here's an example, but with "/usr/lib" again:

gcc -Wall -W -ansi -pedantic -o prsin printsin.c -lm -L/usr/lib

To make "-L" work with any directory, you would have to do

/sbin/ldconfig /path/to/my/directory

as "root" first to add the directory to the "ld-library-cache". Usually, this isn't necessary, because most libraries install themselves into default-directories, because they want to be found by programs.

Notice, that the options "-l" and "-L" have to be given after the file-names to compile (because they refer to the linking-process).
Also "ldconfig"; sollte man aber nicht so machen: Wenn's überall laufen soll, sollten die Libs in Standard-Verzeichnissen sein.

Auch recht gut:

http://www.amath.washington.edu/~lf/tutorials/autoconf/toolsmanual.html

Viele Grüße
 
Wenn ich das Programm auf meinem System kompiliere (in der Hoffnung dass nur die Bibliotheken in den Unterverzeichnissen verlinkt werden) gehts genauso wenig, dann findet er auf dem fremden System die Libraries im Ordner /lib nicht

wenn Bibliotheken nicht in einem Standard-Pfad stehen, musst du vor Programmaufruf den LD_LIBRARY_PATH setzen.
Code:
export LD_LIBRARY_PATH=./lib:$LD_LIBRARY_PATH
./dein-programm

wichtig ist dabei ALLE Verzeichnisse (durch ":" getrennt), welche nicht Standard sind, aufzuführen.
 
Hallo Leute,
danke erstmal für eure Antworten. Allerdings läufts immer noch nicht.

Das meiste war mir schon klar, allerdings dachte ich, dass wenn ich beim compilieren explizit angebe, wo er die Bibliotheken suchen soll, dass man dann den LIBRARY_PATH nicht zu ändern braucht ??? Außerdem erhalte ich nur 'Speicherzugriffsfehler' -Meldungen, wenn ich das auf dem anderen System eingebe (nichtmal "ls" geht dann noch)

ldconfig fällt auch flach, ich hab keine root-Rechte auf dem PC wos laufen soll.

Kann mir bitte nochmal jemand das Problem erläutern ? Ich dachte es genügt, alle benötigten libraries in einen Ordner ./lib zu packen und dann auf dem neuen System mit -L./lib zu compilieren. Warum reicht das anscheinend nicht ? Und wie gehts ?

Dazu gleich die nächste Frage: bis zu welcher Ebene gibt ldd die Abhängigkeiten von libraries an. Kann es sein, dass eine library eine weitere braucht, die ldd nicht angibt ?

Bis dann,
Gruß David
 
du vermengst hier zwei Sachen: compile-time und run-time

zur run-time brauchst du den LD_LIBRARY_PATH, zur compile-time musst du dem Linker sagen welche libraries und wo sie zu finden sind.
 
und damit man dir mal konkret helfen kann, poste mal die Ausgabe deines compile/link Laufes nach nopaste:
http://www.rafb.net/paste/

Und den Ergebnis-Link von nopaste dann bitte hier posten. Dann sieht man mal was du da eigentlich treibst :mrgreen:
 
Aaah, konkrete Hilfe, genau das brauch ich ;-)

Allerdings kann ich da keine 10000 Zeilen Compiler-Ausgabe reinposten...

Ich glaube allerdings, dass es daran liegt, dass die Standardbibliotheken nicht gefunden werden, da viele Meldungen wie "undefined reference to std:basic_ostream" (bzw. std::basic_string usw..) ausgegeben werden.
Ich habe mal auf meinem Rechner mit "-nostdlib" kompiliert, da bekomm ich ungefähr die selbe Ausgabe wie auf fremden Rechnern. Ziel ist es ja, dass das Programm seine Bibliotheken gänzlich dem Ordner ./lib entnimmt (denke ich zumindest - dann sollts ja auf jedem System laufen).

Ich kann ja nochmal mein Vorgehen hinschreiben, und ihr sagt mir wos nicht richtig ist:

(i) ldd eingeben - alle dynamischen Libs finden, die das Programm braucht
(ii) Alle statischen Bibliotheken finden (welche sind die Standardbibliotheken ?)
(iii) Die alle in den Unterordner /Lib/ kopieren
(iv) Beim compilieren nun "-L./lib" dazuschreiben und evtl. "-nostdlib", um einen Rechner ohne Bibliotheken zu simulieren.
(v) Hoffen dass es geht.

Danke nochmal,
Gruß David
 
davidhigh schrieb:
(i) ldd eingeben - alle dynamischen Libs finden, die das Programm braucht
(ii) Alle statischen Bibliotheken finden (welche sind die Standardbibliotheken ?)
Was willst du mit statischen? Die werden doch nicht gebraucht.
(iii) Die alle in den Unterordner /Lib/ kopieren
(iv) Beim compilieren nun "-L./lib" dazuschreiben und evtl. "-nostdlib", um einen Rechner ohne Bibliotheken zu simulieren.
Compilier das ganze doch einfach ohne -Llib und ohne -nostdlib Flags, und kopiere hinterher einfach die Bibliotheken;—wo ist das Problem?
 
O.k., dann kann ich das Programm auf dem neuen System nicht bearbeiten, aber egal. Hauptsache es läuft...

Also: Ich kompiliere es ganz normal und kopiere alle libs aufs neue System ins Verzeichnis "/program/lib".
Läuft aber noch nicht, klar da er /lib/ nicht durchsucht.
Also " export LD_LIBRARY_PATH=~/program/lib:$LD_LIBRARY_PATH " eingeben, damit er zur Laufzeit /lib/ durchsucht.

Danach erhalte ich aber bei jedem Befehl (ls,cd,./program,..) die Ausgabe "Speicherzugriffsfehler" ?

Woran liegt das ?

Gruß David
 
Hallo,

ich verstehe immer noch nicht, was Du da vorhast: Also, Dein Programm soll nicht überall laufen, sondern auf EINEM anderen Rechner, auf dem Du aber keine root-Rechte hast.

... und das ist schon ein System, auf dem das Executable nicht laufen würde, wenn Du's bei Dir kompiliert hättest ?

Was machst Du, wenn Du auf dem anderen System was nachinstallieren mußt ? Bist Du überhaupt sicher, daß dort auch nur g++, make usw. vorhanden sind ?

Weißt Du was, wenn Du dort wirklich kompilieren mußt, würde ich den dortigen SysAdmin fragen, ob er Dir bzgl. der Sachen, die root-Rechte voraussetzen, helfen würde ...

Oder willst Du dem SysAdmin ein fremdes Programm ins System schieben ? Von was für einem Programm reden wir hier überhaupt ???

Gruß
 
Hi,

ich bin Physik-Student und das Programm brauch ich für meine Diplomarbeit. Weil die so langsam in die heiße Phase geht, würd ich gerne ein paar Rechnungen auf den Uni-Server auslagern. Das Programm soll bitte auf jedem der dortigen Rechner laufen (auf welchem Rechner jetzt genau welche libs instaliert sind, weiss ich nicht. Die Standardprogramme (g++, make,..) sind aber drauf. Der Admin ist da auch sehr schwerfällig, so dass ich ihn nur ungern nochmal bitten würde - ich habs schon getan und es tut sich nichts...).

Deshalb dache ich zunächst, ich liefer generell alle libs mit, so dass das Programm unabhängig vom Rechner läuft. Und ich es dort auch kompilieren kann. Die Sache sollte ja nicht zu kompliziert sein...
Eigentlich gibts ja auch nur zwei Möglichkeiten, die hier auch schon angesprochen wurden:

Alle libs die beötigt werden mit "ldd -v" finden. Dann diese in Unterordner lib kopieren. Dann:

(i) Bei mir kompilieren, dort laufen lassen. Nehme alle libs aus dem Unterordner lib.
(ii) Dort kompilieren, dort laufen lassen. Nehme ebenso alle libs aus dem Unterordner lib, dieses Mal allerdings schon beim Kompiliervorgang.

Davor noch auf dem fremden System "export LD_LIBRARY_PATH=./lib:$LD_LIBRARY_PATH", aber dann gibts wie gesagt Speicherzugriffsfehler bei jedem weiteren Befehl. Warum ???

Kann mir bitte jemand die Vorgehensweise zu einem von beiden genauer erklären bzw. einen Link schicken, wo das gemacht wird ?
Tut mir leid wenn ich mich hier wiederhole oder das allzu länglich wird, aber es ist mir sehr wichtig...
Naja,
danke nochmal im Voraus,
Gruß David
 
davidhigh schrieb:
Danach erhalte ich aber bei jedem Befehl (ls,cd,./program,..) die Ausgabe "Speicherzugriffsfehler" ?
Du fragst mich—ich frag dich!


Was ist denn dieses "fremde" System?
Leider gibt es manchmal gravierende Unterschiede wie die GNU Libcs funktionieren... die kopierte libc.so.6 kannst du oftmals nicht mit den Systemprogrammen wie ls verwenden, verwende LD_LIBRARY_PATH daher *nur* für dein Programm, und nicht für den Rest des Systems. Mit anderen Worten: die Umgebungsvariable nur für das Programm setzen.
 
Ja, das fremde System. Klingt nach SciFi, ist aber ein normaler Opteron-PC.

Mit anderen Worten: die Umgebungsvariable nur für das Programm setzen.

Kannst du mir noch sagen, wie man das macht ?
Und: Das Programm selbst gibt genau so einen Speicherzugriffsfehler wie ls,cd und alle anderen Befehle.

Gruß David
 
Oben