ld: utilisant -rpath,$ORIGIN À l'intérieur de la bibliothèque générale /Récursif/

Je viens de faire un exemple de base d'utiliser l'option
-rpath

ld de
$ORIGIN

https://coderoad.ru/6311016/
/Voir la 2e réponse de la version de travail/. J'essaie de créer un exemple , Où
main.run

fait référence à
foo.so

, qui fait à son tour référence à
bar.so

, Tout en utilisant
rpath

et
$ORIGIN

.

La structure de fichier du temps d'exécution est comme suit:

project/

lib/

dir/

sub/

bar.so


foo.so


run/

main.run

/Ne peut pas construire/


Je suis en train de bâtir foo.so par:


g++ -c -o obj/foo.o src/foo.cpp -fPIC
g++ -shared -o lib/dir/foo.so obj/foo.o -Wl,-soname,foo.so -Wl,-rpath,'$ORIGIN/sub' -Llib/dir/sub -l:bar.so


Qui est parfaitement construit.
ldd lib/dir/foo.so

Peut-être même trouvé
bar.so

.

Cependant, quand j'essaie de crier
main.run

de
foo.so

,
foo.so

Impossible de trouver bar.so.

Je suis en train de bâtir main.so par:


g++ -c -o obj/main.o src/main.cpp
g++ -o run/main.run obj/main.o -Wl,-rpath,'$ORIGIN/../lib/dir' -Llib/dir -l:foo.so


Cela fonctionne parfaitement parfaitement si une autre version est utilisée
foo.so

, qui n'est pas une liaison récursive. /Lignes rassasiantes B. make.sh, Dans le projet ci-dessous pour vérifier/.

Cependant, en utilisant l'habituel
foo.so

, Je reçois cette erreur lors de la construction
main.run

:

/usr/bin/ld: Attention: bar.so, Obligatoire lib/dir/foo.so, pas trouvé /Essayer d'utiliser -rpath ou -rpath-link/

Donc, mes questions sont les suivantes ::

Li est autorisé
$ORIGIN

à l'intérieur foo.so dans
project/lib/dir

/Où
foo.so

/ ou
project/run

/Où
main.run

/Fichier exécutable la liaison//?

ldd , apparemment indique que cela
project/lib/dir

, Ce qui semble être le meilleur moyen /Bien que j'ai essayé de supposer à la fois/.


Comment puis-je leur faire les attacher /Garder la possibilité de bouger/ - De préférence sans utilisation
-rpath-link

.

Vous pouvez télécharger le projet
http://dl.dropbox.com/u/319906 ... t.zip
. C'est tellement simple que je peux faire. 4 Brèves sources et script.

Après avoir passé juste courir
./make.sh

de
project/

.


Noter:

j'utilise
-l:

. Ça ne devrait rien changer , sauf que les bibliothèques sont appelées comme
foo.so

au lieu
libfoo.so

, et lunk de
-l:foo.so

au lieu
-lfoo

.
Invité:

Babette

Confirmation de:

Eh bien, j'ai quelque chose à travailler. Mais je ne comprends vraiment pas pourquoi ça marche. Pour moi, cela ressemble à une erreur dans ld.

L'Iran
strace -f -o /var/tmp/strace.out -- g++ ...

Pour la compilation main.run. La liaison statique essaie réellement d'ouvrir des fichiers, dont le nom littéral ressemble à "$ORIGIN/lib/dir/sub/bar.so", Entre autres 20-30. /En d'autres termes, il recherche un vrai catalogue nommé
$ORIGIN

. Sérieusement./

Il semble également rechercher le chemin de liaison RPATH pour le nom "lib/dir/sub/bar.so", pas seulement "bar.so". Je ne sais pas pourquoi.

En tout cas, c'est un lien pour main.run, Qui fonctionne pour moi:


g++ -o run/main.run obj/main.o -Wl,-rpath,'$ORIGIN/../lib/dir' -Wl,-rpath-link,. -Llib/dir -l:foo.so


Il est identique au tien, mais avec inset
-Wl,-rpath-link,.

.

[une addition]

Eh bien, je pense que je comprends ce qui se passe. Premier, liant statique /GNU ld/ Juste n'observe pas $ORIGIN Dans les bibliothèques avec lesquelles il se lie.

Deuxièmement, comportement lorsqu'il est utilisé
-lbar

contre
-l:bar.so

très différent.

Lancer
readelf -a

sur
foo.so

. Dans votre assemblée, cela montre la dépendance à "lib/dir/sub/bar.so". C'est pourquoi installer des liens de RPATH à "." Corrige l'assemblage main.run; Il provoque une liaison statique de rechercher "." pour "lib/dir/sub/bar.so", Qu'il trouve.

Si vous renommez bar.so dans libbar.so et cravate foo.so utilisant
-lbar

au lieu
-l:bar.so

, Le même readelf montrera que foo.so Dépend maintenant de "libbar.so" /Sans composante de chemin/. Avec l'aide de cette foo.so Vous pouvez faire le lien main.run Travailler en utilisant
-Wl,-rpath-link,lib/dir/sub

, comme prévu , Si vous saviez que la lieur statique n'observe tout simplement pas $ORIGIN.

Au fait, je ne vois pas la syntaxis
-l:bar.so

, documenté n'importe où dans le manuel GNU ld. Juste hors de curiosité, comment vous êtes-vous arrivé?

En supposant que ceci est une fonction prise en charge, c'est un peu comme une erreur /-l:bar.so Crée une dépendance ot lib/dir/sub/bar.so Au lieu de simple bar.so/. Vous pouvez soit faire face à cette erreur en installant rpath-link sur '.' pour main.run, soit renommer du matériel habituel /libxxx.so/.

Christine

Confirmation de:

De la page de référence
http://linux.die.net/man/8/ld-linux
:

$ORIGIN et rpath

ld.so Comprend la chaîne $ORIGIN /ou équivalent ${ORIGIN}/ dans
Caractéristiques rpath /DT_RPATH ou DT_RUNPATH/ En tant que catalogue
, Contenant un fichier d'application exécutable. Ainsi, une application située dans
somedir/app, peut être compilé avec gcc-Wl,-rpath,'$ORIGIN/../lib'
, afin qu'il trouve la bibliothèque générale associée dans somedir/lib indépendamment
d'où somedir Situé dans la hiérarchie des répertoires. Cela facilite la tâche
créature "turn-key" applications qui n'ont pas besoin
établir dans des répertoires spéciaux, mais vous pouvez plutôt décompresser
Tout catalogue et trouvez toujours vos propres bibliothèques générales.

Ainsi, en réponse à votre première question, il n'y a qu'une seule valeur pour
$ORIGIN

:
project/run

.

Par conséquent, la réponse à votre deuxième question devrait être d'utiliser la commande suivante pour communiquer.
foo.so

:


g++ -shared -o lib/dir/foo.so obj/foo.o -Wl,-soname,foo.so -Wl,-rpath,'$ORIGIN/../lib/dir/sub' -Llib/dir/sub -l:bar.so

Gaspard

Confirmation de:

Premièrement, il y a des problèmes avec l'expansion du signe $ qui peut causer des problèmes. Je suis en train de bâtir Python Du code source et faites-le:


export LDFLAGS='-Wl,-rpath,\$${ORIGIN}/../lib -Wl,-rpath,\$${ORIGIN}/../usr/lib -Wl,--enable-new-dtags'


Avant de courir
make

. Cela fonctionne bien et il trouve la dépendance du 1er niveau. Soyez prudent avec des citations simples et doubles lorsque vous traitez avec ce type de problèmes d'expansion de macros.

Deuxièmement, si vous courez
objdump -x

Dans un fichier ou une bibliothèque binaire, vous pouvez voir le titre. RPATH, qu'il contient réellement. Quand je cours
objdump -x path/to/python |grep RPATH

, Il me montre ça.

RPATH
${ORIGIN}/../lib:${ORIGIN}/../usr/lib`

Je vous suggère de vérifier vos fichiers binaires pour voir ce qui est réellement dans le titre RPATH. Malheureusement, je ne pense pas que cela résoudra votre problème. C'est ce que je vois en courant
ldd path/to/python

:


libpython2.7.so.1.0 => /data1/python27/bin/../lib/libpython2.7.so.1.0 /0x00002ad369d4f000/
libpthread.so.0 => /lib/libpthread.so.0 /0x00002ad36a12f000/
libdl.so.2 => /lib/libdl.so.2 /0x00002ad36a34d000/
libutil.so.1 => /lib/libutil.so.1 /0x00002ad36a551000/
libm.so.6 => /lib/libm.so.6 /0x00002ad36a754000/
libc.so.6 => /lib/libc.so.6 /0x00002ad36a9d8000/
/lib64/ld-linux-x86-64.so.2 /0x00002ad369b2d000/


Comme vous pouvez le constater, la dépendance du premier niveau est correctement traitée.
rpath

, Mais la dépendance au deuxième niveau, c'est-à-dire des dépendances libpython, Retour aux bibliothèques système. Et oui, libpython a exactement le même titre RPATH dans votre fichier binaire. J'ai trouvé votre question quand google
rpath recursive

, Essayer de résoudre mon problème de créer indépendamment de la distribution de paquets.

Ajouté plus tard

Titres
rpath

Vivant seulement le chemin FIRST, La bibliothèque souhaitée. S'ils ne les trouvent pas là-bas, le chargeur continue de rechercher des endroits ordinaires.
ldd

Il ne contient que la voie réelle de la bibliothèque trouvée à la suite de la recherche. Quand j'ai copié ces bibliothèques dans le catalogue
rpath

, Que tous fonctionnaient. En principe, il n'y a pas de moyen précis de trouver toutes les dépendances et de les copier, juste
ldd -v path/to/python

Et une analyse de cette sortie.

Giselle

Confirmation de:

Je l'ai également étudié et, autant que je puisse juger, vous devez utiliser
-rpath-link

Pour tout chemin qui utilisera l'extension ORIGIN. Par exemple:


CC -shared /other flags/ -R'$ORIGIN/../lib/' -o /buildpath/lib/libmylib1.so
CC -shared /other flags/ -R'$ORIGIN/../lib/' -lmylib1 -o /buildpath/lib/libmylib2.so
# This fails to link 'somebinary'
CC /various flags/ -R'$ORIGIN/../lib/' -lmylib2 -o /buildpath/bin/somebinary
# This works correctly
CC /various flags/ -R'$ORIGIN/../lib/' -Wl,-rpath-link,/buildpath/lib/mylib1 -lmylib2 -o /buildpath/bin/somebinary
# The text above the carets to the right is a typo: ------------------^^^^^^
# I'm fairly sure it should read like this /though it has been awhile since I wrote this/:
# /.../ -Wl,-rpath-link,/buildpath/lib -lmylib1 /.../



ld

ne se déroulera pas
$ORIGIN

dans les chemins spécifiés en utilisant
-rpath-link

, ou des chemins qu'il supprime de RPATH Sous-section. Dans l'exemple ci-dessus
mylib2

dépend de
mylib1

; Lors de la liaison
somebinary


ld

Essayer de trouver
mylib1

, En utilisant littéral/Chaîne inachevée
$ORIGIN/../lib/

, B. B. intégré libmylib2.so.
ld.so

sera pendant l'exécution, mais pas
ld

.

Il n'utilise pas non plus les chemins spécifiés avec
-L

Trouver sur les pages de dépendance montrées/M | H./.

Catherine

Confirmation de:

Vérifier
https://github.com/zym1010/til ... ct.sh
. En principe, utilisez un supplément
-rpath-link

sans pour autant
$ORIGIN

, car
ld

Ne comprenez pas du tout
$ORIGIN

.

Quant à vos questions.


$ORIGIN

ne fonctionne que pendant l'exécution et il w.r.t. Chaque bibliothèque. Ainsi, différentes bibliothèques générales ont différents
$ORIGIN

.

J'ai peur , Ce qui est préférable d'ajouter
rpath-link

, Et cela n'affectera pas votre portabilité, car ils sont relatifs et n'existeront pas dans le fichier exécutable final, comme je l'ai montré dans ma version.
make.sh


Outre,
https://github.com/zym1010/til ... ng.md
. J'espère que cela aidera.

Hannah

Confirmation de:

Pour autant que je sache, c'est un problème dans ld /c'est à dire. binutils/ Et comment cela est résolu "Secondary Dependencies"

AFAIK commencer avec
binutils >= 2.30

. rpath En fonction de l'ajout à la recherche.
c'est à dire.
ld ... main.exe

trouver
foo.so

, puis lisez RPATH dans
foo.so

Alors trouver
bar.so


Voici mon stack overflow question:
https://coderoad.ru/52647141/
Et voici mes recherches sur diverses distributions /conteneur intérieur docker/ Pour tester diverses versions binutils
https://github.com/Mizux/SecondaryDependency
Remarque: jetez un coup d'œil au magazine Trevis-CI ...

Pour répondre aux questions, connectez-vous ou registre