如何告诉MinGW链接器不要导出所有符号?

我正在使用MinGW工具链构buildWindowsdynamic库。

要build立这个库,我静态地链接到其他2提供了一个API,我有一个.def文件,我写了唯一的符号,我想在我的图书馆出口。

问题是GCC正在导出所有的符号,包括我链接的库中的符号。 是否有告诉链接器只是导出def文件中的符号?

我知道有选项--export-all-symbols但似乎没有相反的意思。

现在构build脚本的最后一行有这样的结构:

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

编辑:在关于链接器的文档中 ,它表示--export-all-symbols是默认行为,当你不提供def文件时,如果你不提供def文件,它将被禁用。 无论如何,第三方库中的符号都被导出。

编辑:添加选项--exclude-libs LIBS–exclude-symbols SYMBOLS不会阻止导出库中的符号。

Solutions Collecting From Web of "如何告诉MinGW链接器不要导出所有符号?"

如果您的binutils(本地编译或交叉编译)提供了它,您可以使用dllwrap。

它可以使用DEF文件中的接口来生成DLL(在这种情况下,它调用gcc,ld和dlltool来执行此操作)。 使用这个和将DEF文件直接传递给GCC的区别在于文件中的定义被区别对待。

例如,如果在导出文件中有一个符号重命名:

 _SomeFuntion = _SomeFunction@12 

海湾合作委员会将创建2出口,一个由_SomeFunction名称和另一个与装饰名称,而dllwrap将只会导出_SomeFuntion 。 所以,如果你只添加到DEF文件中,你想要导出的符号将只在库中与它们结束。

dllwrap默认使用C编译器驱动程序,因为它无法知道其他情况。 在链接C ++代码时,必须使用选项--driver-name c++来设置驱动程序。 如果你碰巧拥有带有前缀的MinGW可执行文件,你也必须在驱动程序名称中包含它(例如i686-mingw32-c++而不是c++ ),而且你也可能需要使用选项--dlltool-name

尝试使用这两行代替您发布的代码:

 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 

第一个从library.cpp的代码生成一个目标文件,第二个组装动态库。 OBJECT_FILES东西(我认为是以前生成的其他对象文件)应该有library.o

也就是说,我必须告诉你,dllwrap在2006年已经被弃用了,官方的binutils包里没有任何文档。 得到一些信息,你可以像平常一样用--help来调用它。 它可以生成一个导入库,以防您也需要它。

不知道为什么没有真正的答案,但这是对我有用:

  1. 汇编你的目标文件

     g++ -O0 -gdwarf-4 dll\dllmain.cpp -c -o dllmain.o 
  2. 链接( -Wl,--exclude-all-symbols很重要):

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

然后,您可以选择在DLL的源代码中直接导出哪些函数:

 #include <windows.h> __declspec(dllexport) void someExportedFunction() { MessageBox(NULL, "msgbox", "msgbox", MB_OK); } void nonExportedFunction() { MessageBox(NULL, "notexported", "notexported", MB_OK); } 

验证:

 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

这是一个经常性的问题。 SO中有两个相关的问题:

和外面SO:

即Windows平台上的全局/本地导出不是在链接器级别处理,而是提供.def文件以补充.dll

缺乏一个好的答案,我做了一个python脚本,照顾从DLL导出表中删除的东西,你可以在这里找到它。

您是否在您提供链接的页面上阅读了此内容,如果–export-all-symbols没有明确使用,则关于行为 – 在以下情况下自动导出被禁用:

任何对象文件中的任何符号都标有__declspec(dllexport)属性。

你有没有尝试明确地只导出你感兴趣的功能? 在DEF文件中弄错名称是很容易的,因为这个方法比较可靠。

您可以使用选项-Wl,--retain-symbols-file=file ,然后在-Wl,--retain-symbols-file=file列出要保留的符号(每行一个)。 这将导致链接器放弃所有其他符号,只保留你想要的。

免责声明:我只在Linux上这样做,但AFAIK它也应该在Windows上工作

您可以使用-fvisibility=hidden选项; 有关更多信息,请参阅http://gcc.gnu.org/wiki/Visibility