On Fri, 23 May 2025 17:41:02 +0100
Jon Turney wrote:
> This hasn't substantially been revised since (at least) 2004, and
> doesn't really represent normal usage of modern gcc and binutils.
> ---
> winsup/doc/dll.xml | 168 ++++++++++++++++++++++++++++++++++-----------
> 1 file changed, 127 insertions(+), 41 deletions(-)
>
> diff --git a/winsup/doc/dll.xml b/winsup/doc/dll.xml
> index f0369760f..7117b65bd 100644
> --- a/winsup/doc/dll.xml
> +++ b/winsup/doc/dll.xml
> @@ -19,26 +19,47 @@ 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>
>
> <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 +70,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 +80,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! To finish up the example, you can now link to the
> -dll with a simple program:
> + 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>
> +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 +126,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
> --
> 2.45.1
Thanks! LGTM. Please push.
--
Takashi Yano <[email protected]>