Improve the user guide section on shared libs
authorDuncan Coutts <duncan@well-typed.com>
Tue, 8 Sep 2009 18:32:41 +0000 (18:32 +0000)
committerDuncan Coutts <duncan@well-typed.com>
Tue, 8 Sep 2009 18:32:41 +0000 (18:32 +0000)
Make it clear that Haskell code to be used by other Haskell code
must be built as a package.

docs/users_guide/shared_libs.xml

index e2152d1..00f6f67 100644 (file)
@@ -68,10 +68,72 @@ ghc --make -dynamic Main.hs
   </sect2>
 
   <sect2>
-    <title>Building shared libraries</title>
+    <title>Shared libraries for Haskell packages</title>
+    <para>
+      You can build Haskell code into a shared library and make a package to be
+      used by other Haskell programs. The easiest way is using Cabal, simply
+      configure the Cabal package with the <literal>--enable-shared</literal>
+      flag.
+    </para>
+    <para>
+      If you want to do the steps manually or are writing your own build
+      system then there are certain conventions that must be followed. Building
+      a shared library that exports Haskell code, to be used by other Haskell
+      code is a bit more complicated than it is for one that exports a C API
+      and will be used by C code. If you get it wrong you will usually end up
+      with linker errors.
+    </para>
+    <para>
+      In particular Haskell shared libraries <emphasis>must</emphasis> be
+      made into packages. You cannot freely assign which modules go in which
+      shared libraries. The Haskell shared libraries must match the package
+      boundaries. Most of the conventions GHC expects when using packages are
+      described in <xref linkend="building-packages"/>.
+    </para>
     <para>
-      To build some Haskell modules into a shared library use the
+      GHC handles references to symbols <emphasis>within</emphasis> the same
+      shared library (or main executable binary) differently from references
+      to symbols <emphasis>between</emphasis> different shared libraries. GHC
+      needs to know for each imported module if that module lives locally in
+      the same shared lib or in a separate shared lib. The way it does this
+      is by using packages. When using <literal>-dynamic</literal>, a module
+      from a separate package is assumed to come from a separate shared lib,
+      while modules from the same package (or the default "main" package) are
+      assumed to be within the same shared lib (or main executable binary).
+   </para>
+    <para>
+      Most of the conventions GHC expects when using packages are described
+      in <xref linkend="building-packages"/>. In addition note that GHC
+      expects the <literal>.hi</literal> files to use the extension
+      <literal>.dyn_hi</literal>. The other requirements are the same as for
+      C libraries and are described below, in particular the use of the flags
       <literal>-dynamic</literal>, <literal>-fPIC</literal> and
+      <literal>-shared</literal>.
+    </para>
+  </sect2>
+
+  <sect2>
+    <title>Shared libraries that export a C API</title>
+    <para>
+      Building Haskell code into a shared library is a good way to include
+      Haskell code in a larger mixed-language project. While with static
+      linking it is recommended to use GHC to perform the final link step,
+      with shared libaries a Haskell library can be treated just like any
+      other shared libary. The linking can be done using the normal system C
+      compiler or linker.
+    </para>
+    <para>
+      It is possible to load shared libraries generated by GHC in other
+      programs not written in Haskell, so they are suitable for using as
+      plugins. Of course to construct a plugin you will have to use the FFI
+      to export C functions and follow the rules about initialising the RTS.
+      See <xref linkend="ffi-library"/>. In particular you will probably want
+      to export a C function from your shared library to initialise the
+      plugin before any Haskell functions are called.
+    </para>
+    <para>
+      To build Haskell modules that export a C API into a shared library use
+      the <literal>-dynamic</literal>, <literal>-fPIC</literal> and
       <literal>-shared</literal> flags:
 <programlisting>
 ghc --make -dynamic -shared -fPIC Foo.hs -o libfoo.so
@@ -98,39 +160,14 @@ ghc -dynamic -shared Foo.o -o libfoo.so
       suitable to include into a shared library and we do not do that at the
       moment.
     </para>
-  </sect2>
-
-  <sect2>
-    <title>Shared libraries that export a C API</title>
-    <para>
-      Building Haskell code into a shared library is a good way to include
-      Haskell code in a larger mixed-language project. While with static
-      linking it is recommended to use GHC to perform the final link step,
-      with shared libaries a Haskell library can be treated just like any
-      other shared libary. The linking can be done using the normal system C
-      compiler or linker.
-    </para>
     <para>
-      It is possible to load shared libraries generated by GHC in other
-      programs not written in Haskell, so they are suitable for using as
-      plugins. Of course to construct a plugin you will have to use the FFI
-      to export C functions and follow the rules about initialising the RTS.
-      See <xref linkend="ffi-library"/>. In particular you will probably want
-      to export a C function from your shared library to initialise the
-      plugin before any Haskell functions are called.
+      <emphasis>Warning:</emphasis> if your shared library exports a Haskell
+      API then you cannot directly link it into another Haskell program and
+      use that Haskell API. You will get linker errors. You must instead make
+      it into a package as described in the section above.
     </para>
   </sect2>
 
-  <sect2>
-    <title>Shared libraries for Haskell packages</title>
-    <para>
-      When building Haskell packages as shared libraries to be used by other
-      Haskell programs there are certain conventions that must be followed.
-      These are handled by Cabal but for the details see <xref
-      linkend="building-packages"/>.
-   </para>
-  </sect2>
-
   <sect2 id="finding-shared-libs">
     <title>Finding shared libraries at runtime</title>
     <para>