#2459: can't link haskell without "main" function, or -no-hs-main broken on
windows?
------------------------+---------------------------------------------------
    Reporter:  jvl      |       Owner:         
        Type:  bug      |      Status:  new    
    Priority:  normal   |   Component:  Driver 
     Version:  6.8.2    |    Severity:  normal 
    Keywords:           |    Testcase:         
Architecture:  Unknown  |          Os:  Windows
------------------------+---------------------------------------------------
 can't link haskell without "main" function, or -no-hs-main broken on
 windows?

 The issue arose when trying to compile wxHaskell examples with a !WinMain
 entry point in
 the executable rather than the standard "main" function, thereby stopping
 a new console
 window being created when the application starts up, i.e. creating a
 "windows" application.

 luckily (by chance, I think) the desired objective can be achieved without
 any change to the haskell
 code as follows, with the support that gcc already provides for a !WinMain
 entry point,
 utilising the wxHaskell example:

 {{{
 > ghc -o HelloWorl.o -fglasgow-exts -c HelloWorld.hs
 > ghc -optl-mwindows -o HelloWorld.exe HelloWorld.o -package wxcore
 }}}

 OK, so what is the issue ? We what if we want to define our own !WinMain
 or utilise the
 !WinMain or other entry point provided by another object file or code.
 According to the
 ghc documentation the way it could be achieved would be, with this example
 ...

 !MyHelloWorld.hs ..

 {{{
 > module Hello where
 >
 > foreign export ccall "runHsMain" runMain :: IO ()
 >
 > runMain = do
 >   putStrLn "Hello World"
 }}}

 and mymain.c

 {{{
 #include "HsFFI.h"
 extern void __stginit_Hello ( void );

 extern void runHsMain();


 int main(int argc, char* argv[])
 {


   hs_init(&argc, &argv);
   hs_add_root(__stginit_Hello);
   runHsMain();

   hs_exit();
   return 0;
 }
 }}}


 {{{
 > ghc -c -fglasgow-exts -o MyHelloWorld.o MyHelloWorld.hs
 > ghc -o hello.exe mymain.c MyHelloWorld.o MyHelloWorld_stub.o
 > hello.exe
 Hello World
 }}}

 all works fine, but dosn't ghc documentation say, the -no-hs-main option
 should be used ? OK so use it

 {{{
 > ghc -no-hs-main -c -fglasgow-exts -o MyHelloWorld.o MyHelloWorld.hs
 > ghc  -no-hs-main -o hello.exe mymain.c MyHelloWorld.o
 MyHelloWorld_stub.o
 > hello.exe
 Hello World
 }}}

 OK, works both with and without -no-hs-main, strange?
 but how about if we want to define our own !WinMain or dllMain etc (i.e.
 no main at all)

 winmain.c:

 {{{
 #include <windows.h>
 #include "HsFFI.h"
 extern void __stginit_Hello ( void );

 extern void runHsMain();

 int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
     LPSTR lpszCmdLine, int nCmdShow)
 {

   hs_init(0, 0);
   hs_add_root(__stginit_Hello);

   hs_exit();
   return 0;
 }
 }}}

 you can use the above haskell hello example or the wxHaskell !HelloWorld
 example
 but with edits to main/module name as per !MyHelloWorld, call it
 !MyHelloWorldW.
 But the above Haskell suffices as a test case, and is used in the
 following.

 linking with winmain, we get this error:

 {{{
 >ghc -no-hs-main -o winhello.exe winmain.c MyHelloWorld.o
 MyHelloWorld_stub.o
 C:/apps/ghc/6.8.2/libHSrts.a(Main.o)(.text+0x7):Main.c: undefined
 reference to `
 __stginit_ZCMain'
 C:/apps/ghc/6.8.2/libHSrts.a(Main.o)(.text+0x36):Main.c: undefined
 reference to
 `ZCMain_main_closure'
 collect2: ld returned 1 exit status
 }}}

 it appears ghc does something like this (normal operation, for a standard
 haskell main)

  * create bootstrapping that initialises the ghc runtime and adds the root
 !__stginit_ZCMain, and runs the haskell main
  * create a "c" main that calls/executes the bootstrapping code
  * the executables entry point will be set by default to the "c" "main"
 procedure

 it seems that linking the haskell object with an object that already
 contains a main symbol will:

  * suppress the creation of bootstrapping code
  * executable entry point still set to the default ("main")

 this behaviour is exhibitted regardless of -no-hs-main option

 When the haskell objects are linked with other objects and even though
 -no-hs-main option is
 specified it appears that ghc:

  * creates bootstrapping that initialises the ghc runtime and adds the
 root !__stginit_ZCMain, and runs the haskell main
  * creates a main that calls/executes the bootstrapping code
  * executable entry point still set to the default ("main")

 i.e. the same behaviour as for "normal" execution, this behaviour appears
 wrong, the behaviour should be:

  * suppress the creation of bootstrapping code (initialisation of haskell
  should be the responsibility of the external code, per guidlines)
  * executable entry point still set to default

 i.e., as in the above example hs_add_root initialises the root module
 (!__stginit_Hello)
 and there is no requirement for an !__stginit_ZCMain.


 you can get the above example to compile and link with ...

 {{{
 >ghc -main-is Hello.runMain -c -fglasgow-exts -o MyHelloWorld.o
 MyHelloWorld.hs

 >ghc -o winhello.exe winmain.c MyHelloWorld.o MyHelloWorld_stub.o
 }}}

 but if this is the wxHaskell !HelloWorld example, you would see that the
 it still starts up as a console
 application and not a !WinMain (windows) application.

 the effect of using th -main-is option is to insert a "!___stginit_ZCMain"
 symbol into the !HelloWorld.o
 object. A "c" "main" will be created, initialising haskell and invoking
 the haskell main Hell.runMain.
 The entry point of the executable will be this "main", i.e. regard,

 [link with ldl-mwindows to set entry to win32,see what happens]
 {{{
 > ghc -main-is Hello.runMain -c -fglasgow-exts -o MyHelloWorld.o
 MyHelloWorld.hs

 > ghc -o winhello.exe winmain.c MyHelloWorld.o MyHelloWorld_stub.o
 }}}

 the above will compile and run but, will not invoke the winmain, rather it
 will invoke the
 automatically generated "main".

 the following

 {{{
 > ghc -main-is Hello.runMain -c -fglasgow-exts -o MyHelloWorld.o
 MyHelloWorld.hs
 > ghc -optl-mwindows -o winhello.exe winmain.c MyHelloWorld.o
 MyHelloWorld_stub.o

 >winhello
 }}}

 will invoke the !WinMain routine as a windows application, (in this
 example a popup will be displayed
 reporting an error "hPutChar invalid arg bad file descriptor", as it
 should), ignoring the haskell
 supplied main/init.

 BUT you shouldn't have to compile the haskell module with -main-is ... in
 order to get the overall exe to link , i.e. the following should work

 {{{
 >ghc -no-hs-main -c -fglasgow-exts -o MyHelloWorld.o MyHelloWorld.hs
 >ghc -optl-mwindows -o winhello.exe winmain.c MyHelloWorld.o
 MyHelloWorld_stub.o
 }}}

 but we get ...

 {{{
 C:/apps/ghc/6.8.2/libHSrts.a(Main.o)(.text+0x7):Main.c: undefined
 reference to `
 __stginit_ZCMain'
 C:/apps/ghc/6.8.2/libHSrts.a(Main.o)(.text+0x36):Main.c: undefined
 reference to
 `ZCMain_main_closure'
 collect2: ld returned 1 exit status
 }}}

 what should be:

  * no-hs-main option should suppress the requirement for a
 !___stginit_ZCMain symbol, this should enable
   the linking of, and specification of an arbitrary entry point into the
 executable external to the
   haskell code.

 i.e. the last example should work.

 the -optl-mwindows on the ghc command line we can flip the .exe entry
 point for the executable to a windows
 entry point, gcc seems to handle it as follows: if the above -mwindows
 option is given then the entry point
 of the executable is set to !WinMainCRTStartup, which in turn calls the
 !WinMain function (if present) or
 the supplied main, it also sets the subsystem to windows.

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/2459>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs

Reply via email to