From: Duncan Coutts Date: Sat, 4 Jul 2009 21:20:03 +0000 (+0000) Subject: Add new section on using shared libs X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=commitdiff_plain;h=a7981216f157c0d7faac9e9acf98cf0351951a8d Add new section on using shared libs --- diff --git a/docs/users_guide/shared_libs.xml b/docs/users_guide/shared_libs.xml new file mode 100644 index 0000000..e2152d1 --- /dev/null +++ b/docs/users_guide/shared_libs.xml @@ -0,0 +1,210 @@ + + + Using shared libraries + Shared librariesusing + Dynamic librariesusing + + + On some platforms GHC supports building Haskell code into shared + libraries. Shared libraries are also sometimes known as dynamic + libraries, in particular on Windows they are referred to as dynamic link + libraries (DLLs). + + + + Shared libraries allow a single instance of some pre-compiled code to be + shared between several programs. In contrast, with static linking the + code is copied into each program. Using shared libraries can thus save + disk space. They also allow a single copy of code to be shared in memory + between several programs that use it. Shared libraires are often used as + a way of structuring large projects, especially where different parts are + written in different programming languages. Shared libraries are also + commonly used as a plugin mechanism by various applications. This is + particularly common on Windows using COM. + + + + In GHC version 6.12 building shared libraries is supported for Linux on + x86 and x86-64 architectures and there is partial support on Windows (see + ). The crucial difference in support on + Windows is that it is not currently possible to build each Haskell + package as a separate DLL, it is only possible to link an entire Haskell + program as one massive DLL. + + + + Building and using shared libraries is slightly more complicated than + building and using static libraries. When using Cabal much of the detail + is hidden, just use --enable-shared when configuring a + package to build it into a shared library, or to link it against other + packages built as shared libraries. The additional complexity when + building code is to distinguish whether the code will be used in a shared + library or will use shared library versions of other packages it depends + on. There is additional complexity when installing and distributing + shared libraries or programs that use shared libraries, to ensure that + all shared libraries that are required at runtime are present in suitable + locations. + + + + Building programs that use shared libraries + + To build a simple program and have it use shared libraries for the + runtime system and the base libraries use the + -dynamic flag: + +ghc --make -dynamic Main.hs + + This has two effects. The first is to compile the code in such a way + that it can be linked against shared library versions of Haskell + packages (such as base). The second is when linking, to link against + the shared versions of the packages' libraries rather than the static + versions. Obviously this requires that the packages were build with + shared libraries. On supported platforms GHC comes with shared + libraries for all the core packages, but if you install extra packages + (e.g. with Cabal) then they would also have to be built with shared + libraries (--enable-shared for Cabal). + + + + + Building shared libraries + + To build some Haskell modules into a shared library use the + -dynamic, -fPIC and + -shared flags: + +ghc --make -dynamic -shared -fPIC Foo.hs -o libfoo.so + + As before, the -dynamic flag specifies that this + library links against the shared library versions of the rts and base + package. The -fPIC flag is required for all code + that will end up in a shared library. The -shared + flag specifies to make a shared library rather than a program. To make + this clearer we can break this down into separate compliation and link + steps: + +ghc -dynamic -fPIC -c Foo.hs +ghc -dynamic -shared Foo.o -o libfoo.so + + In principle you can use -shared without + -dynamic in the link step. That means to + statically link the rts all the base libraries into your new shared + library. This would make a very big, but standalone shared library. + Indeed this is exactly what we must currently do on Windows where + -dynamic is not yet supported (see ). + On most platforms however that would require all the static libraries + to have been built with -fPIC so that the code is + suitable to include into a shared library and we do not do that at the + moment. + + + + + Shared libraries that export a C API + + 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. + + + 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 . 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. + + + + + Shared libraries for Haskell packages + + 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 . + + + + + Finding shared libraries at runtime + + The primary difficulty with managing shared libraries is arranging + things such that programs can find the libraries they need at runtime. + The details of how this works varies between platforms, in particular + the three major systems: Unix ELF platforms, Windows and Mac OS X. + + + On Unix there are two mechanisms. Shared libraries can be installed + into standard locations that the dynamic linker knows about. For + example /usr/lib or + /usr/local/lib on most systems. The other mechanism + is to use a "runtime path" or "rpath" embedded into programs and + libraries themselves. These paths can either be absolute paths or on at + least Linux and Solaris they can be paths relative to the program or + libary itself. In principle this makes it possible to construct fully + relocatable sets of programs and libraries. + + + GHC has a -dynload linking flag to select the method + that is used to find shared libraries at runtime. There are currently + three modes: + + + sysdep + + + A system-dependent mode. This is also the default mode. On Unix + ELF systems this embeds rpaths into the shared library or + executable. In particular it uses absolute paths to where the + shared libraries for the rts and each package can be found. + This means the program can immediately be run and it will be + able to find the libraries it needs. However it may not be + suitable for deployment if the libraries are installed in a + different location on another machine. + + + + + deploy + + + This does not embed any runtime paths. It relies on the shared + libraries being available in a standard location or in a + directory given by the LD_LIBRARY_PATH + environment variable. + + + + + wrapped + + + This mode generates a wrapper program which in turn calls the + real program (in the same directory but with a .dyn extension) + in such a way that it can find the shared libraries that it + needs. At the current time this mode is somewhat experimental. + + + + + To use relative paths for dependent libraries on Linux and Solaris you + can use the deploy mode and pass suitable a -rpath + flag to the linker: + +ghc -dynamic Main.hs -o main -lfoo -L. -optl-Wl,-rpath,'$ORIGIN' + + This assumes that the library libfoo.so is in the + current directory and will be able to be found in the same directory as + the executable main once the program is deployed. + Similarly it would be possible to use a subdirectory relative to the + executable e.g. -optl-Wl,-rpath,'$ORIGIN/lib'. + + + + diff --git a/docs/users_guide/ug-ent.xml b/docs/users_guide/ug-ent.xml index 02ea31b..a582242 100644 --- a/docs/users_guide/ug-ent.xml +++ b/docs/users_guide/ug-ent.xml @@ -20,3 +20,4 @@ + diff --git a/docs/users_guide/using.xml b/docs/users_guide/using.xml index 024a4e7..f668639 100644 --- a/docs/users_guide/using.xml +++ b/docs/users_guide/using.xml @@ -1795,7 +1795,9 @@ f "2" = 2 &phases; - + + &shared_libs; + Using Concurrent Haskell Concurrent Haskellusing