diff --git a/shake-ext.cabal b/shake-ext.cabal
--- a/shake-ext.cabal
+++ b/shake-ext.cabal
@@ -1,7 +1,7 @@
 name:                shake-ext
-version:             0.1.0.1
-synopsis:            Helper functions for linting with [shake](http://shakebuild.com/) 
-description:         This package provides several linters out of the box, as well as several helper functions for build ATS projects.
+version:             0.2.0.0
+synopsis:            Helper functions for linting with shake 
+description:         This package provides several linters out of the box, as well as functionality for building ATS projects with [shake](http://shakebuild.com/).
 homepage:            https://hub.darcs.net/vmchale/shake-ext
 license:             BSD3
 license-file:        LICENSE
@@ -24,26 +24,16 @@
   hs-source-dirs:      src
   exposed-modules:     Development.Shake.FileDetect
                      , Development.Shake.Linters
+                     , Development.Shake.ATS
   build-depends:       base >= 4.8 && < 5
                      , shake
+                     , ats-format >= 0.2.0.2
   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
-
--- test-suite continued-fractions-test
-  -- type:                exitcode-stdio-1.0
-  -- hs-source-dirs:      test
-  -- main-is:             Spec.hs
-  -- build-depends:       base
-                     -- , continued-fraction
-                     -- , hspec
-  -- if flag(development)
-    -- ghc-options: -Werror
-  -- ghc-options:         -threaded -rtsopts -with-rtsopts=-N -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates -Wcompat
-  -- default-language:    Haskell2010
 
 source-repository head
   type:     darcs
diff --git a/src/Development/Shake/ATS.hs b/src/Development/Shake/ATS.hs
new file mode 100644
--- /dev/null
+++ b/src/Development/Shake/ATS.hs
@@ -0,0 +1,52 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module Development.Shake.ATS ( cgen
+                             , cgenPretty
+                             ) where
+
+import           Control.Monad              (filterM)
+import           Data.Either                (fromRight)
+import           Development.Shake
+import           Development.Shake.FilePath
+import           Language.ATS
+import           System.Exit                (ExitCode (ExitSuccess))
+
+atsCommand :: CmdResult r => String -> String -> Action r
+atsCommand sourceFile out = command atsArgs "patsopt" ["--output", out, "-dd", sourceFile, "-cc"]
+    where atsArgs = [EchoStderr False, AddEnv "PATSHOME" "/usr/local/lib/ats2-postiats-0.3.8"]
+
+-- | This provides rules for generating C code from ATS source files in the
+-- @ats-src@ directory.
+cgen :: Rules ()
+cgen = do
+
+    atsDeps
+
+    "//*.c" %> \out -> do
+        let sourceFile = "ats-src/" ++ (dropDirectory1 out -<.> "dats")
+        need [sourceFile]
+        atsCommand sourceFile out
+
+atsDeps :: Rules ()
+atsDeps =
+
+    ["//*.dats", "//*.sats"] |%> \out -> do
+        contents <- liftIO $ readFile out
+        let ats = fromRight mempty . parseATS . lexATS $ contents
+        deps <- filterM doesFileExist $ getDependencies ats
+        need deps
+
+-- | This uses @pats-filter@ to prettify the errors.
+cgenPretty :: Rules ()
+cgenPretty = do
+
+    atsDeps
+
+    "//*.c" %> \out -> do
+
+        let sourceFile = "ats-src/" ++ (dropDirectory1 out -<.> "dats")
+        need [sourceFile]
+        (Exit c, Stderr _) :: (Exit, Stderr String) <- atsCommand sourceFile out
+        if c /= ExitSuccess
+            then error "patscc failure"
+            else pure ()
