
#10352: Properly link Haskell shared libs on all systems -------------------------------------+------------------------------------- Reporter: duncan | Owner: Phyx- Type: task | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.11 (Linking) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: 5987 Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by Phyx-): I'm having a hard time getting this to work on Windows which is what is causing the delay. The issue is that normally you'd be able to do this easily by delay loading the dll. This is done by creating a delay loading import library which essentially, instead of putting the symbols in the IAT of the PE file instead links statically against stubs. These stubs allow it to then load the DLL only on first call of a related function. This is done by those adding a level of indirection. (mingw-w64's implementation is here if curious https://github.com/mirror/mingw-w64/blob/master/mingw-w64-crt/misc/delayimp....) The issue is that this approach has a major limitation: It only works for Functions! This limitation is described here https://msdn.microsoft.com/en- us/library/yx1x886y.aspx But essentially this is because exported `const data` entries end up becoming stubs too. (empty stubs, but stubs in any case). This address is resolved at link time (because you're linking against the stub instead of the IAT entry being added to the Windows Loader can later resolve it). One way to work around this is to replace constant imports such as {{{ __declspec(dllimport) extern FooS_t fooStruct; }}} With explicit loads using MACROs: {{{ FooS_t fst = *(FooS_t*)GetProcAddress(GetModuleHandle("foo"), "fooStruct"); }}} This works, but I would have to track down each and every use of constants in the RTS and change them to this or to make them functions (e.g `getFooStruct()`). What I am investigating now is a third approach, using an intermediate proxy dll. Link normally against the proxy to the loader resolves the addresses of const data as it should, but have the proxy "forward" the requests to the right dll. This can be done because when the linker looks up symbols in the IAT the OS allows for hooks in the target library to override the returned address. This should allow me to use the proxy to choose at runtime which runtime to use. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10352#comment:14 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler