[Haskell-cafe] GHC can't find DLL dependencies on Windows

Ryan Scott ryan.gl.scott at gmail.com
Wed Oct 28 19:25:05 UTC 2015

I recently decided to try out a simple diagrams-cairo project on
Windows 8 (x86_64) to discover that GHC (7.10.2, to be specific) acts
rather bizarrely when dealing with external DLL dependencies.

To start, I downloaded MSYS2 [1], installed the libraries needed for
cairo and pango to work [2], installed diagrams-cairo [3], and tried
running a simple diagrams program:

    module Main (main) where

    import Diagrams.Prelude
    import Diagrams.Backend.Cairo.CmdLine

    main :: IO ()
    main = mainWith (circle 1 :: Diagram B)

like so from MSYS2:

   runghc Cairo.hs -o circle.svg -w 400

And it worked. Hooray!

Now, I normally use cmd.exe/PowerShell for most of my Windows
command-line tasks, so later I tried invoking the above command on
PowerShell, only to be greeted with an error message:

    $ runghc.exe .\Cairo.hs -o circle.svg -w 400
    Cairo.hs: warning: _tzset from msvcrt is linked instead of __imp__tzset
    Cairo.hs: libcairo-2: The specified procedure could not be found.
    Cairo.hs: <command line>: can't load .so/.DLL for: libcairo-2.dll
(addDLL: could not load DLL)

PowerShell, alas, couldn't find libcairo-2.dll when MSYS2 had no
trouble whatsoever. I realized that MSYS2 stores all of its
MinGW-related DLL files in a special location (C:\msys64\mingw64\bin).
This can be observed by running cygcheck on the executable:

    $ C:\msys64\usr\bin\cygcheck.exe .\Cairo.exe
    cygcheck: track_down: could not find libcairo-2.dll

    cygcheck: track_down: could not find libglib-2.0-0.dll

    cygcheck: track_down: could not find libgobject-2.0-0.dll

    cygcheck: track_down: could not find libpango-1.0-0.dll

    cygcheck: track_down: could not find libpangocairo-1.0-0.dll

After reading about DLL search paths in Windows [4], I got the
impression that I could add C:\msys64\mingw64\bin to my PATH, and then
executables would look for DLLs there. Adding C:\msys64\mingw64\bin to
my PATH seemed to make cygcheck happy:

    $ C:\msys64\usr\bin\cygcheck.exe .\Cairo.exe

But invoking runghc Cairo.exe on PowerShell still fails with the same
error message! For the life of me, I can't figure out what kind of
sorcery MSYS2 is doing to make C:\msys64\mingw64\bin visible to the
DLL search path from GHC. The only way I can trick PowerShell into
seeing libcairo-2.dll is to

(1) Copy libcairo-2.dll directly to C:\Windows\System32, or
(2) Invoke SetDllDirectory("C:\msys64\mingw64\bin") [5] from a
PowerShell startup script

Neither of these options are very satisfying, since (1) has massive
security implications, and (2) only works when you have one external
DLL directory (if you called SetDllDirectory again with a different
directory, it overrides the first one).

I know there are folks out there who have managed to get diagrams
working on Windows, so can someone let me know if I'm doing something

Ryan S.
[1] http://msys2.github.io/
[2] pacman -S mingw-w64-x86_64-cairo mingw-w64-x86_64-pango 1.38.1-1
[3] cabal install diagrams-cairo
[4] https://msdn.microsoft.com/en-us/library/ms682586.aspx#search_order_for_desktop_applications
[5] https://msdn.microsoft.com/en-us/library/windows/desktop/ms686203%28v=vs.85%29.aspx

More information about the Haskell-Cafe mailing list