Pregunta

Tengo un proyecto de biblioteca compartida que se construye a partir de 4 bibliotecas estáticas (.a) y un archivo de objeto (.o). Estoy tratando de añadir la opción -fvisibility=hidden para restringir símbolos en la salida a sólo aquellos que me marca en la fuente con un __attribute __.

He añadido la opción -fvisibility=hidden a las opciones de compilació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 espera de la .so final. Sin embargo, los símbolos de los proyectos .a están todavía en el archivo .so final. Añadiendo la opción -fvisibility=hidden al comando de enlazado .so no tiene ningún efecto.

¿Qué estoy haciendo mal?

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

EDIT: En realidad he usado una versión mapa para resolver esto para ahora. Sin embargo, requiere un mantenimiento continuo de la escritura de la versión a medida que cambian los símbolos externos. respuesta aceptada tiene una idea mejor.

¿Fue útil?

Solución

Básicamente, la visibilidad es manejado durante el enlace, y no parece que el enlazador imponerla a los archivos estáticos. Una cuestión relacionada (aunque no es un duplicado) se le preguntó sobre href="https://stackoverflow.com/questions/1601900"> SO .

Lo que yo aconsejo que hacer 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 vuelvas los archivos de objetos:

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

Otros consejos

Basta con pasar a -Wl,--exclude-libs,ALL gcc

Esto indicará al enlazador para transformar todos los símbolos en las librerías estáticas a escondidas.

--exclude-libs también acepta una lista de archivos (es decir, nombres de biblioteca estática) para granularidad más fina en la que las bibliotecas para ocultar los símbolos de.

Nota: esto sólo funcionará en sistemas que utilicen binutils de GNU (por ejemplo, Linux) o con un enlazador de soporte --exclude-libs (por ejemplo, no va a funcionar con ld64 de OSX)

Esta es una respuesta al problema de OS X.

El ld Mac no soporta --exclude-libs, pero apoya -exported_symbol sym y hace aplicar esto a los ficheros objeto en bibliotecas estáticas. Y cuando se está filtrando a una API pública, la lista blanca es suficientemente pequeño como para explicarla.

que terminó con la siguiente en mi Makefile para generar una bandera -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)

A continuación, se puede hacer si-puerta entre esta versión de las banderas y la versión de GNU ld después de detectar la cual el sistema tiene enlazador.

scroll top