2012-01-04 15 views
8

Sto osservando una differenza quando si tenta di eseguire la stessa operazione su GCC 4.4 e GCC 4.5. Perché il codice con cui sto facendo questo è proprietario, non sono in grado di fornirlo, ma sto osservando un errore simile con questo semplice caso di test.GCC 4.5 vs 4.4 collegamento con dipendenze

Quello che sto cercando di fare è che una libreria condivisa (libb) dipende da un'altra libreria condivisa (liba). Quando carico libb, presumo che anche la liba debba essere caricata - anche se libb non usa necessariamente i simboli in liba.

Quello che sto osservando è quando compilo con GCC 4.4, osservo che la liba è caricata, ma se compilo con GCC 4.5, libb non è caricato.

Ho un piccolo test case costituito da due file, a.c e b.c. Il contenuto dei file:

//a.c 
int a(){ 
    return 0; 
} 

//b.c 
int b(){ 
    return 0; 
} 
//c.c 
#include <stdio.h> 
int a(); 
int b(); 

int main() 
{ 
    printf("%d\n", a()+b()); 
    return 0; 
} 
//test.sh  
$CC -o liba.so a.c -shared 
$CC -o libb.so b.c -shared -L. -la -Wl,-rpath-link . 
$CC c.c -L. -lb -Wl,-rpath-link . 
LD_LIBRARY_PATH=. ./a.out 

Questa è la mia uscita con diverse versioni di GCC

$ CC=gcc-4.4 ./test.sh 
1 
$ CC=gcc-4.5 ./test.sh 
/tmp/cceJhAqy.o: In function `main': 
c.c:(.text+0xf): undefined reference to `a' 
collect2: ld returned 1 exit status 
./test.sh: line 4: ./a.out: No such file or directory 
$ CC=gcc-4.6 ./test.sh 
/tmp/ccoovR0x.o: In function `main': 
c.c:(.text+0xf): undefined reference to `a' 
collect2: ld returned 1 exit status 
./test.sh: line 4: ./a.out: No such file or directory 
$ 

Qualcuno può spiegare che cosa sta succedendo? Un altro extra di informazioni è che ldd su libb.so mostra liba.so su GCC 4.4 ma non su GCC 4.5.

EDIT

ho cambiato test.sh al seguente:

$CC -shared -o liba.so a.c 
$CC -L. -Wl,--no-as-needed -Wl,--copy-dt-needed-entries -la -shared -o libb.so b.c -Wl,-rpath-link . 
$CC -L. c.c -lb -Wl,-rpath-link . 
LD_LIBRARY_PATH=. ./a.out 

Questo ha dato il seguente risultato con GCC 4.5:

/usr/bin/ld: /tmp/cc5IJ8Ks.o: undefined reference to symbol 'a' 
/usr/bin/ld: note: 'a' is defined in DSO ./liba.so so try adding it to the linker command line 
./liba.so: could not read symbols: Invalid operation 
collect2: ld returned 1 exit status 
./test.sh: line 4: ./a.out: No such file or directory 
+0

il mio ambiente di sviluppo è Ubuntu 11.10 x86-64 –

+0

Su Debian 6.0.3, il GCC 4.4 impacchettato gestisce l'esempio senza problemi. Il GCC 4.3 impacchettato lamenta un flag '-fPIC' mancante. –

risposta

11

Sembra che ci sono stati cambiamenti nella le librerie DT_NEEDED vengono gestite durante il collegamento da ld. Ecco la parte rilevante della corrente man ld:

Con --copy-dt-needed-entries librerie dinamiche menzionate nella riga di comando saranno ricorsivamente cercato, seguendo le loro tag DT_NEEDED ad altre biblioteche, al fine di risolvere i simboli richiesti dal binario di uscita. Con l'impostazione di default tuttavia la ricerca delle librerie dinamiche che la seguono si fermerà con la libreria dinamica stessa. Nessun collegamento DT_NEEDED verrà attraversato per risolvere i simboli.

(parte della sezione --copy-dt-needed-entries).

Un po 'di tempo tra GCC 4.4 e GCC 4.5 (apparentemente, vedere qualche riferimento here - non riesce a trovare nulla di veramente autorevole), il valore predefinito è stato modificato dalla ricerca ricorsiva, a nessuna ricerca ricorsiva (come si vede con i più recenti GCCS).

In ogni caso, si può (e si deve) risolvere il problema specificando liba nel vostro passo anello finale:

$CC c.c -L. -lb -la -Wl,-rpath-link . 

È possibile verificare che questa impostazione linker è davvero (almeno in parte) il problema in esecuzione con i tuoi nuovi compilatori e questa riga di comando:

$CC c.c -L. -Wl,--copy-dt-needed-entries -lb -Wl,--no-copy-dt-needed-entries \ 
     -Wl,-rpath-link . 
+0

Questa sarebbe un'ottima spiegazione, ma l'aggiunta delle bandiere non cambia il risultato. Ho provato ad aggiungerli entrambi quando costruisco libb.so e quando si costruisce cc –

+0

Per riferimento, la mia versione di LD è GNU ld (GNU Binutils per Ubuntu) 2.21.53.20110810 –

+0

Le bandiere sono necessarie solo sul collegamento finale, non quando costruendo i file '.so'. In ogni caso, la vera soluzione è collegare il tuo eseguibile con 'libb' ** e **' liba'. (Sono su ld 2.22.) – Mat

Problemi correlati