¿Cómo aplicar la opción de visibilidad a los símbolos en las bibliotecas estáticas?

Tengo un proyecto de biblioteca compartida que se genera a partir de 4 bibliotecas estáticas ( .a ) y un archivo de objetos ( .o ). Estoy intentando agregar la opción -fvisibility=hidden para restringir los símbolos en la salida a solo aquellos que marque en la fuente con un __attribute__.

He agregado la opción -fvisibility=hidden a las opciones de comstackción para el proyecto .so (que cubre el archivo .o ) y para los proyectos .a .

Los símbolos en el archivo de objeto se eliminan como se esperaba de .so final. Sin embargo, los símbolos de los proyectos .a todavía están en el archivo .so final. Agregar la opción -fvisibility=hidden al comando .so link no tiene ningún efecto.

¿Qué estoy haciendo mal?

Mi propósito aquí es eliminar del .so todos los símbolos excepto las funciones de interfaz a la biblioteca.

EDITAR: en realidad usé un mapa de versión para resolver esto por ahora. Sin embargo, requiere un mantenimiento continuo del script de versión a medida que cambian los símbolos externos. La respuesta aceptada tiene una mejor idea.

Básicamente, la visibilidad se maneja durante la vinculación, y el vinculador no parece imponerlo en los archivos estáticos. Una pregunta relacionada (aunque no un duplicado) fue solicitada en SO aquí .

Lo que le aconsejo que haga es reemplazar su etapa de vinculación: gcc -shared -o mylib.so foo.o libbar.a en un proceso de dos etapas en el que recupera los archivos del objeto:

  • ar x libbar.a (posiblemente en un directorio adecuado, vacío)
  • gcc -fvisibility=hidden -shared -o mylib.so foo.o tempdir/*.o

Simplemente pase -Wl,--exclude-libs,ALL a gcc

Esto le indicará al vinculador que transforme todos los símbolos en las bibliotecas estáticas en ocultos.

--exclude-libs también acepta una lista de archivos (es decir, nombres de bibliotecas estáticas) para una granularidad más precisa de las bibliotecas para ocultar símbolos.

Nota: esto solo funcionará en sistemas que utilicen binutils de GNU (p. Ej., Linux) o con un enlazador que admita –exclude --exclude-libs (p. Ej., No funcionará con ld64 de OSX)

Esta es una respuesta al problema para OS X.

Mac ld no es compatible con --exclude-libs , pero sí admite -exported_symbol sym y lo aplica a archivos de objetos en bibliotecas estáticas. Y cuando se está filtrando a una API pública, la lista blanca es lo suficientemente pequeña para deletrearla.

Terminé con lo siguiente en mi Makefile para generar un -Wl,-exported_symbol,_api_func_1 para cada símbolo exportado:

 SYMBOLS = api_func_1 api_func_2 api_func_3 api_func_4 SYMBOLS += api_func_5 # add more as necessary COMMA = , LDFLAGS += $(addprefix -Wl$(COMMA)-exported_symbol$(COMMA)_,$(SYMBOLS)) # ... libmyapi.so: # ... $(CC) -shared -o $@ ... $(LDFLAGS) 

Luego puede hacer una compuerta entre esta versión de los indicadores y la versión GNU ld después de detectar qué enlazador tiene el sistema.