https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=04f4da794de2f7fee0e8b813db031bb7ac8513c7
commit 04f4da794de2f7fee0e8b813db031bb7ac8513c7 Author: Jon Turney <[email protected]> Date: Fri May 23 13:54:18 2025 +0100 Cygwin: doc: Update "building DLLs" section This hasn't been substantially revised since (at least) 2004, and doesn't really represent normal usage of modern gcc and binutils. Diff: --- winsup/doc/dll.xml | 174 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 133 insertions(+), 41 deletions(-) diff --git a/winsup/doc/dll.xml b/winsup/doc/dll.xml index f0369760f..66d65f7d8 100644 --- a/winsup/doc/dll.xml +++ b/winsup/doc/dll.xml @@ -19,26 +19,53 @@ variables, etc. All these are merged together, like if you were building one big object files, and put into the dll. They are not put into your .exe at all.</para> -<para>The exports contains a list of functions and variables that the +<para>The exports is a list of functions and variables that the dll makes available to other programs. Think of this as the list of -"global" symbols, the rest being hidden. Normally, you'd create this -list by hand with a text editor, but it's possible to do it -automatically from the list of functions in your code. The -<filename>dlltool</filename> program creates the exports section of -the dll from your text file of exported symbols.</para> - -<para>The import library is a regular UNIX-like -<filename>.a</filename> library, but it only contains the tiny bit of -information needed to tell the OS how your program interacts with -("imports") the dll. This information is linked into your -<filename>.exe</filename>. This is also generated by -<filename>dlltool</filename>.</para> +"public" symbols, the rest being hidden. + +<footnote> + <para> + Note that <filename>ld</filename>'s default behaviour is to export all + global symbols, if there otherwise wouldn't be any exported symbols + (i.e. because you haven't specified a def file or made any export + annotations). (See <code>--export-all-symbols</code> in the + <filename>ld</filename> man page for more details.) + </para> +</footnote> + +This list can be in a module definition (.def) file, which you can write by hand +with a text editor, but it's also possible to have it generated automatically +from the functions and variables in your code, by annotating the declarations +with <code>__attribute__ ((dllexport))</code>. + +<footnote> + <para> + If you're making these annotations on the declarations in a header which is + also installed to be included by users of your library, you probably want to + use macros to do the right thing and increase portability. See <ulink + url="https://gcc.gnu.org/wiki/Visibility">this example</ulink> for details. + </para> +</footnote> + +</para> + +<para>The import library is a regular UNIX-like <filename>.a</filename> library, +but it only contains the tiny bit of information ("a stub") needed to tell the +OS how your program interacts with ("imports") the dll. This information is +linked into your <filename>.exe</filename>. +</para> + +<para> + Refer to the <ulink + url="https://sourceware.org/binutils/docs/ld/WIN32.html">section of the ld + manual</ulink> discussing Win32 PE specifics for more details. +</para> <sect2 id="dll-build"><title>Building DLLs</title> -<para>This page gives only a few simple examples of gcc's DLL-building +<para>This page gives only a few simple examples of gcc's DLL-building capabilities. To begin an exploration of the many additional options, -see the gcc documentation and website, currently at +see the gcc documentation and website, currently at <ulink url="http://gcc.gnu.org/">http://gcc.gnu.org/</ulink> </para> @@ -49,8 +76,8 @@ For this example, we'll use a single file <filename>mydll.c</filename> for the contents of the dll (<filename>mydll.dll</filename>).</para> -<para>Fortunately, with the latest gcc and binutils the process for building a dll -is now pretty simple. Say you want to build this minimal function in mydll.c:</para> +<para>Say you want to build this minimal function in +<filename>mydll.c</filename>:</para> <screen> #include <stdio.h> @@ -59,28 +86,44 @@ int hello() { printf ("Hello World!\n"); -} +} </screen> -<para>First compile mydll.c to object code:</para> +<para>First compile <filename>mydll.c</filename> to the object +<filename>mydll.o</filename>:</para> <screen>gcc -c mydll.c</screen> <para>Then, tell gcc that it is building a shared library:</para> -<screen>gcc -shared -o mydll.dll mydll.o</screen> +<screen>gcc -shared -o mydll.dll mydll.o -Wl,--out-implib libmydll.a</screen> + +<para> + That's it! You now have the dll (<filename>mydll.dll</filename>) and the + import library (<filename>libmydll.a</filename>). + +<footnote> + <para> + In fact, <code>--out-implib</code> is optional in this simple example, + because <filename>ld</filename> can automatically generate import stubs when + told to link directly to a .dll. (See <code>--enable-auto-import</code> in + the <filename>ld</filename> man page for more details.) + </para> +</footnote> + +</para> <para> -That's it! To finish up the example, you can now link to the -dll with a simple program: +To finish up the example, you can now link to the dll with a simple program, +<filename>myprog.c</filename>: </para> <screen> -int +int main () { hello (); -} +} </screen> <para> @@ -89,35 +132,84 @@ Then link to your dll with a command like: <screen>gcc -o myprog myprog.c -L./ -lmydll</screen> -<para>However, if you are building a dll as an export library, -you will probably want to use the complete syntax:</para> +<para> + Try it out: +</para> + +<screen> +$ ./myprog +Hello World! +</screen> + +<para>However, if you are building a dll for installation, +you will probably want to use a more complex syntax:</para> <screen>gcc -shared -o cyg${module}.dll \ -Wl,--out-implib=lib${module}.dll.a \ - -Wl,--export-all-symbols \ - -Wl,--enable-auto-import \ - -Wl,--whole-archive ${old_libs} \ - -Wl,--no-whole-archive ${dependency_libs}</screen> + -Wl,--whole-archive ${objs_libs} -Wl,--no-whole-archive \ + ${dependency_libs}</screen> -<para> +<itemizedlist spacing="compact"> +<listitem> The name of your library is <literal>${module}</literal>, prefixed with <literal>cyg</literal> for the DLL and <literal>lib</literal> for the -import library. Cygwin DLLs use the <literal>cyg</literal> prefix to -differentiate them from native-Windows MinGW DLLs, see -<ulink url="http://mingw.org">the MinGW website</ulink> for more details. -<literal>${old_libs}</literal> are all -your object files, bundled together in static libs or single object -files and the <literal>${dependency_libs}</literal> are import libs you -need to link against, e.g -<userinput>'-lpng -lz -L/usr/local/special -lmyspeciallib'</userinput>. +import library. Cygwin DLLs use the <literal>cyg</literal> prefix to +differentiate them from native-Windows MinGW DLLs. +</listitem> +<listitem> +<literal>${objs_libs}</literal> are all your object files, bundled together in +static libs or single object files +</listitem> +<listitem> +<literal>${dependency_libs}</literal> are static or import libs you need to link +against, e.g <userinput>'-lpng -lz -L/usr/local/special -lmyspeciallib' +</userinput>. +</listitem> +</itemizedlist> + +<para> + When the import library is installed into <filename>/usr/lib</filename>, it + can be linked to with just <code>-l${module}</code>. The dll itself is + installed into <filename>/usr/bin</filename> so it can be found on + <code>PATH</code> by the loader when a linked .exe is run. +</para> + +</sect2> + +<sect2 id="dll-tool"><title>dlltool</title> + +<para> +Historically, the process for building a dll with <filename>gcc</filename> and +<filename>binutils</filename> wasn't so simple, and the +<filename>dlltool</filename> tool was used: </para> + +<itemizedlist spacing="compact"> + <listitem> + <para> + To create the exports section of the dll, from the module definition file + or by scanning object files. + </para> + </listitem> + + <listitem> + <para> + To generate the import library. + </para> + </listitem> +</itemizedlist> + +<para> + (See the <filename>dlltool</filename> man page for more details.) +</para> + </sect2> -<sect2 id="dll-link"><title>Linking Against DLLs</title> +<sect2 id="dll-link"><title>Linking Against Foreign DLLs</title> <para>If you have an existing DLL already, you need to build a Cygwin-compatible import library. If you have the source to compile -the DLL, see <xref linkend="dll-build"></xref> for details on having +the DLL, see <xref linkend="dll-build"></xref> for details on having <filename>gcc</filename> build one for you. If you do not have the source or a supplied working import library, you can get most of the way by creating a .def file with these commands (you might need to
