Compiling Linking Notes
File-Namen für Libraries
Library type | Linux | Windows |
---|---|---|
static | libfoobar.a | libfoobar.lib |
dynamic-link / shared | libfoobar.so.x.y.z, plus SymLinks | libfoobar.dll |
Welche Libraries verwendet ein Programm/eine Library?
Linux
% ldd foobar libgmodule-1.2.so.0 => libgmodule-1.2.so.0 (0x40142000) libglib-1.2.so.0 => libglib-1.2.so.0 (0x40145000) libdl.so.2 => /lib/libdl.so.2 (0x40176000) libXi.so.6 => /usr/X11R6/lib/libXi.so.6 (0x4017a000) libXext.so.6 => /usr/X11R6/lib/libXext.so.6 (0x40182000) libX11.so.6 => /usr/X11R6/lib/libX11.so.6 (0x40191000) libm.so.6 => /lib/libm.so.6 (0x4025f000) libc.so.6 => /lib/libc.so.6 (0x40281000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x80000000)
Windows
C:\> dumpbin /rawdata /section:.drectve foobar.obj >output.txt
Die Ausgabe in output.txt sieht dann z.B. so aus:
-default|lib:mfc4 0.lib -d|efaultli b:mfcs40|.lib -de faultlib|:msvcrt. lib -def|aultlib: kernel32|.lib -de faultlib|:user32. lib
Mac OS X
% otool -L foobar /sw/lib/libxml2.2.dylib (compatibility version 9.0.0, current version 9.20.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 88.2.1) /usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.3) /sw/lib/libiconv.2.dylib (compatibility version 6.0.0, current version 6.0.0) /usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0) /usr/lib/libmx.A.dylib (compatibility version 1.0.0, current version 92.0.0)
Welche Symbole stellt ein Programm/eine Library zur Verfügung?
ELF Files können mit readelf untersucht werden:
% readelf -s libfoobar.so.1
Symbol table '.symtab' contains 212 entries: Num: Value Size Type Bind Vis Ndx Name 1: 000018e0 0 FUNC LOCAL DEFAULT 10 xxx 2: 0000e7b0 0 OBJECT LOCAL DEFAULT 16 yyy 3: 0000e7b8 0 OBJECT LOCAL DEFAULT 17 zzz [...]
Für andere Objekt-Files kann nm verwendet werden (nm funktioniert auch für ELF):
% nm libfoobar.so.1 U xxx 00010fe8 W yyy 00068718 T zzz [...]
Wobei die Buchstaben-Codes folgende Bedeutung haben:
- U = Undefined. Library verwendet das Symbol, definiert es aber nicht
- W = Weak. Library definiert das Symbol, lässt aber zu, dass das Symbol anderswo neu definiert wird
- T = Text. Library definiert das Symbol im Text (= Code) Segment
- weitere Symbol-Typen sind möglich, siehe man nm
Kompilier-Vorgang unter Windows
- der Compiler erzeugt aus jedem .cpp File ein .obj File
- ein solches .obj File enthält
- Code
- Sections (vermutlich das gleiche wie "Segmente", also z.B. Daten-Segment, etc.)
- Linker-Direktiven
- externe Referenzen
- Funktions- und Daten-Namen
Link-Vorgang unter Windows
- es werden mehrere .obj Files zu einem .exe oder einer Library (.lib, .dll) zusammengefügt
- Alle in den .obj Files verwendeten Symbole müssen irgendwo definiert sein. Falls nicht in anderen .obj Files des gleichen Projekts, müssen sie in externen Libraries definiert sein. Diese Libraries müssen dem Linker angegeben werden. Folgende Libraries werden beim Linken verwendet:
- Libraries, die dem Linker explizit auf der cmdline mitgeteilt werden
- Libraries, die dem Linker mit /DEFAULTLIB mitgeteilt werden
- Default-Libraries, die in den .obj Files aufgeführt sind
- dazu muss man wissen, dass der Compiler in jedes .obj File Default-Libraries schreiben kann. Automatisch tut er dies mindestens für die C Run-Time Library. Siehe dazu KB 143072
- der Name der verwendeten C Run-Time Library hängt von der verwendeten /Mx Compiler Option ab. Im GUI von VC++ entspricht dies der Einstellung "Use Run-Time Library". Siehe dazu KB 128641. Weiter unten in diesem Topic findet sich eine Liste der möglichen Libraries.
- Default-Libraries (ob nun mit /DEFAULTLIB angegeben, oder bereits im .obj File einkompiliert) können mit /NODEFAULTLIB bzw. /NODEFAULTLIB:libfoobar übersteuert werden
Library-Namen unter Windows
C Run-Time Library
Reusable Library | Switch | Library | Macro(s) Defined |
---|---|---|---|
Single Threaded | /ML | LIBC | (none) |
Static MultiThread | /MT | LIBCMT | _MT |
Dynamic Link (DLL) | /MD | MSVCRT | _MT and _DLL |
Debug Single Threaded | /MLd | LIBCD | _DEBUG |
Debug Static MultiThread | /MTd | LIBCMTD | _DEBUG and _MT |
Debug Dynamic Link (DLL) | /MDd | MSVCRTD | _DEBUG, _MT, and _DLL |
Standard C++ Debug Library
Library | Description | Switch | Macro(s) Defined |
---|---|---|---|
LIBCPD.LIB | Single-threaded, static link | /MLd | _DEBUG |
LIBCPMTD.LIB | Multithreaded, static link | /MTd | _DEBUG, _MT |
MSVCPRTD.LIB | Multithreaded, dynamic link (import library for DLL) | /MDd | _DEBUG, _MT, _DLL |
LIBCP.LIB | Single threaded, static link | /ML | |
LIBCPMT.LIB | Multithreaded, static link | /MT | _MT |
MSVCPRT.LIB | Multithreaded, dynamic link (import library for DLL) | /MD | _MT, _DLL |
iostream Debug Library
Library | Description | Switch | Macro(s) Defined |
---|---|---|---|
LIBCID.LIB | Single threaded, static link | /MLd | _DEBUG |
LIBCIMTD.LIB | Multithreaded, static link | /MTd | _DEBUG, _MT |
MSVCIRTD.LIB | Multithreaded, dynamic link (import library for DLL) | /MDd | _DEBUG, _MT, _DLL |
LIBCI.LIB | Single threaded, static link | /ML | |
LIBCIMT.LIB | Multithreaded, static link | /MT | _MT |
MSVCIRT.LIB | Multithreaded, dynamic link (import library for DLL) | /MD | _MT, _DLL |
MFC Libraries
- nafxcwd.lib: ANSI Debug
- uafxcwd.lib: Unicode Debug
- nafxcw.lib: ANSI Release
- uafxcw.lib: Unicode Release
Libraries unter Windows
- eine .lib ist immer eine statische Library
- eine .dll besitzt immer eine zugehörige .lib. Diese .lib enthält Symbol-Informationen und wird von dem Programm dazugelinkt, das später die .dll verwenden will. Beim Linken wird - nebst den Informationen zu den Symbolen - der Programmcode erzeugt, mit dem die .dll zur Laufzeit geladen wird
- eine .lib, die explizit als statische Library gebildet wurde, und bei der mit VC++ 6.0 Debug Informationen mit der Option "Program Database" eingebunden wurden, enthält einen hart codierten Pfad auf ein File vc60.pdb (z.B. c:\foobar\debug\vc60.pdb). Falls diese statische Library auf andere Arbeitsplätze verteilt werden soll, und auf diesen Arbeitsplätzen gibt es das File vc60.pdb nicht (oder nicht an dem hart codierten Pfad), so tritt beim Linken ein Fehler auf (LNK1202). Das Problem kann vermieden werden, indem die statische Library mit der Einstellung "Debug Info = C7 compatible" kompiliert wird. In diesem Fall wird kein hart codierter Pfad als Verweis auf vc60.pdb in die Library ein-kompiliert.
Libraries unter Mac OS X
- Shared Libraries haben die Endung .dylib
- die Umgebungsvariable MACOSX_DEPLOYMENT_TARGET ist wichtig fuer den Linker ld und bestimmt im Wesentlichen den kleinsten gemeinsamen Nenner, fuer den die erzeugte Library lauffaehig sein soll (z.B. schaltet ldd Features aus, die es nur in 10.4 gibt, wenn die Umgebungsvariable auf <=10.3 gesetzt wird). Siehe man page von ld
- der Suchpfad fuer Libraries, die vom Runtime Linker dyld benoetigt werden, wird ueber die Umgebungsvariable DYLD_LIBRARY_PATH gesteuert
Debugging von Runtime Problemen unter Linux
Beim Starten eines Programms wird der Runtime Shared Library Loader (ld.so) aktiv. Er analysiert die Abhängigkeiten des zu startenden Programms, findet die benötigten Shared Libraries, lädt sie in den Speicher, nimmt allfällige Anpassungen am Programm und an den Libraries vor (z.B. Relocation), und startet schlussendlich das Programm.
Die Pfade, in denen ld.so nach Shared Libraries sucht, wird mit der Umgebungsvariablen LD_LIBRARY_PATH beeinflusst (DYLD_LIBRARY_PATH unter Mac OS X).
Die Arbeit von ld.so kann durch weitere Umgebungsvariablen beeinflusst werden. Siehe dazu "man ld.so". Um die Arbeit von ld.so zu beobachten, sind die folgenden Variablen interessant:
- LD_DEBUG: je nachdem, welchen Wert diese Variable enthält, gibt ld.so verschiedene Arten von Informationen aus. Achtung: die Ausgabe erfolgt auf stdout! Meistens macht es Sinn, die Ausgabe in eine Datei schreiben zu lassen. Siehe LD_DEBUG_OUTPUT
- all: gibt alle Debug Informationen aus, die ld.so überhaupt beherrscht
- libs: zeigt die "library search paths" an, d.h. wo ld.so überall nach einem bestimmten Shared Library File sucht
- help: gibt aus, auf welche Werte LD_DEBUG gesetzt werden kann
- LD_DEBUG_OUTPUT: diese Variable enthält einen Filenamen. Die durch LD_DEBUG ausgelöste Ausgabe wird in dieses File geschrieben