executables with a C main function #497

bos opened this Issue May 24, 2012 · 5 comments


None yet

4 participants

bos commented May 24, 2012

(Imported from Trac #504, reported by @dcoutts on 2009-02-22)

We would like to be able to do:

executable blah
  main-is: main.c
Either for pure C programs or mixed C/Haskell programs with main in the C code rather than Haskell code.


Until this is implemented one can use a main in Haskell that calls out to the C main function. For example:


int real_main () {
  return 42;
import System.Exit
import Foreign.C
main = real_main >>= exitWith . ExitFailure . fromIntegral
foreign import ccall "real_main" real_main :: IO CInt
name: c-main
version: 0.0
build-type: Simple
cabal-version: >= 1.2
extra-source-files: main.h
executable c-main
  main-is: Main.hs
  c-sources: main.c
  includes: main.h
  extensions: ForeignFunctionInterface
  build-depends: base

Implementation notes

At the moment Cabal's "Simple" build system requires main-is to specify a .hs or .lhs file (though it does allow that to be generated by a pre-processor). If we lift that restriction the first thing to go wrong will be that ghc --make does not work with -no-hs-main. We will have to do the build and link steps separately (which is probably a good thing anyway). We would use ghc --make to compile all Haskell modules to .o files and then invoke ghc in batch mode passing it all the .o files (from Haskell and C modules) and -package flags. If we're using a C main then we'd do the link step with -no-hs-main.

@ghost ghost was assigned May 24, 2012
bos commented May 24, 2012

(Imported comment by jcpetruzza on 2009-02-22)

I believe the lack of this feature makes SDL-based applications currently unbuildable on OS X.

On OS X, SDL.h "renames" (using a macro) the "main" function to "_SDL_main"; the latter is then called from a "main" function defined in libSDLmain.a (with which every SDL-based program has to be linked). For this to work with Haskell, the workaround suggested in the SDL package is to use a C wrapper which includes SDL.h and defines a "main" function that calls, via the FFI, the entry-point of the haskell application.

Notice that the workaround suggested in the ticket description does not work in this case, since the "main" function defined in the haskell wrapper would collide with the one in libSDLmain.a when linked.

Observe also, that for this feature to work in a mixed Haskell/C setting like the one described, the .c program cannot be compiled first (as I think is the case with declared c-files), since it will need to #include the stubs generated from processing FFI export declarations.

bos commented May 24, 2012

(Imported comment by @dankna on 2011-04-18)

I have submitted a patch for this with darcs send. My patch simply relaxes the restriction on the name of the file given to main-is: to also allow known C-language extensions. The ticket description suggested that -no-hs-main might be required in this situation, but that seems to no longer be the case. There might still be a problem when the entry point is WinMain?() instead of main(); see GHC ticket #2459 (at http://hackage.haskell.org/trac/ghc/ticket/2459 ). I'm not really set up to test that case.

ezyang commented Oct 23, 2012

Adapted dankna's patchset to Git. Modern GHC does need -no-hs-main.



IIUC, this is fixed. OK to close this ticket?

ttuegel commented Apr 23, 2015

Appears to be resolved.

@ttuegel ttuegel closed this Apr 23, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment