2012-01-04 12 views
8

Estoy observando una diferencia al intentar hacer la misma operación en GCC 4.4 y GCC 4.5. Debido a que el código con el que estoy haciendo esto es de propiedad, no puedo proporcionarlo, pero estoy observando un error similar con este sencillo caso de prueba.GCC 4.5 vs 4.4 vinculación con dependencias

Lo que básicamente trato de hacer es tener una biblioteca compartida (libb) que dependa de otra biblioteca compartida (liba). Al cargar libb, supongo que liba también debe cargarse, aunque libb no necesariamente usa los símbolos en liba.

Lo que estoy observando es cuando compilo con GCC 4.4, observo que la liba está cargada, pero si compilo con GCC 4.5, no se carga libb.

Tengo una pequeña caja de prueba que consta de dos archivos, a.c. y b.c. El contenido de los archivos:

//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 

Ésta es mi salida con diferentes versiones de 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 
$ 

Puede alguien explicar lo que está sucediendo? Otra información adicional es que ldd en libb.so muestra liba.so en GCC 4.4 pero no en GCC 4.5.

EDITAR

me cambió test.sh a lo siguiente:

$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 

Esto dio el siguiente resultado 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

Mi entorno de compilación es Ubuntu 11.10 x86-64 –

+0

en Debian 6.0.3, el GCC 4.4 empaquetado maneja el ejemplo sin problemas. El GCC 4.3 empaquetado se queja de una bandera '-fPIC' faltante. –

Respuesta

11

Parece que ha habido cambios en cómo se tratan las bibliotecas DT_NEEDED durante la vinculación por ld. Aquí está la parte pertinente de la corriente man ld:

Con --copy-dt-needed-entries bibliotecas dinámicas mencionadas en la línea de comandos serán de forma recursiva buscado, a raíz de sus etiquetas DT_NEEDED a otras bibliotecas, con el fin de resolver los símbolos requeridos por el binario de salida. Con la configuración predeterminada , la búsqueda de las bibliotecas dinámicas que siguen se detendrá con la propia biblioteca dinámica. No se atravesarán los enlaces DT_NEEDED para resolver los símbolos.

(parte de la sección --copy-dt-needed-entries).

Algún tiempo entre GCC 4.4 y GCC 4.5 (aparentemente, vea alguna referencia here - no se puede encontrar nada realmente autorizado), el valor predeterminado cambió de la búsqueda recursiva a ninguna búsqueda recursiva (como se ve con el más reciente GCC).

En cualquier caso, puede (y debe) solucionarlo mediante la especificación de liba en su paso eslabón final:

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

Usted puede comprobar que este ajuste enlazador es de hecho (al menos parte de) el problema corriendo con sus nuevos compiladores y esta línea de comandos:

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

Esa sería una muy buena explicación, pero agregar las banderas no cambia el resultado. He intentado agregarlos tanto al compilar libb.so como al construir cc –

+0

Como referencia, mi versión de LD es GNU ld (GNU Binutils para Ubuntu) 2.21.53.20110810 –

+0

Las banderas solo son necesarias en el enlace final, no cuando construyendo los archivos '.so'. En cualquier caso, la verdadera solución es vincular su ejecutable con 'libb' ** y **' liba'. (Estoy en ld 2.22.) – Mat

Cuestiones relacionadas