I've been doing some more work with atspkg and polyglot builds. It is now in slightly better shape, and it gives us the ability to call ATS code in Haskell almost painlessly.

Cabal Builds

Cabal is the common architectures for building and install Haskell libraries. It is sophisticated, accompanying a massive Cabal library. Since it's written in Haskell, it's relatively easy to just plug everything in.

We'll be using atspkg for our build, as usual. This will handle package management and dependency resolution for the ATS side of things. The main disadvantage is that your package's builds will be noticeably longer.

Our first step will be to prepare a polyglot project using pi:

pi git vmchale/haskell-ats ats-library
cd ats-library/

Take it for a test drive with

cabal new-test
cabal new-bench

You should see something exciting: the Haskell package builds with ATS dependencies! The Setup.hs file runs a build process defined by atspkg.dhall, installing the necessary compiler and any package dependencies.

Opening up atspkg.dhall, you should see the following:

let prelude = https://raw.githubusercontent.com/vmchale/atspkg/master/ats-pkg/dhall/atspkg-prelude.dhall

in prelude.default //
  { libraries =
    [
      prelude.lib //
      { name = "ats-library"
      , src = [ "ats-src/ats-library.dats" ]
      , libTarget = "dist-newstyle/lib/libats-library.a"
      }
    ]
  }

This works in concert with the following in our .cabal file:

extra-source-files: ats-src/*.dats
                  , dist-newstyle/lib/empty
                  , atspkg.dhall

custom-setup
  setup-depends:   base
                 , ats-pkg >= 2.6.1.0
                 , Cabal

library
  hs-source-dirs:      src

library
  extra-libraries:     ats-library
  extra-lib-dirs:      ./dist-newstyle/lib
  hs-source-dirs:      src
  exposed-modules:     Lib
  build-depends:       base >= 4.7 && < 5
  default-language:    Haskell2010
  if flag(development)
    ghc-options:       -Werror
  if impl(ghc >= 8.0)
    ghc-options:       -Wincomplete-uni-patterns -Wincomplete-record-updates -Wcompat 
  ghc-options:         -Wall

And that's it! Our ATS source code now builds inside a Haskell package. We can even modify atspkg.dhall to add dependencies or multiple source files:

let prelude = https://raw.githubusercontent.com/vmchale/atspkg/master/ats-pkg/dhall/atspkg-prelude.dhall

in prelude.default //
  { libraries =
    [
      prelude.lib //
      { name = "ats-library"
      , src = [ "ats-src/ats-library0.dats", "ats-src/ats-library1.dats" ]
      , libTarget = "dist-newstyle/lib/libats-library.a"
      }
    ]
  , dependencies = prelude.mapPlainDeps [ "atscntrb-hx-intinf" ]
  }

As you can see, this is a powerful tool for cross-language builds. I suspect that Haskell ecosystem will benefit immensely from such fluent, safe access to low-level functionality.