Merge commit 'origin/master' into msys
[msysgit.git] / mingw / doc / a2dll / static2dll_howto.txt
blobc74883a8f6bedd0d97dad91a85b02b3084e54c62
1 How to build Win32 Dynamic-Loading Library (DLL) from existing static library
2 -----------------------------------------------------------------------------
4 -------
5 NOTE: To perform steps below, you'll need contemparary dlltool, for
6 example from Mumit Khan's gcc-2.95.2 packages.
7 -------
10 This document describes step-by-step procedure of building Win32 DLL from
11 static library. It suitable for both your own and third-party (i.e. ones
12 which you know, and would like to, little about) libs. However, for your
13 own libraries you may adopt more handy and adequate method (exporting all
14 symbols, as done here, may be not the best solution). However, procedure
15 given here describes easiest and fastest way if what you want is just
16 create proper DLL and forget about it. This documets assumes that
17 you have, or will, read documentation for Mumit Khan's dllwrappers
18 tools (dllwrap & dlltool utilities).
20 Before proceeding with description of process, some notes about
21 distinction of DLLs and usual *nix-style shared libraries (.so, referred
22 as SO below) (read also if you don't have experience with .so):
24 [Once again note that there's a big gap between abstract information
25 below and specific practical steps which follow; if you want to fill
26 that gap, read standard documentation.]
29 Theory
30 ------
32 1. Usually, compilation of objects for shared libraries requires different
33 set of compiler options comparing to static counterparts. For example,
34 many systems require -fpic flag to generate position-independent code.
35 However, for Win32, both static libs and DLLs are created from the same
36 set of objects. Despite this little advantage, DLLs have following big
37 disadvantage:
39 2. Once have been created, shared libraries require no additional fuzz
40 for usage. When so-using executable is loaded, every reference to
41 so-symbol gets fixed up to point directly to SO. Win32 has different
42 system: every executable importing DLL has special section, .idata, to hold
43 pointers to imported symbols. During loading, OS loader fills this section
44 with actual info. And application is supposed, when needed DLL-symbol, first
45 lookup its pointer in .idata, and only then have access by that pointer,
46 As you see, for DLL-imported symbols, additional level of indirection is
47 required. This stems probably from dark times of real-mode 16-bit Windows,
48 working on 8086 processor lacking virtual memory. Having all import-related
49 stuff in one single place facilated runtime relocation, which was needed
50 to effictively manage memory there. So or other, but it is that way.
51    So, as you see, special compiler support required to compile client of
52 DLL (note strange symmetry - *nix require special support to compile library,
53 while Win32 - to compile client. Former is better, I agree).
55 3. As was said before, with SO you use library just as you would static
56 version. This is not so for Win32. Win32 DLL is self-contained executable,
57 not supposed to be linked against. Instead, client is linked with special
58 auxilary library, called 'import library' or 'implib'. Implib contains
59 information to properly layout .idata section to be filled in by OS loader
60 with information about DLL.
63 Building DLL from existing static library
64 -----------------------------------------
66 We assume that you already build static lib, which we will call 'libfoo.a'.
67 However, building yourself is not requirement, to perform these instructions,
68 you don't needed sources of library - only library itself and its headers.
70 1. Fisrt step would be to create export definition file (or just def). You
71 can do this directly from library:
73 dlltool libfoo.a --export-all-symbols --output-def foo.def
75 2. Now, we can create DLL itself. This may be done by two ways: 1) link
76 dummy file referencing each symbol in libfoo.a (created by script acting on
77 output from 'nm libfoo.a') against libfoo.a (so, each foo's object for
78 sure will be in foo.dll) or 2) exploding library and linking all its objects
79 together. I consider second way cleaner and show it:
81 mkdir tmp
82 cp libfoo.a tmp/
83 cd tmp
84 ar x libfoo.a
85 dllwrap *.o --def ../foo.def -o ../foo.dll [usual -l libraries here]
86 cd ..
88 3. Let's create implib. If you want totally transparent transition from
89 static to DLL, call it 'libfoo.a'. However, if you want to keep destinction,
90 'libfoo.dll.a' is good:
92 dlltool --def foo.def  --ouput-lib libfoo.dll.a
94 4. Now grep foo.def for entries containing 'DATA'. If there's none -
95 congratulations, your library uses functional-only interface and you've done.
96 Else, most unpleasant work left - patch headers to include dllimport tag.
98 If you want to do it once-and-for-all (you should), do following:
100   a) make something like 'dl_import.h' and put there:
101    -----
102    #if !defined(STATIC) && defined(_WIN32)
103    #define _DL_IMPORT __delcspec(dllimport)
104    #else
105    #define _DL_IMPORT
106    #endif
107    -----
108    , if you want to use DLL by default (note that you will need to compile
109    library itself with STATIC defined), or
110    -----
111    #if defined(DLL) && defined(_WIN32)
112    #define _DL_IMPORT __delcspec(dllimport)
113    #else
114    #define _DL_IMPORT
115    #endif
116    -----
117    , if you want to include -DDLL each time you compile DLL client.
119   b) for each def symbol having DATA attribute, find header where its declared
120   as extern. If that header doesn't have '#include "dl_import.h"' at the top,
121   add it. Put '_DL_IMPORT' in front of 'extern' (strictly speaking, position
122   matters and proper place is after both extern and type, but for data
123   declaration above works also (at least for me)). For example, if it was
125     extern void *(*my_malloc)(int sz);
127   becoming
129     _DL_IMPORT extern void *(*my_malloc)(int sz);
131   will suffice. Procedd with next symbol.
133 However, if you're lazy for that, you may stretch the pleasure and mark
134 symbol as _DL_IMPORT only whenever you encounter it in undefined symbol
135 error during linking of client.
137 5. That's all! Now, just compile client either as usually or with -DDLL,
138 and link either as usually or with -lfoo.dll .
140 Paul.Sokolovsky@technologist.com
141 1999-08-28