quimicos - ¿Cómo hacer que los enlaces débiles funcionen con GCC?
puente de hidrogeno (4)
Del manual de gcc doc:
débiles
El atributo débil hace que la declaración se emita como un símbolo débil en lugar de un indicador global. Esto es principalmente útil para definir las funciones de la biblioteca que pueden anularse en el código del usuario, aunque también se puede usar con declaraciones que no sean de funciones. Los símbolos débiles son compatibles con los objetivos ELF, y también para los objetivos out cuando se utiliza el ensamblador y el enlazador GNU.
lo que significa que un objeto está legitimado para sobrescribir un símbolo débil (definido en otro objeto / biblioteca) sin errores al momento del enlace. Lo que no está claro es si está vinculando la biblioteca con el símbolo débil o no. Parece que ambos no han definido el símbolo y que la biblioteca no está correctamente vinculada.
Parece haber 3 formas de decirle a GCC que vincule débilmente un símbolo:
__attribute__((weak_import))
-
__attribute__((weak))
-
#pragma weak symbol_name
Ninguno de estos funciona para mí:
#pragma weak asdf
extern void asdf(void) __attribute__((weak_import, weak));
...
{
if(asdf != NULL) asdf();
}
Siempre obtengo un error de enlace como este:
Undefined symbols: "_asdf", referenced from: _asdf$non_lazy_ptr in ccFA05kN.o ld: symbol(s) not found collect2: ld returned 1 exit status
Estoy usando GCC 4.0.1 en OS X 10.5.5. ¿Qué estoy haciendo mal?
Debe establecer la variable MACOSX_DEPLOYMENT_TARGET a 10.2 o posterior. Consulte la documentación de Apple y su nota técnica sobre enlaces débiles.
Agregue -Wl,-flat_namespace,-undefined,dynamic_lookup
a la línea del compilador gcc que usa para hacer el enlace final.
Acabo de analizar esto y pensé que otros podrían estar interesados en mis hallazgos.
La vinculación débil con weak_import realmente solo funciona bien con bibliotecas dinámicas. Puede hacer que funcione con enlaces estáticos (al especificar "dynamic_lookup no definido" como se sugirió anteriormente), pero esta no es una idea tan buena. Significa que no se detectarán símbolos indefinidos hasta el tiempo de ejecución. Esto es algo que evitaría en el código de producción, personalmente.
Aquí hay una sesión de la Terminal Mac OS X que muestra cómo hacer que funcione:
Aquí está fc
int f(int n)
{
return n * 7;
}
Aquí está whatnof.c
#include <stdio.h>
#include <stdlib.h>
extern int f (int) __attribute__((weak_import));
int main() {
if(f == NULL)
printf("what, no f?/n");
else
printf("f(8) is %d/n", f(8));
exit(0);
}
Crea una biblioteca dinámica desde fc:
$ cc -dynamiclib -o f.dylib f.c
Compile y vincule con la lib dinámica, liste libs dinámicas.
$ cc -o whatnof whatnof.c f.dylib
$ otool -L whatnof
whatnof:
f.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.0)
Ejecuta whatnof para ver qué pasa:
$ whatnof
f(8) is 56
Ahora reemplace f.dylib con una biblioteca vacía (sin símbolos):
$ mv f.dylib f.dylib.real
$ touch null.c
$ cc -dynamiclib -o f.dylib null.c
Ejecuta lo mismo para ver qué pasa:
$ whatnof
what, no f?
La idea básica (o "caso de uso") de weak_import es que le permite vincularse con un conjunto de bibliotecas dinámicas (compartidas), pero luego ejecuta el mismo código en versiones anteriores de las mismas bibliotecas. Puede verificar las funciones contra NULL para ver si son compatibles con la biblioteca dinámica particular con la que se está ejecutando actualmente el código. Esto parece ser parte del modelo de desarrollo básico soportado por Xcode. Espero que este ejemplo sea útil; me ayudó a tranquilizarme sobre esta parte del diseño de Xcode.