Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Telling cabal where the main module is

Tags:

haskell

cabal

I have a project with this structure:

foo.cabal
src/
    Foo/
        Main.hs

and part of foo.cabal looks like this:

executable foo
  main-is:             Foo/Main.hs
  hs-source-dirs:      src

Main.hs has the package name Foo.Main. When I build it cabal compiles everything but doesn't create an executable because it says there is no main module.

Warning: output was redirected with -o, but no output will be generated
because there is no Main module.

What am I doing wrong?

[EDIT] If I move Main up a level and change foo.cabal to read main-is: Main.hs it works. So can I not have a nested module name for Main?

like image 571
jaybee Avatar asked Dec 21 '14 16:12

jaybee


2 Answers

The Main module must be called Main, not Foo.Main or anything else. If you want Foo.Main, then rename main in it to something like defaultMain, then make a top level Main module that imports Foo.Main (defaultMain) and defines main = defaultMain, such as:

src/
    Foo/
        Main.hs
    Main.hs
foo.cabal

Where

-- src/Foo/Main.hs
module Foo.Main
    ( defaultMain
    ) where

defaultMain :: IO ()
defaultMain = putStrLn "Hello, world!"

And

-- src/Main.hs
module Main where

import Foo.Main (defaultMain)

main :: IO ()
main = defaultMain

Alternatively, you could keep it Foo.Main.main and just import it qualified.

like image 136
bheklilr Avatar answered Oct 20 '22 22:10

bheklilr


Cabal's main-is: specifies only the filename from which to build the module containing the entrypoint (default Main.main); it does not allow changing that default.

Changing the default is compiler-specific, but if you are using GHC you can do this by passing a compiler command-line option: to your Cabal file executable definition add ghc-options: -main-is Foo. You may also use a different top-level function as the entry point: ghc-options: Foo.startup for example. See -main-is <thing> in the documentation for more details.

If you're using a package.yaml (as used by hpack/Stack/etc.) you may specify for main: either:

  1. A .hs filename, in which case that will be directly used on the main-is: line in the generated Cabal file; or
  2. A module name or module and exported definition name (e.g., Foo or Foo.startup) in which case the appropriate ghc-options: -main-is ... will be added to the generated Cabal file and main-is: will be a filename generated from the module name (e.g. main-is: Foo.hs).
like image 27
cjs Avatar answered Oct 20 '22 22:10

cjs