Shared librarys erstellen (in KDevelop)

Moin,
also die Situtation is folgende:
Ich wollte eine shared lib. und ein kleines Testprogramm für selbige erstellen; als Grundlage hab ich das C++ Projekt "Einfaches Hello-World Programm" benutzt. Das automatisch erstellte target (für KDevelop, nicht für make) enthält nur das Testprogramm.
Dem vorhandenen "Unterprojekt" namens "src" (was halt automatisch immer erstellt wird) hab ich ein neues unterprojekt hinzugefügt in dem source usw. für die library ist. Diesem Unterprojet hab ich dann n neues Target hinzugefügt für die Einstellungen wegen der shared lib.
Wenn ich das in KDevelop ausführe, klappt alles wunderbar. Wenn ich das aber mit dem Dreisatz installiere, kommt die Fehlermeldung "error while loading shared libraries: libplayersynk.0: cannot open shared object file: No such file or directory"

Alles in allem sieht die Struktur so aus:
src/libplayersynktest.cpp <---- das testprogramm
src/Makefile.am
src/libplayersynk/libplayersynk.h <--- die lib halt
src/libplayersynk/libplayersynk.cpp
src/libplayersynk/Makefile.am

src/libplayersynk/Makefile.am:
Code:
AM_CPPFLAGS=$(all_includes)
lib_LTLIBRARIES = libplayersynk.la
libplayersynk_la_LDFLAGS = $(all_libraries) -version-info 0:1:0 -no-undefined
libplayersynk_la_SOURCES = libplayersynk.cpp
include_HEADERS=libplayersynk.h
METASOURCES = AUTO
src/Makefile.am:
Code:
bin_PROGRAMS = libplayersynktest
libplayersynktest_SOURCES = libplayersynktest.cpp

# set the include path found by configure
INCLUDES = -I$(top_srcdir)/src/libplayersynk $(all_includes)

# the library search path.
libplayersynktest_LDFLAGS = $(all_libraries)
libplayersynktest_LDADD = libplayersynk/libplayersynk.la
SUBDIRS = libplayersynk
AM_CXXFLAGS = -fPIC

Dass der die shared lib nich findet is eigentlich klar... es gibt kein Verzeichniss namens libplayersynk/ die library wird einfach nach /usr/local/lib installiert.
Wenn ich das aber Umänder in "-lplayersynk" dann klappt das mit dem kompilieren in KDevelop nicht, da die library ja nich installiert ist.
Hilfe? :(
 
Das Kompilieren und Linken klappt doch wunderbar, bloß müsstest Du vor dem Ausführen noch die Umgebungsvariable LD_LIBRARY_PATH=/pfad/zur/fertigen/bibliothek setzen, andernfalls kann das Programm nicht wissen, wo es nach der Bibliothek suchen soll.

/usr/local/lib ist "eigentlich" ein Standardverzeichnis für Bibliotheken, aber irgendwie scheint Deine Distribution das irgendwie vergessen zu haben. Also:
Code:
export LD_LIBRARY_PATH="/usr/local/lib"
PS: Was soll denn diese Zeile hier bewirken?
Code:
AM_CXXFLAGS = -fPIC
Soweit ich weiß, braucht man das nicht, weil automake und libtool sich automatisch um PIC kümmern. So, wie Du es da angegeben hast, verbessert es die Portabilität nicht, sondern verschlechtert sie, weil -fPIC GCC-spezifisch ist. Andere Compiler haben andere Flags für PIC.
 
Ah wunderbar, das klappt.
Nur... meine /etc/ld.so.conf enthält diese Zeile, wieso hat das dann nich geklappt? :shock:

PS: Was soll denn diese Zeile hier bewirken?
Code:
AM_CXXFLAGS = -fPIC

Soweit ich weiß, braucht man das nicht, weil automake und libtool sich automatisch um PIC kümmern. So, wie Du es da angegeben hast, verbessert es die Portabilität nicht, sondern verschlechtert sie, weil -fPIC GCC-spezifisch ist. Andere Compiler haben andere Flags für PIC.

Ich hab sowas von kein Plan... stand in einem KDevelop- Howto so drinne.
http://www.kdevelop.org/index.html?filename=3.3/faq.html#How_to_create_a_.so_library.3F
Was ist PIC überhaupt? :roll:
 
teilzeitstudent schrieb:
Nur... meine /etc/ld.so.conf enthält diese Zeile, wieso hat das dann nich geklappt? :shock:
Weil man das Programm "/sbin/ldconfig" ausführen muss, bevor neu installierte Bibliotheken gefunden werden. Daran hatte ich vorhin gar nicht gedacht, aber das muss der Grund sein.

Zur Info: Das Programm "/lib/ld-linux.so.2" ist der dynamische Linker. Dieses Programm wird beim Ausführen dynamisch gelinkter Programme immer als erstes aufgerufen und ist u.a. dafür zuständig, die Bibliotheken zu finden. Das tut er auch sehr zuverlässig, aber leider langsam.

Deswegen sucht er die Bibliotheken nicht direkt im Dateisystem, sondern aus der Cache-Datei "/etc/ld.so.cache". Diese Cache-Datei muss immer neu aufgebaut werden, wenn man eine Bibliothek ins Verzeichnis "/lib", "/usr/lib" oder in eines der Verzeichnisse aus "/etc/ld.so.conf" installiert.

Genau das geschieht, wenn man "/sbin/ldconfig" ausführt, also immer schön daran denken, dies nicht zu vergessen.
teilzeitstudent schrieb:
Ich hab sowas von kein Plan... stand in einem KDevelop- Howto so drinne.
http://www.kdevelop.org/index.html?filename=3.3/faq.html#How_to_create_a_.so_library.3F
Was ist PIC überhaupt? :roll:
PIC ist "position independent code". Alle technischen Details dazu finden sich im DSO-HowTo von Ulrich Drepper:

http://people.redhat.com/drepper/dsohowto.pdf

Eigentlich brauchst Du die Details gar nicht genau zu kennen. Wichtig ist nur: Sämtlicher Code, der in Shared Libraries landet, muss PIC sein. Damit er PIC wird, muss man die GCC-Option "-fPIC" verwenden, wenn man den GCC direkt benutzt.

Du benutzt den GCC allerdings nicht direkt, sondern über automake und libtool. Die kümmern sich schon darum, dass der Code, der PIC sein muss, PIC wird - und auch wirklich nur dieser und kein anderer. Nach Deinem jetzigen System wäre nämlich nicht nur die Shared Library PIC, sondern auch die eventuell gebaute statische Bibliothek und möglicherweise auch die Anwendung. Das schadet zwar nicht, ist aber auch nicht optimal, weil PIC geringfügig langsamer ist.

Nimm das mal raus, kompilier das Projekt dann nochmal und schau nach, ob in den g++-Aufrufen "-fPIC" drinsteckt. Ich gehe einfach mal davon aus, dass das der Fall sein wird. Wenn ja, dann belass es auch dabei, es nicht explizit reinzuschreiben.

Hintergrund: Sollte theoretisch irgendwann mal jemand auf die Idee kommen, Dein Projekt mit einem anderen Compiler zu übersetzen, dann würde er Probleme bekommen, wenn dort explizit "-fPIC" steht. Bei anderen Compilern lautet die Option für PIC nämlich anders, bei Suns Compilern beispielsweise "-KPIC". libtool weiß das und fügt für jeden Compiler die passende Option hinzu.
 
Hmm, also wenn ich das richtig verstehe, dann wird beim complilieren & linken direkt im Dateisystem nach diesen Bibliotheken geguckt (halt innerhalb des Projektes in meinem Fall) und wenn ein installiertes Programm ausgeführt wird, wird im cache nachgeguckt?
Allerdings... ich hab vorhin nochma das alles umgestellt auf 2 verschiedene Projekte; das alte alles deinstalliert, die shared lib installiert (ohne ldconfig aufzurufen) und beim Ausführen des Testprogrammes gab es keinerlei Probleme... aber ich schätze mal, da hat der einfach den alten Eintrag vom letzten Versuch genommen. Version und alles war ja genau das gleiche.
Die Sache mit den Versionen scheint ja auch noch 'n Thema für sich zu sein... ich wünschte wir hätten sowas mal in den Vorlesungen anstatt Mathe von morgens bis abends :p

Hintergrund: Sollte theoretisch irgendwann mal jemand auf die Idee kommen, Dein Projekt mit einem anderen Compiler zu übersetzen, dann würde er Probleme bekommen, wenn dort explizit "-fPIC" steht. Bei anderen Compilern lautet die Option für PIC nämlich anders, bei Suns Compilern beispielsweise "-KPIC". libtool weiß das und fügt für jeden Compiler die passende Option hinzu.
Jupp, der fügt da automatisch -fPIC und -DPIC ein.

Danke für die schnelle und umfangreiche Hilfe :D
 
teilzeitstudent schrieb:
Hmm, also wenn ich das richtig verstehe, dann wird beim complilieren & linken direkt im Dateisystem nach diesen Bibliotheken geguckt (halt innerhalb des Projektes in meinem Fall) und wenn ein installiertes Programm ausgeführt wird, wird im cache nachgeguckt?
Ja, genau so ist es.

Beim Kompilieren und Linken spielt es ja auch keine so furchtbar große Rolle, ob das nun eine Viertelsekunde länger dauert oder nicht. Beim Ausführen aber sehr wohl (ist wirklich so - wenn Programme auch nur den Bruchteil einer Sekunde nicht reagieren, werden sie von den Benutzern als "langsam" wahrgenommen).

PS: Wahrscheinlich ist die Tatsache, dass die Bibliothek beim zweiten Mal auch ohne ldconfig gefunden wurde, wirklich darauf zurückzuführen, dass der Cache-Eintrag schon da war. Um ihn loszuwerden, kann man einfach nach dem Entfernen auch wieder ldconfig ausführen.
 
Oben