[newlib-cygwin/main] Cygwin: doc: Update "building DLLs" section

Jon Turney via Cygwin-cvs <[email protected]>
Newsgroups gmane.os.cygwin.cvs
Message-ID <[email protected]>
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 &lt;stdio.h&gt;
@@ -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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.