2010-05-11 16 views
13

Estoy construyendo una biblioteca dinámica de Windows usando la cadena de herramientas MinGW.¿Cómo decirle al enlazador MinGW que no exporte todos los símbolos?

Para construir esta biblioteca estoy vinculando estáticamente a otros 2 que ofrecen una API y tengo un archivo .def donde escribí el único símbolo que deseo exportar en mi biblioteca.

El problema es que GCC está exportando todos los símbolos, incluidos los de las bibliotecas a las que estoy vinculando. ¿Hay alguna forma de decirle al vinculador que solo exporte los símbolos en el archivo def?

Sé que existe la opción --export-all-symbols pero parece que no es lo contrario.

En este momento la última línea de la escritura de la estructura tiene esta estructura:

g++ -shared CXXFLAGS DEFINES INCLUDES -o library.dll library.cpp DEF_FILE \ 
OBJECT_FILES LIBS -Wl,--enable-stdcall-fixup 

EDIT: En el docs sobre el enlazador se dice que --export-all-symbols es el comportamiento predeterminado y que es desactivada cuando no se utiliza esa opción explícitamente si proporciona un archivo def, excepto cuando no lo haga; los símbolos en libs de terceros se exportan de todos modos.

EDITAR: Agregar la opción --exclude-libs LIBS o –exclude-symbols SYMBOLS no impide que se exporten los símbolos de las bibliotecas.

Respuesta

1

Puede usar dllwrap si su distribución de binutils (ya sea nativo o compilación cruzada) lo proporciona.

Puede producir archivos DLL utilizando la interfaz en un archivo DEF (bajo el capó llama a gcc, ld y dlltool para hacerlo). La diferencia entre usar esto y pasar un archivo DEF a GCC directamente es que las definiciones en el archivo se tratan de manera diferente.

Por ejemplo, si tiene un símbolo de cambio de nombre en el archivo de exportación:

_SomeFuntion = [email protected] 

GCC creará 2 exportaciones, uno por el nombre de _SomeFunction y el otro con el nombre decorado mientras dllwrap sólo se exportará _SomeFuntion. De modo que si solo agrega al archivo DEF los símbolos que desea exportar, terminará solo con ellos en la biblioteca.

dllwrap utiliza de forma predeterminada el controlador del compilador C, ya que no tiene forma de saber lo contrario.Al vincular el código C++, debe usar la opción --driver-name c++ para configurar el controlador. Si tiene los ejecutables MinGW con un prefijo, debe incluirlo también en el nombre del controlador (por ejemplo, i686-mingw32-c++ en lugar de c++) y es posible que necesite utilizar también la opción --dlltool-name.

Trate de usar estas dos líneas en lugar de la que usted envió:

g++ -c CXXFLAGS DEFINES INCLUDES -o library.o library.cpp 
dllwrap -o library.dll --driver-name c++ --def DEF_FILE OBJECT_FILES LIBS -Wl,--enable-stdcall-fixup 

El primero genera un fichero objeto a partir del código de library.cpp y el segundo reúne la biblioteca dinámica. La cosa OBJECT_FILES (que supongo que es otros archivos objeto que generó anteriormente) debe tener library.o allí también.

Dicho esto, tengo que decirte que dllwrap ya era deprecated en 2006 y que no hay documentación en el paquete binutils oficial; para obtener información, puede llamarla con --help como de costumbre. Puede generar una biblioteca de importación en caso de que la necesite también.

+0

¡Gracias por tu respuesta! Funciona, a menos que los símbolos se especifiquen en el archivo 'def' no se exportan, incluso los de las bibliotecas. Usaré dllwrap, estoy usando binutils 2.20 y dllwrap todavía está allí así que tal vez todavía se mantenga. Si está obsoleto ... ¿No debería haber una forma de hacer lo mismo usando solo gcc y cia? –

+0

@James, la forma preferida es marcar los símbolos en la fuente con 'dllexport/dllimport' y tener la visibilidad del símbolo manejada de esa manera. – rubenvb

0

responsabilidad: Sólo he hecho esto en Linux, pero que yo sepa que debería funcionar en Windows, así

Usted puede utilizar la opción -fvisibility=hidden; Para más información ver http://gcc.gnu.org/wiki/Visibility

+2

Me temo que no ayuda en un entorno de Windows (al menos con mi compilador). Obtengo "advertencias de atributo de visibilidad no admitidas en esta configuración", incluso "ignoradas" en una prueba Foo, ¡pero gracias de todos modos! –

1

¿Ha leído esto en la página que ha proporcionado a alink, con respecto al comportamiento si --export-all-símbolos no se utiliza de forma explícita - exportación automática se desactiva si:

Cualquier símbolo en cualquier archivo de objeto era marcado con el atributo __declspec (dllexport) .

¿Ha intentado exportar explícitamente solo las funciones que le interesan? Es muy fácil obtener nombres incorrectos en el archivo DEF, debido a la modificación, por lo que este método debería ser más confiable.

+0

He marcado así los símbolos que deseo que se exporten, y lo son, pero no puedo acceder a las fuentes de las bibliotecas a las que me estoy vinculando. No puedo quitar esa marca de allí. –

+0

@James No me puedo llevar la exportación una vez que se ha hecho, me temo. –

+0

Aha, gracias, entonces los símbolos exportados por otras bibliotecas deben permanecer. –

1

Puede usar la opción -Wl,--retain-symbols-file=file y luego enumerar los símbolos que desea conservar (uno por línea) en file. Esto hará que el vinculador descarte todos los demás símbolos, manteniendo solo los que desee.

+0

¿Dónde están los documentos para --retain-symbols-file? – paulm

+0

@paulm: en [documentos para GNU ld] (https://sourceware.org/binutils/docs/ld/Options.html#Options) –

2

Este es un problema recurrente. Aquí hay dos preguntas relacionadas en SO:

y fuera SO:

es decir, la exportación global/local en la plataforma de Windows no se maneja en el nivel del enlazador, sino en la provisión de un archivo .def para complementar el .dll.

A falta de una buena respuesta, hice una secuencia de comandos python que se encarga de eliminar elementos de la tabla de exportación dll, puede encontrarlo here.

3
No

seguro de por qué no hay una respuesta real a esta, pero aquí es lo que funcionó para mí:

  1. Compilación de los archivos de objetos:

    g++ -O0 -gdwarf-4 dll\dllmain.cpp -c -o dllmain.o 
    
  2. Vinculación (-Wl,--exclude-all-symbols es importante):

    g++ -Wl,--enable-auto-import -Wl,--out-implib,libsomelib.a -Wl,--exclude-all-symbols -shared dllmain.o -o somelib.dll 
    

A continuación, elegir qué funciones para exportar directamente en el código fuente de la DLL:

#include <windows.h> 

__declspec(dllexport) void someExportedFunction() { 
    MessageBox(NULL, "msgbox", "msgbox", MB_OK); 
} 

void nonExportedFunction() { 
    MessageBox(NULL, "notexported", "notexported", MB_OK); 
} 

Verificación:

C:\libtest>pedump -E somelib.dll 

=== EXPORTS === 

# module "somelib.dll" 
# flags=0x0 ts="2014-02-20 08:37:48" version=0.0 ord_base=1 
# nFuncs=1 nNames=1 

    ORD ENTRY_VA NAME 
    1  1570 _Z20someExportedFunctionv 

(pedump = http://pedump.me)

Cuestiones relacionadas