X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fdocs%2Fusers_guide%2Fwin32-dlls.sgml;h=cdaad9cd605ee179c6c8e57cc7315654e33ea246;hb=4a4bc50d9a1e6bdb4662005188a957a50f20aee1;hp=ce1cbffeb33623ffed1037ef65e3c9b54b8fe72c;hpb=57ff175ec6b215daba92cf1cb6ac1b35b063768c;p=ghc-hetmet.git diff --git a/ghc/docs/users_guide/win32-dlls.sgml b/ghc/docs/users_guide/win32-dlls.sgml index ce1cbff..cdaad9c 100644 --- a/ghc/docs/users_guide/win32-dlls.sgml +++ b/ghc/docs/users_guide/win32-dlls.sgml @@ -1,4 +1,160 @@ - + +Running GHC on Win32 systems + + + +Starting GHC on Win32 platforms + + +The installer that installs GHC on Win32 also sets up the file-suffix associations +for ".hs" and ".lhs" files so that double-clicking them starts ghci. + + +Be aware of that ghc and ghci do +require filenames containing spaces to be escaped using quotes: + + c:\ghc\bin\ghci "c:\\Program Files\\Haskell\\Project.hs" + +If the quotes are left off in the above command, ghci will +interpret the filename as two, "c:\\Program" and "Files\\Haskell\\Project.hs". + + + + + + + + +Interacting with the terminal + +By default GHC builds applications that open a console window when they start. +If you want to build a GUI-only application, with no console window, use the flag +-optl-mwindows in the link step. + + +For some reason, Mingw ships with the readline library, +but not with the readline headers. As a result, GHC (like Hugs) does not +use readline for interactive input on Windows. +You can get a close simulation by using an emacs shell buffer! + + + + + + +Differences in library behaviour + + +Some of the standard Haskell libraries behave slightly differently on Windows. + + + +On Windows, the '^Z' character is interpreted as an +end-of-file character, so if you read a file containing this character +the file will appear to end just before it. To avoid this, +use IOExts.openFileEx to open a file in binary +(untranslated) mode or change an already opened file handle into +binary mode using IOExts.hSetBinaryMode. The +IOExts module is part of the +lang package. + + + + + + + + +Using GHC (and other GHC-compiled executables) with cygwin + + +Background The cygwin tools aim to provide a +unix-style API on top of the windows libraries, to facilitate ports of +unix software to windows. To this end, they introduce a unix-style +directory hierarchy under some root directory (typically +/ is C:\cygwin\). Moreover, +everything built against the cygwin API (including the cygwin tools +and programs compiled with cygwin's ghc) will see / as the root of +their file system, happily pretending to work in a typical unix +environment, and finding things like /bin and /usr/include without +ever explicitly bothering with their actual location on the windows +system (probably C:\cygwin\bin and C:\cygwin\usr\include). + + + +The problem +GHC, by default, no longer depends on cygwin, but is a native +windows program. It is built using mingw, and it uses mingw's ghc +while compiling your Haskell sources (even if you call it from +cygwin's bash), but what matters here is that - just like any other +normal windows program - neither GHC nor the executables it produces +are aware of cygwin's pretended unix hierarchy. GHC will happily +accept either '/' or '\' as path separators, but it won't know where +to find /home/joe/Main.hs or /bin/bash +or the like. This causes all +kinds of fun when GHC is used from within cygwin's bash, or in +make-sessions running under cygwin. + + + +Things to do + + + Don't use absolute paths in make, configure & co if there is any chance + that those might be passed to GHC (or to GHC-compiled programs). Relative + paths are fine because cygwin tools are happy with them and GHC accepts + '/' as path-separator. And relative paths don't depend on where cygwin's + root directory is located, or on which partition or network drive your source + tree happens to reside, as long as you 'cd' there first. + + + + If you have to use absolute paths (beware of the innocent-looking + ROOT=`pwd` in makefile hierarchies or configure scripts), cygwin provides + a tool called cygpath that can convert cygwin's unix-style paths to their + actual windows-style counterparts. Many cygwin tools actually accept + absolute windows-style paths (remember, though, that you either need + to escape '\' or convert '\' to '/'), so you should be fine just using those + everywhere. If you need to use tools that do some kind of path-mangling + that depends on unix-style paths (one fun example is trying to interpret ':' + as a separator in path lists..), you can still try to convert paths using + cygpath just before they are passed to GHC and friends. + + + + If you don't have cygpath, you probably don't have cygwin and hence + no problems with it... unless you want to write one build process for several + platforms. Again, relative paths are your friend, but if you have to use + absolute paths, and don't want to use different tools on different platforms, + you can simply write a short Haskell program to print the current directory + (thanks to George Russell for this idea): compiled with GHC, this will give + you the view of the file system that GHC depends on (which will differ + depending on whether GHC is compiled with cygwin's gcc or mingw's + gcc or on a real unix system..) - that little program can also deal with + escaping '\' in paths. Apart from the banner and the startup time, + something like this would also do: + + $ echo "Directory.getCurrentDirectory >>= putStrLn . init . tail . show " | ghci + + + + + + + + Building and using Win32 DLLs @@ -10,7 +166,15 @@ dynamic link libraries (DLLs) containing ghc-compiled code. This section shows you how to make use of this facility. - + +Until recently, strip didn't work reliably on DLLs, so you +should test your version with care, or make sure you have the latest +binutils. Unfortunately, we don't know exactly which version of binutils +cured the problem (it was supposedly fixed some years ago). + + + + Linking with DLLs @@ -22,7 +186,6 @@ command-line, so - sh$ cat main.hs module Main where @@ -31,25 +194,26 @@ sh$ ghc -o main main.hs ghc: module version changed to 1; reason: no old .hi file sh$ strip main.exe sh$ ls -l main.exe --rwxr-xr-x 1 544 everyone 6144 May 3 17:11 main.exe* +-rwxr-xr-x 1 544 everyone 4608 May 3 17:11 main.exe* sh$ ./main hello, world! sh$ - -will give you a binary as before, but the main.exe generated will use the Prelude and RTS DLLs instead. +will give you a binary as before, but the main.exe +generated will use the Prelude and RTS DLLs instead of linking them in +statically. -6K for a "hello, world" application---not bad, huh? :-) +4K for a "hello, world" application—not bad, huh? :-) - + - + Not linking with DLLs <IndexTerm><Primary>-static option (Win32)</Primary></IndexTerm> @@ -65,34 +229,45 @@ Notice that you cannot mix code that has been compiled with option on all the Haskell modules that make up your application. - + - + Creating a DLL +Making libraries into DLLs doesn't work on Windows at the +moment (and is no longer supported); however, all the machinery is +still there. If you're interested, contact the GHC team. Note that +building an entire Haskell application as a DLL is still supported +(it's just inter-DLL Haskell calls that don't work). Creating a Win32 DLL ---mk-dll -Sealing up your Haskell library inside a DLL is quite straightforward; +––mk-dll +Sealing up your Haskell library inside a DLL is straightforward; compile up the object files that make up the library, and then build -the DLL by issuing the following command: +the DLL by issuing a command of the form: -ghc --mk-dll -o HSsuper.dll A.o Super.o B.o libmine.a -lgdi32 +ghc ––mk-dll -o foo.dll bar.o baz.o wibble.a -lfooble -By feeding the ghc compiler driver the option , it +By feeding the ghc compiler driver the option , it will build a DLL rather than produce an executable. The DLL will consist of all the object files and archives given on the command line. +To create a `static' DLL, i.e. one that does not depend on the GHC DLLs, +use the when compiling up your Haskell code and +building the DLL. + + + A couple of things to notice: @@ -100,24 +275,28 @@ A couple of things to notice: - - Since DLLs correspond to packages (see ) you need to use when compiling modules that -belong to a DLL. If you don't, Haskell code that calls entry points in that -DLL will do so incorrectly, and a crash will result. - +belong to a DLL if you're going to call them from Haskell. Otherwise, Haskell +code that calls entry points in that DLL will do so incorrectly, and crash. +For similar reasons, you can only compile a single module tree into a DLL, +as startupHaskell needs to be able to call its +initialisation function, and only takes one such argument (see ). Hence the modules +you compile into a DLL must have a common root. - + -By default, the entry points of all the object files will -be exported from the DLL when using . Should you want to constrain this, you can specify the module definition file to use on the command line as follows: +By default, the entry points of all the object files will be exported from +the DLL when using . Should you want to constrain +this, you can specify the module definition file to use +on the command line as follows: -ghc --mk-dll -o .... -optdll--def -optdllMyDef.def +ghc ––mk-dll -o .... -optdll--def -optdllMyDef.def See Microsoft documentation for details, but a module definition file @@ -131,41 +310,161 @@ EXPORTS DllRegisterServer = DllRegisterServer@0 DllUnregisterServer = DllUnregisterServer@0 + + + + + +In addition to creating a DLL, the option also +creates an import library. The import library name is derived from the +name of the DLL, as follows: + + +DLL: HScool.dll ==> import lib: libHScool_imp.a + + +The naming scheme may look a bit weird, but it has the purpose of allowing +the co-existence of import libraries with ordinary static libraries (e.g., +libHSfoo.a and +libHSfoo_imp.a. + +Additionally, when the compiler driver is linking in non-static mode, it +will rewrite occurrence of on the command line to +. By doing this for you, switching from +non-static to static linking is simply a question of adding + to your command line. + + + + + + + + + + +Making DLLs to be called from other languages + + + +If you want to package up Haskell code to be called from other languages, +such as Visual Basic or C++, there are some extra things it is useful to +know. The dirty details are in the Foreign Function +Interface definition, but it can be tricky to work out how to +combine this with DLL building, so here's an example: + + + + + + + +Use foreign export declarations to export the Haskell +functions you want to call from the outside. For example, + + +module Adder where +adder :: Int -> Int -> IO Int -- gratuitous use of IO +adder x y = return (x+y) +foreign export stdcall adder :: Int -> Int -> IO Int + + + +Compile it up: + + +ghc -c adder.hs -fglasgow-exts + + +This will produce two files, adder.o and adder_stub.o + + + -In addition to creating a DLL, the option will also -create an import library. The import library name is derived from the -name of the DLL, as follows: +compile up a DllMain() that starts up the Haskell +RTS-––a possible implementation is: -DLL: HScool.dll ==> import lib: libHScool_imp.a +#include <windows.h> +#include <Rts.h> + +EXTFUN(__stginit_Adder); + +static char* args[] = { "ghcDll", NULL }; + /* N.B. argv arrays must end with NULL */ +BOOL +STDCALL +DllMain + ( HANDLE hModule + , DWORD reason + , void* reserved + ) +{ + if (reason == DLL_PROCESS_ATTACH) { + /* By now, the RTS DLL should have been hoisted in, but we need to start it up. */ + startupHaskell(1, args, __stginit_Adder); + return TRUE; + } + return TRUE; +} +Here, Adder is the name of the root module in the module +tree (as mentioned above, there must be a single root module, and hence a +single module tree in the DLL). + +Compile this up: + + +ghc -c dllMain.c + + + -The naming scheme may look a bit weird, but it has the purpose of -allowing the co-existence of import libraries with ordinary static -libraries (e.g., libHSfoo.a and libHSfoo_imp.a. + + +Construct the DLL: -Additionally, when the compiler driver is linking in non-static mode, -it will rewrite occurrence of on the command line to -. By doing this for you, switching from non-static -to static linking is simply a question of adding to -your command line. + +ghc ––mk-dll -o adder.dll adder.o adder_stub.o dllMain.o + - + + +Start using adder from VBA-––here's how I would +Declare it: + +Private Declare Function adder Lib "adder.dll" Alias "adder@8" + (ByVal x As Long, ByVal y As Long) As Long + + +Since this Haskell DLL depends on a couple of the DLLs that come with GHC, +make sure that they are in scope/visible. + + + +Building statically linked DLLs is the same as in the previous section: it +suffices to add to the commands used to compile up +the Haskell source and build the DLL. - + + + + + +