ad esempio la costruzione di un semplice (ciao-mondo-esque) di utilizzare l'opzione -rpath di LD con $ ORIGIN

StackOverflow https://stackoverflow.com/questions/6311016

  •  26-10-2019
  •  | 
  •  

Domanda

Nota: esempio di lavoro completa seguito. domanda iniziale segue:

Sto avendo problemi con il parametro -rpath di LD con $ORIGIN.
Come io non riuscivo a trovare un esempio completo, ho pensato che mi piacerebbe provare a scrivere uno io stesso, in modo che io e gli altri possono utilizzare in un secondo momento. Una volta che ho capito di lavoro io riordinare in su.

I chiesto questo prima , ma credo che il mio post era un po 'di confusione.

Il progetto di esempio costruisce una libreria condivisa e uno eseguibile che si collega a detto biblioteca.
È molto piccolo (3 file, 22 linee buildscript incl).
È possibile scaricare il progetto dal qui


Struttura del file (prima della costruzione):

  • project/
    • src/
      • foo.cpp
      • main.cpp
    • make.sh

project/src/foo.cpp


int foo()
  { return 3; }

project/src/main.cpp


int foo();

#include <iostream>
int main()
  {
    std::cout << foo() << std::endl;
    return 0;
  }

project/make.sh


# Make directories:
mkdir -p -v obj
mkdir -p -v lib
mkdir -p -v run

# Build the library:
g++ -c -o obj/foo.o src/foo.cpp -fPIC
g++ -shared -o lib/foo.sh obj/foo.o

# Build the executable:
g++ -c -o obj/main.o src/main.cpp
g++ -o run/main.run obj/main.o -Wl,-rpath,'$ORIGIN/../../lib' -Llib -l:foo.sh

Dalla directory project, make.sh eseguire (assicurarsi che sia eseguibile).


struttura del file (dopo l'edificio):

  • project/
    • src/
      • foo.cpp
      • main.cpp
    • obj/
      • foo.o
      • main.o
    • lib/
      • foo.so
    • run/
      • main.run
    • make.sh

run/main.run dovrebbe ora caricare lib/foo.sh sull'esecuzione, da qualsiasi luogo.

Problemi

Al momento, questo funziona solo in parte.
I file di compilare e collegamento OK, ma non riesce a collegamento quando viene eseguito da qualsiasi directory, tranne project (che è il punto di esercizio).

Controllo main.run con spettacoli readelf -d:
0x0000000000000001 (NEEDED) Shared library: [lib/foo.sh]
0x000000000000000f (RPATH) Library rpath: [$ORIGIN/../../lib] Il che sembra vicino (avrei preferito [foo.sh] di [lib/foo.sh] ma Riparerò che più tardi).

AFAICT il $ORIGIN in mezzo -Wl,-rpath,'$ORIGIN/../../lib' project/run/main.run quindi questo rpath dovrebbe diventare project/lib.

Ho cercato $ORIGIN/.., $ORIGIN/../lib, $ORIGIN/../.., $ORIGIN/../../lib senza alcun risultato.

Nota: sto usando -l: che richiede il nome del file libreria completa (tra le altre ragioni, è più facile per script con variabili quando tutte le funzioni assumono lo stesso formato del nome).

Qualcuno sa perché questo non sta funzionando?
O in alternativa, qualcuno ha o sa di un esempio di lavoro completo?

È stato utile?

Soluzione

(avrei preferito [foo.sh] di [lib/foo.sh] ma Riparerò che più tardi).

Non c'è la maggior parte del problema:. Il / nel nome si ferma il linker dinamico dal fare la magia rpath

(La vostra rpath è sbagliato troppo Pensateci:.? Dalla shell, se tu fossi attualmente nella directory in cui il vostro eseguibile è, come si potrebbe arrivare alla directory in cui la libreria è qui, avresti bisogno di cd ../lib . Così il vostro rpath dovrebbe essere $ORIGIN/../lib.)

Se avete costruito il vostro oggetto come libfoo.so e collegato con -Llib -lfoo, il linker dovrebbe capire cosa avevate intenzione, e fare la cosa giusta. Ma se avete intenzione di utilizzare le convenzioni di denominazione inusuali, dovrete aiutare fuori:

  1. Cambia la linea di collegamento per la libreria per impostare in modo esplicito il soname per la libreria a solo foo.sh:

    g++ -shared -Wl,-soname,foo.sh -o lib/foo.sh obj/foo.o

  2. Fissare il rpath:

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

E 'utile eseguire ldd main/main.run per vedere cosa sta succedendo. Nel tuo caso difetto originale, vedrete qualcosa di simile:

    lib/foo.sh (0xNNNNNNNN)

(la mancanza di qualsiasi => /some/resolved/path mostrando che non è fatto alcun risoluzione del percorso). Nel caso fisso, vedrete qualcosa di simile:

    foo.sh => /your/path/to/run/../lib/foo.sh (0xNNNNNNNN)

Altri suggerimenti

Questo è un esempio di relativa percorso che collega (con ld) utilizzando $ORIGIN in rpath.

rpath è un percorso (o insieme di percorsi) incorporato nel file binari (librerie condivise (.so) e gli eseguibili).
Questi percorsi sono i percorsi di ricerca più importanti per le librerie condivise i binari devono essere collegati con in fase di esecuzione.

$ ORIGIN è una directory potenziale inizio per un percorso rPath. Risolve alla directory contenente il file di esecuzione. (Ad esempio: $ORIGIN/lib)

Il progetto di esempio costruisce una libreria condivisa e uno eseguibile che si collega a detto libreria utilizzando rpath e $ORIGIN.
È possibile scaricare il progetto dal qui .


Struttura del file (prima della costruzione):

  • project/
    • src/
      • foo.cpp
      • main.cpp
    • make.sh

project/src/foo.cpp


int foo()
  { return 3; }

project/src/main.cpp


int foo();

#include <iostream>
int main()
  {
    std::cout << foo() << std::endl;
    return 0;
  }

project/make.sh


# Make directories:
mkdir -p -v obj
mkdir -p -v lib/dir
mkdir -p -v run

# Build the library:
g++ -c -o obj/foo.o src/foo.cpp -fPIC
g++ -shared -o lib/dir/foo.so -Wl,-soname,foo.so obj/foo.o

# Build the executable:
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

Dalla directory project, make.sh eseguire (se non funziona, assicurarsi make.sh ha i permessi di esecuzione).

Se tutto è andato bene, main.run dovrebbe ora caricare lib/dir/foo.so sull'esecuzione, indipendentemente dal percorso assoluto per project (è possibile spostarlo ovunque), e indipendentemente dalla directory di lavoro corrente (è possibile eseguirlo da qualsiasi luogo).


Note:

  • -fPIC istruisce il compilatore di costruire file oggetto rilocabile (file oggetto costruzione in librerie condivise devono essere relocatable).
  • -Wl,-soname,<NAME> incorpora <NAME> nella libreria generata. Questo dovrebbe corrispondere al nome utente fornisce per le opzioni -l o -l: quando si collegano a questa libreria.
  • -Wl,-rpath,'<PATH>' incorpora <PATH> in biblioteca generato come un percorso di ricerca libreria di runtime (o rpath - vedi sopra).
  • -L aggiunge un percorso per il l'accumulo di tempo biblioteca di ricerca Lista percorso. . (Nota: rpath è irrilevante al accumulo di tempo, -L è irrilevante in fase di esecuzione)
  • -l: aggiunge il nome del file (senza percorso) di una libreria per Link contro. (Simile a -l, tranne -l: richiede il nome del file completo.

struttura del file (dopo l'edificio):

  • project/
    • src/
      • foo.cpp
      • main.cpp
    • obj/
      • foo.o
      • main.o
    • lib/
      • dir/
        • foo.so
    • run/
      • main.run
    • make.sh

. Nota: sto usando -l: che richiede il nome del file libreria completa (tra le altre ragioni, è più facile per script con variabili quando tutte le funzioni assumono lo stesso formato del nome)
È più comune utilizzo -l, per cui -l<NAME> denota lib.so.

Limitazioni

Per quanto io sappia (correggetemi se sbaglio) non c'è modo per aggiungere una libreria all'interno di una sottodirectory all'interno di un percorso di ricerca (tranne che per l'aggiunta di quella directory come un sub-path). Questo è vero sia per l'accumulo di tempo (-L) e run-time (-rpath) percorsi di ricerca.

se si dispone di due librerie con lo stesso nome, ma luoghi diversi, non sarà in grado di collegare entrambi. (Spero che mi sbaglio o che questo si fissa).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top