¿Cómo hacer que los enlaces débiles funcionen con GCC?

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:

  Símbolos indefinidos:
   "_asdf", referenciado de:
       _asdf $ non_lazy_ptr en ccFA05kN.o
 ld: símbolo (s) no encontrado
 collect2: ld devolvió 1 estado de salida 

Estoy usando GCC 4.0.1 en OS X 10.5.5. ¿Qué estoy haciendo mal?

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  #include  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 fc 

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.

Agregue -Wl,-flat_namespace,-undefined,dynamic_lookup a la línea del comstackdor gcc que usa para hacer el enlace final.

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.

Del manual de gcc doc:

débiles

El atributo débil hace que la statement 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 objectives ELF, y también para los objectives 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.