[英]How to tell the MinGW linker not to export all symbols?
我正在使用MinGW工具鏈構建一個Windows動態庫。
為了構建這個庫,我靜態地鏈接到提供API的其他2,我有一個.def
文件,在那里我寫了我想要在我的庫中導出的唯一符號。
問題是GCC正在導出所有符號,包括我鏈接到的庫中的符號。 反正告訴鏈接器只是導出def
文件中的符號?
我知道有選項--export-all-symbols
但似乎沒有相反的選擇。
現在,構建腳本的最后一行具有以下結構:
g++ -shared CXXFLAGS DEFINES INCLUDES -o library.dll library.cpp DEF_FILE \
OBJECT_FILES LIBS -Wl,--enable-stdcall-fixup
編輯:在關於鏈接器的文檔中 ,它表示--export-all-symbols
是默認行為,並且如果你提供def
文件時沒有明確地使用該選項它被禁用,除非它沒有; 無論如何,第三方庫中的符號正在導出。
編輯:添加選項--exclude-libs LIBS
或–exclude-symbols SYMBOLS
不會阻止導出庫中的符號。
不知道為什么沒有真正的答案,但這對我有用:
編譯目標文件:
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
然后,您可以選擇在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文件中輸入名稱很容易,因為變形,所以這種方法應該更可靠。
如果您的binutils(本機或交叉編譯)的分發提供它,您可以使用dllwrap。
它可以使用DEF文件中的接口生成DLL(在它下面調用gcc,ld和dlltool)。 使用它和直接將DEF文件傳遞給GCC之間的區別在於文件中的定義被區別對待。
例如,如果導出文件中有符號重命名:
_SomeFuntion = _SomeFunction@12
GCC將創建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
調用它。 它可以生成導入庫,以備您需要時使用。
您可以使用選項-Wl,--retain-symbols-file=file
,然后列出你想保持(每行一個)中的符號file
。 這將導致鏈接器丟棄所有其他符號,只保留您想要的符號。
免責聲明:我只在Linux上完成此操作,但AFAIK也適用於Windows
您可以使用-fvisibility=hidden
選項; 有關更多信息,請參閱http://gcc.gnu.org/wiki/Visibility
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.