2010-05-11 9 views
13

Ich baue eine Windows dynamische Bibliothek mit der MinGW Toolchain.Wie kann ich dem MinGW-Linker mitteilen, dass er nicht alle Symbole exportieren soll?

Um diese Bibliothek zu erstellen, bin ich statisch mit anderen 2 verbunden, die eine API anbieten, und ich habe eine .def Datei, wo ich das einzige Symbol geschrieben habe, das ich in meine Bibliothek exportieren möchte.

Das Problem ist, dass GCC alle Symbole einschließlich der aus den Bibliotheken exportiert, die ich verlinke. Gibt es sowieso, dem Linker zu sagen, nur die Symbole in der def Datei zu exportieren?

Ich weiß, es gibt die Option --export-all-symbols, aber es scheint nicht das Gegenteil zu sein.

Im Augenblick ist die letzte Zeile des Build-Skript hat diese Struktur:

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

EDIT: Im docs über den Linker heißt es, dass --export-all-symbols das Standardverhalten ist, und dass es deaktiviert, wenn Sie nicht verwenden diese Option explizit, wenn Sie eine def Datei bereitstellen, außer wenn dies nicht der Fall ist; Die Symbole in 3rd-Party-Bibliotheken werden trotzdem exportiert.

EDIT: Das Hinzufügen der Option --exclude-libs LIBS oder –exclude-symbols SYMBOLS verhindert nicht, dass die Symbole aus den Bibliotheken exportiert werden.

Antwort

1

Sie können dllwrap verwenden, wenn Ihre Verteilung von binutils (entweder nativ oder Cross Compiling) es bereitstellt.

Es kann DLLs unter Verwendung der Schnittstelle in einer DEF-Datei erzeugen (unter der Haube ruft es dazu gcc, ld und dlltool auf). Der Unterschied zwischen der Verwendung dieser Funktion und der direkten Übergabe einer DEF-Datei an GCC besteht darin, dass die Definitionen in der Datei unterschiedlich behandelt werden.

Zum Beispiel, wenn Sie ein Symbol in der Exportdatei umbenennen:

_SomeFuntion = [email protected] 

GCC 2 Exporte, ein unter dem Namen _SomeFunction erstellen und das andere mit dem ergänzten Namen während dllwrap wird nur Export _SomeFuntion. Wenn Sie also nur die zu exportierenden Symbole zur DEF-Datei hinzufügen, landen Sie nur in der Bibliothek.

dllwrap verwendet standardmäßig den C-Compiler-Treiber, da es keine Möglichkeit hat, etwas anderes zu wissen.Wenn Sie C++ - Code verknüpfen, müssen Sie die Option --driver-name c++ verwenden, um den Treiber festzulegen. Wenn Sie die ausführbaren MinGW-Dateien mit einem Präfix haben, müssen Sie sie ebenfalls in den Treibernamen aufnehmen (z. B. i686-mingw32-c++ anstelle von c++), und Sie müssen möglicherweise auch die Option --dlltool-name verwenden.

versuchen, diese zwei Linien statt der Sie auf dem Laufenden mit:

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 

Die erste erzeugt eine Objektdatei aus dem Code von library.cpp und die zweite assembliert die dynamische Bibliothek. Die OBJECT_FILES Sache (von der ich annahm, dass sie andere Objektdateien sind, die Sie vorher erzeugten) sollte library.o dort auch haben.

Das sagte, ich muss Ihnen sagen, dllwrap war bereits deprecated in 2006 und es gibt keine Dokumentation darüber im offiziellen binutils Paket; um Informationen zu erhalten, können Sie es wie gewohnt mit --help anrufen. Es kann eine Importbibliothek erzeugen, falls Sie diese auch benötigen.

+0

Vielen Dank für Ihre Antwort! Es funktioniert, wenn die Symbole nicht in der 'def'-Datei angegeben sind, werden sie nicht exportiert, auch die aus den Bibliotheken. Ich werde dllwrap verwenden, ich bin binutils 2.20 und dllwrap ist immer noch da, vielleicht ist es immer noch gepflegt. Wenn es veraltet ist ... sollte es nicht einen Weg geben, dasselbe mit gcc und cia zu machen? –

+0

@James Der bevorzugte Weg besteht darin, die Symbole in der Quelle mit 'dllexport/dllimport' zu markieren und die Symbolsichtbarkeit so zu behandeln. – rubenvb

0

Haftungsausschluss: Ich habe dies auf Linux nur getan, aber AFAIK sollte es unter Windows arbeiten und

Sie die -fvisibility=hidden Option verwenden können; Für weitere Informationen siehe http://gcc.gnu.org/wiki/Visibility

+2

Ich fürchte, es nicht hilft in einer Windows-Umgebung (zumindest mit meinem Compiler). Ich bekomme "Sichtbarkeitsattribut nicht unterstützt in dieser Konfiguration; ignorierte" Warnungen sogar in einem foo Test, aber danke trotzdem! –

1

Haben Sie diese Zeilen lesen auf der Seite, die Sie alink zugeführt, in Bezug auf Verhalten, wenn --export-all-Symbole nicht explizit verwendet wird - auto Export ist deaktiviert, wenn:

Alle Symbole in jeder Objektdatei wurde mit dem __declspec (dllexport) Attribut markiert.

Haben Sie versucht, explizit nur die Funktionen zu exportieren, an denen Sie interessiert sind? Es ist sehr einfach, Namen in der DEF-Datei wegen Mangelns zu bekommen, daher sollte diese Methode zuverlässiger sein.

+0

Ich habe so die Symbole markiert, die ich exportieren möchte, und sie sind es, aber ich kann nicht auf die Quellen der Bibliotheken zugreifen, mit denen ich verlinke. Ich kann diese Markierung nicht von dort wegnehmen. –

+0

@James Sie können nicht exportieren exportieren, sobald es getan wurde, fürchte ich. –

+0

Aha, danke dann, also müssen die von anderen Bibliotheken exportierten Symbole bleiben. –

1

Sie können die Option -Wl,--retain-symbols-file=file verwenden und dann die Symbole auflisten, die Sie behalten möchten (eins pro Zeile) in file. Das wird den Linker veranlassen, alle anderen Symbole zu verwerfen, nur die gewünschten zu behalten.

+0

Wo sind die Dokumente für --retain-symbols-Datei? – paulm

+0

@paulm: In der [Dokumentation für GNU ld] (https://sourceware.org/binutils/docs/ld/Options.html#Options) –

2

Dies ist ein wiederkehrendes Problem. Hier sind zwei miteinander verbundene Fragen in SO:

und außerhalb SO:

d. H. Der globale/lokale Export auf der Windows-Plattform wird nicht auf der Linker-Ebene gehandhabt, aber die Bereitstellung einer .def-Datei zur Ergänzung der .dll.

Fehlende eine gute Antwort, habe ich ein Python-Skript, das kümmert sich um das Entfernen von Sachen aus der DLL-Export-Tabelle, können Sie es finden here.

3

nicht sicher, warum gibt es keine wirkliche Antwort auf diese, aber hier ist was für mich gearbeitet:

  1. Kompilation Ihrer Objektdateien:

    g++ -O0 -gdwarf-4 dll\dllmain.cpp -c -o dllmain.o 
    
  2. Linking (-Wl,--exclude-all-symbols ist wichtig):

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

Dann wählen Sie Funktionen, die direkt im Quellcode der DLL zu exportieren:

#include <windows.h> 

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

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

Überprüfung:

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)

Verwandte Themen