windows 如何告诉 MinGW 链接器不要导出所有符号?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2810118/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to tell the MinGW linker not to export all symbols?
提问by James R.
I'm building a Windows dynamic library using the MinGW toolchain.
我正在使用 MinGW 工具链构建 Windows 动态库。
To build this library I'm statically linking to other 2 which offer an API and I have a .def
file where I wrote the only symbol I want to be exported in my library.
为了构建这个库,我静态链接到提供 API 的其他 2 个库,并且我有一个.def
文件,我在其中编写了我想在库中导出的唯一符号。
The problem is that GCC is exporting all of the symbols including the ones from the libraries I'm linking to. Is there anyway to tell the linker just to export the symbols in the def
file?
问题是 GCC 正在导出所有符号,包括我链接到的库中的符号。有没有告诉链接器只是导出def
文件中的符号?
I know there is the option --export-all-symbols
but there seems not to be the opposite to it.
我知道有这个选择,--export-all-symbols
但似乎没有相反的选择。
Right now the last line of the build script has this structure:
现在构建脚本的最后一行具有以下结构:
g++ -shared CXXFLAGS DEFINES INCLUDES -o library.dll library.cpp DEF_FILE \
OBJECT_FILES LIBS -Wl,--enable-stdcall-fixup
EDIT: In the docsabout the linker it says that --export-all-symbols
is the default behavior and that it's disabled when you don't use that option explicitly if you provide a def
file, except when it doesn't; the symbols in 3rd party libs are being exported anyway.
编辑:在有关链接器的文档中,它说这--export-all-symbols
是默认行为,并且如果您提供def
文件,则不明确使用该选项时它被禁用,除非它没有;无论如何,第 3 方库中的符号都会被导出。
EDIT: Adding the option --exclude-libs LIBS
or –exclude-symbols SYMBOLS
doesn't prevent the symbols from the libraries from being exported.
编辑:添加选项--exclude-libs LIBS
或–exclude-symbols SYMBOLS
不会阻止导出库中的符号。
采纳答案by Xandy
You can use dllwrap if your distribution of binutils (either native or cross compiling) provides it.
如果您的 binutils 发行版(本机或交叉编译)提供了 dllwrap,您可以使用它。
It can produce DLLs using the interface in a DEF file (under the hood it calls gcc, ld and dlltool to do so). The difference between using this and passing a DEF file to GCC directly is that the definitions in the file are treated differently.
它可以使用 DEF 文件中的接口生成 DLL(在后台它调用 gcc、ld 和 dlltool 来执行此操作)。使用它和直接将 DEF 文件传递给 GCC 的区别在于文件中的定义被不同地对待。
For example, if you have a symbol rename in the export file:
例如,如果您在导出文件中有一个符号重命名:
_SomeFuntion = _SomeFunction@12
GCC will create 2 exports, one by the name of _SomeFunction
and the other one with the decorated name while dllwrap will only export _SomeFuntion
. So if you only add to the DEF file the symbols you want to be exported you will end up only with them in the library.
GCC 将创建 2 个导出,一个是名称,_SomeFunction
另一个是修饰名称,而 dllwrap 只会导出_SomeFuntion
. 因此,如果您只将要导出的符号添加到 DEF 文件中,那么您最终只会在库中使用它们。
dllwrap by default uses the C compiler driver since it has no way of knowing otherwise. As you're linking C++ code, you have to use the option --driver-name c++
to set the driver. If you happen to have the MinGW executables with a prefix you have to include it too in the driver name (e.g. i686-mingw32-c++
instead of c++
) and you may need to use the option --dlltool-name
too.
dllwrap 默认使用 C 编译器驱动程序,因为它无法知道其他情况。当您链接 C++ 代码时,您必须使用该选项--driver-name c++
来设置驱动程序。如果您碰巧有带有前缀的 MinGW 可执行文件,您也必须将它包含在驱动程序名称中(例如,i686-mingw32-c++
而不是c++
),并且您可能也需要使用该选项--dlltool-name
。
Try using these two lines instead of the one you posted:
尝试使用这两行而不是您发布的那一行:
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
The first one generates an object file from the code of library.cpp
and the second one assembles the dynamic library. The OBJECT_FILES
thing (which I assume to be other object files you generated previously) should have library.o
there too.
第一个从代码生成目标文件,library.cpp
第二个汇编动态库。这个OBJECT_FILES
东西(我假设是你之前生成的其他目标文件)也应该在library.o
那里。
That said, I have to tell you dllwrap was already deprecatedin 2006 and there is no documentation on it in the official binutils package; to get some info you may call it with --help
as usual. It can generate an import library in case you need it too.
也就是说,我必须告诉你 dllwrap 已经在 2006 年被弃用,并且官方 binutils 包中没有关于它的文档;要获取一些信息,您可以--help
像往常一样调用它。如果您也需要它,它可以生成一个导入库。
回答by antonone
Not sure why there's no real answer to this, but here's what worked for me:
不知道为什么没有真正的答案,但这对我有用:
Compilation of your object files:
g++ -O0 -gdwarf-4 dll\dllmain.cpp -c -o dllmain.o
Linking (
-Wl,--exclude-all-symbols
is important):g++ -Wl,--enable-auto-import -Wl,--out-implib,libsomelib.a -Wl,--exclude-all-symbols -shared dllmain.o -o somelib.dll
编译目标文件:
g++ -O0 -gdwarf-4 dll\dllmain.cpp -c -o dllmain.o
链接(
-Wl,--exclude-all-symbols
很重要):g++ -Wl,--enable-auto-import -Wl,--out-implib,libsomelib.a -Wl,--exclude-all-symbols -shared dllmain.o -o somelib.dll
Then you choose which functions to export directly in source code of your DLL:
然后您选择直接在 DLL 的源代码中导出哪些函数:
#include <windows.h>
__declspec(dllexport) void someExportedFunction() {
MessageBox(NULL, "msgbox", "msgbox", MB_OK);
}
void nonExportedFunction() {
MessageBox(NULL, "notexported", "notexported", MB_OK);
}
Verification:
确认:
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)
( pedump
= http://pedump.me)
回答by dsign
This is a recurrent issue. Here are two related questions in SO:
这是一个反复出现的问题。以下是 SO 中的两个相关问题:
- Removing exported symbols from a DLL and its associated import library (VS8)
- https://stackoverflow.com/questions/9586262/how-to-know-exported-symbols-for-windows-dll-from-linux-mingw/9600759#9600759(DEAD)
- 从 DLL 及其关联的导入库 (VS8) 中删除导出的符号
- https://stackoverflow.com/questions/9586262/how-to-know-exported-symbols-for-windows-dll-from-linux-mingw/9600759#9600759(死)
and outside SO:
和外面SO:
- http://boost.2283326.n4.nabble.com/unwanted-exported-symbols-in-a-DLL-which-statically-links-to-Boost-Library-td2590169.html
- http://sourceforge.net/p/mingw/bugs/1134/
- http://boost.2283326.n4.nabble.com/unwanted-exported-symbols-in-a-DLL-which-statically-links-to-Boost-Library-td2590169.html
- http://sourceforge.net/p/mingw/bugs/1134/
i.e. global / local exporting on the Windows platform is not handled at the linker level but but the provision of a .def
file to complement the .dll
.
即 Windows 平台上的全局/本地导出不是在链接器级别处理的,而是提供一个.def
文件来补充.dll
.
Lacking a good answer, I did a python script that takes care of removing stuff from the dll export table, you can find it here.
缺乏一个好的答案,我做了一个 python 脚本,负责从 dll 导出表中删除内容,你可以在这里找到它。
回答by dsign
Did you read this on the page you supplied alink to, regarding behaviour if --export-all-symbols is not used explicitly - auto export is disabled if:
您是否在提供链接的页面上阅读了此内容,关于未明确使用 --export-all-symbols 时的行为 - 在以下情况下禁用自动导出:
Any symbol in any object file was marked with the __declspec(dllexport) attribute.
任何目标文件中的任何符号都标有 __declspec(dllexport) 属性。
Have you tried explicitly exporting only the functions you are interested in? It's very easy to get names wrong in DEF file, because of mangling, so this method should be more reliable.
您是否尝试过仅显式导出您感兴趣的功能?DEF 文件中很容易出现名称错误,因为 mangling,所以这种方法应该更可靠。
回答by Chris Dodd
You can use the option -Wl,--retain-symbols-file=file
and then list the symbols you want to keep (one per line) in file
. This will cause the linker to discard all other symbols, keeping just the ones you want.
您可以使用该选项-Wl,--retain-symbols-file=file
,然后列出要保留的符号(每行一个)file
。这将导致链接器丢弃所有其他符号,只保留您想要的符号。
回答by janneb
Disclaimer: I've only done this on Linux, but AFAIK it should work on Windows as well
免责声明:我只在 Linux 上做过这个,但 AFAIK 它也应该在 Windows 上工作
You can use the -fvisibility=hidden
option; for more info see http://gcc.gnu.org/wiki/Visibility
您可以使用该-fvisibility=hidden
选项;有关更多信息,请参阅http://gcc.gnu.org/wiki/Visibility