Cabal: a Haskell eDSL?

· 2 min read

While I’m working on more radical ideas about Hackage and Cabal, I thought I’d stick out a couple more palatable ones now.

Cabal (almost always?) links an executable whenever cabal install <some package> is run. Combined with a slow linker such as OSX’s… and well, it’s slow. The generated application is almost always a shim around the (compiled) Cabal library, so linker step can probably be removed entirely. The general design permits the installer to select which version of the Cabal library to use, cabal-install just provides the bootstrap. I think this could be done done with runhaskell or runghc instead.

When porting our build system from cabal-waf to shake-install I decided to carry forward WAF’s use of the host language (WAF uses Python) as the Makefile language. Haskell seems like a natural way to describe the build hierarchy for Haskell projects, though shake-install reads dependencies from .cabal files. Could this idea be further extended to replace Cabal’s language entirely with an eDSL? Link in GHC as an interpreter and you’ve got a fast Haskell build system.

Monadic, applicative or monoidal. This is just an idea without implementation.

import Cabal

-- equivalent of 'Main :: IO ()' for Cabal installers
cabal :: Cabal Package
cabal = package "sample" $ do
  language Haskell2010
  license BSD3

  library "demo" $ do
    depends $ do
      "base"         (==? any)
      "stm"          (>=? "2.3")
      "transformers" ((>=? "1.0") <> (<=? "2.0"))

    options GHC $ do
      "-Wall"
      "-fno-warn-foo"

    modules $ do
      exposed "MyPackage.MyExposedModule"
      hidden  "MyPackage.MyHiddenModule"

Comments

7 comments · 3 replys · 5 participants

  1. Avatar for meteficha
    meteficha Permalink to comment 740896157

    Using a finally tagless approach we could build Cabal file analyzers as interpreters =).

  2. Avatar for Mikhail Glushenkov
    Mikhail Glushenkov Permalink to comment 740936983

    Cabal (almost always?) links an executable whenever cabal install 'some package' is run.

    Only when the build-type is not Simple, which is relatively rare.

    Could this idea be further extended to replace Cabal’s language entirely with an eDSL?

    I believe that this idea was discussed and rejected during the initial design stage (2006?). Maybe Duncan will answer in more detail if you ask on the mailing list; or you can just search in the archives.

    1. Avatar for Nathan Howell
      Nathan Howell Permalink to comment 740959499

      Only when the build-type is not Simple, which is relatively rare.

      Take a look at the execve output from running 'cabal configure' on mtl-2.1.2, a Simple project. It definitely links something, though the result doesn't appear to be used. https://gist.github.com/c93...

      1. Avatar for Mikhail Glushenkov
        Mikhail Glushenkov Permalink to comment 740992430

        This is configureLd' in Distribution.Simple.GHC - basically a configure check. The program it compiles and links is just "int foo() {}". This is done once per 'cabal install' invocation, as opposed to once per a single package installation (see calls to configCompiler in cabal-install/Main.hs).

        1. Avatar for Nathan Howell
          Nathan Howell Permalink to comment 741208069

          Got it. My bad experience from this was using a Cabal sandbox that doesn't use 'cabal install'. Modifying a common library triggered a very large number of reconfigures, and lots of needless linking. We use a different sandbox now so it's not a problem.