Opened 9 years ago

Closed 8 years ago

#4465 closed bug (fixed)

GHCi linker failure on Windows

Reported by: joellathrop Owned by: simonmar
Priority: high Milestone: 7.4.1
Component: GHCi Version: 6.12.3
Keywords: ghci linker -L DLL Cc: joell@…, overture2112@…, fryguybob@…
Operating System: Windows Architecture: x86
Type of failure: Incorrect result at runtime Test Case: ghci/linking/ghcilink002
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description

On Windows, GHCi seems unable to find a DLL in a non-standard location, even when that location is provided with -L.

Presume a valid DLL named "foo.dll" in "c:\temp\test". An attempt to load "foo" into GHCi when the current working directory is "c:\temp\test" is successful:

C:\temp\test>ghci -lfoo
GHCi, version 6.12.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
Loading object (dynamic) foo ... done
final link ... done
Prelude>

However, if the current working directory is "c:\temp" all attempts to load "foo" into GHCi using the -L switch fail:

C:\temp>ghci -lfoo -Ltest
GHCi, version 6.12.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
: foo: The specified module could not be found.
Loading object (dynamic) foo ... failed.
<command line>: user specified .o/.so/.DLL could not be loaded (addDLL: could no
t load DLL)
Whilst trying to load:  (dynamic) foo
Additional directories searched:   test
C:\temp>ghci -lfoo -L\temp\test
GHCi, version 6.12.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
: foo: The specified module could not be found.
Loading object (dynamic) foo ... failed.
<command line>: user specified .o/.so/.DLL could not be loaded (addDLL: could no
t load DLL)
Whilst trying to load:  (dynamic) foo
Additional directories searched:   \temp\test
C:\temp>ghci -lfoo -Lc:\temp\test
GHCi, version 6.12.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
: foo: The specified module could not be found.
Loading object (dynamic) foo ... failed.
<command line>: user specified .o/.so/.DLL could not be loaded (addDLL: could no
t load DLL)
Whilst trying to load:  (dynamic) foo
Additional directories searched:   c:\temp\test

However, GHCi has no problem loading "foo" if the path component is included in the -l option. (Naturally, this is not ideal and far from the accepted usage of -l and -L.)

C:\temp>ghci -ltest\foo
GHCi, version 6.12.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
Loading object (dynamic) test\foo ... done
final link ... done
Prelude>

Finally, this issue does not manifest on Linux. Everything seems to work fine there.

Change History (7)

comment:1 Changed 9 years ago by jre2

Cc: overture2112@… added

comment:2 Changed 9 years ago by igloo

Milestone: 7.0.2

Thanks for the report.

comment:3 Changed 9 years ago by igloo

Milestone: 7.0.27.2.1

comment:4 Changed 9 years ago by fryguybob

Cc: fryguybob@… added

I poked around on this a little and found that loadDynamic in compiler\ghci\Linker.lhs doesn't try to append an extension because addDll (from job rts\Linker.c) does that job. But if you don't add the extension it isn't going to find the file.

-- return Nothing == success, else Just error message from dlopen
loadDynamic :: [FilePath] -> FilePath -> IO (Maybe String)
loadDynamic paths rootname
  = do  { mb_dll <- findFile mk_dll_path paths
        ; case mb_dll of
            Just dll -> loadDLL dll
            Nothing  -> loadDLL (mkSOName rootname) }
                        -- Tried all our known library paths, so let 
                        -- dlopen() search its own builtin paths now.
  where
    mk_dll_path dir = dir </> mkSOName rootname

mkSOName :: FilePath -> FilePath
mkSOName root
 | isDarwinTarget  = ("lib" ++ root) <.> "dylib"
 | isWindowsTarget = -- Win32 DLLs have no .dll extension here, because
                     -- addDLL tries both foo.dll and foo.drv
                     root
 | otherwise       = ("lib" ++ root) <.> "so"

comment:5 Changed 8 years ago by igloo

Milestone: 7.2.17.4.1

comment:6 Changed 8 years ago by simonmar

difficulty: Unknown
Owner: set to simonmar
Priority: normalhigh

I believe I fixed this in d146fdbbf8941a8344f0ec300e79dbeabc08d1ea; assigning to myself to check.

comment:7 Changed 8 years ago by simonmar

Resolution: fixed
Status: newclosed
Test Case: ghci/linking/ghcilink002
Note: See TracTickets for help on using tickets.