diff --git a/shake-ats.cabal b/shake-ats.cabal
--- a/shake-ats.cabal
+++ b/shake-ats.cabal
@@ -1,48 +1,55 @@
-name:                shake-ats
-version:             1.5.0.6
-synopsis:            Utilities for building ATS projects with shake
-description:         Various helper functions for building [ATS](http://www.ats-lang.org/) with the [shake](http://shakebuild.com/) library
-homepage:            https://github.com/vmchale/shake-ats#readme
-license:             BSD3
-license-file:        LICENSE
-author:              Vanessa McHale
-maintainer:          vamchale@gmail.com
-copyright:           Copyright: (c) 2018 Vanessa McHale
-category:            Development, Build, ATS, Shake
-build-type:          Simple
-extra-doc-files:     README.md
-cabal-version:       1.18
+cabal-version: 1.18
+name: shake-ats
+version: 1.5.0.7
+license: BSD3
+license-file: LICENSE
+copyright: Copyright: (c) 2018 Vanessa McHale
+maintainer: vamchale@gmail.com
+author: Vanessa McHale
+homepage: https://github.com/vmchale/shake-ats#readme
+synopsis: Utilities for building ATS projects with shake
+description:
+    Various helper functions for building [ATS](http://www.ats-lang.org/) with the [shake](http://shakebuild.com/) library
+category: Development, Build, ATS, Shake
+build-type: Simple
+extra-doc-files: README.md
 
-Flag development {
-  Description: Enable `-Werror`
-  manual: True
-  default: False
-}
+source-repository head
+    type: darcs
+    location: https://hub.darcs.net/vmchale/ats
 
-library
-  hs-source-dirs:      src
-  exposed-modules:     Development.Shake.ATS
-  other-modules:       Development.Shake.ATS.Type
-                     , Development.Shake.ATS.Rules
-                     , Development.Shake.ATS.Environment
-                     , Development.Shake.ATS.Generate
-  build-depends:       base >= 4.7 && < 5
-                     , language-ats >= 0.3.0.3
-                     , shake-ext >= 2.6.0.0
-                     , hs2ats >= 0.2.0.1
-                     , directory
-                     , microlens
-                     , text
-                     , dependency
-                     , shake
-                     , binary
-  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
+flag development
+    description:
+        Enable `-Werror`
+    default: False
+    manual: True
 
-source-repository head
-  type:     darcs
-  location: https://hub.darcs.net/vmchale/ats
+library
+    exposed-modules:
+        Development.Shake.ATS
+    hs-source-dirs: src
+    other-modules:
+        Development.Shake.ATS.Type
+        Development.Shake.ATS.Rules
+        Development.Shake.ATS.Environment
+        Development.Shake.ATS.Generate
+    default-language: Haskell2010
+    ghc-options: -Wall
+    build-depends:
+        base >=4.7 && <5,
+        language-ats,
+        shake-ext >=2.7.0.0,
+        hs2ats >=0.2.0.1,
+        directory -any,
+        microlens -any,
+        text -any,
+        dependency -any,
+        shake -any,
+        binary -any
+    
+    if flag(development)
+        ghc-options: -Werror
+    
+    if impl(ghc >=8.0)
+        ghc-options: -Wincomplete-uni-patterns -Wincomplete-record-updates
+                     -Wcompat
diff --git a/src/Development/Shake/ATS.hs b/src/Development/Shake/ATS.hs
--- a/src/Development/Shake/ATS.hs
+++ b/src/Development/Shake/ATS.hs
@@ -5,27 +5,22 @@
 {-# LANGUAGE TypeSynonymInstances #-}
 
 module Development.Shake.ATS ( -- * Shake Rules
-                               cgen
-                             , cgenPretty
-                             , cleanATS
+                               cleanATS
                              , atsBin
                              , atsLex
                              , cabalExport
-                             -- * Actions
-                             , patsHome
+                             , cgen
+                             , genATS
                              -- * Helper functions
                              , getSubdirs
-                             , ccToString
-                             , ccFromString
                              , ccToDir
-                             , compatible
-                             , host
+                             , withPF
+                             -- * Environment/configuration
                              , patscc
                              , patsopt
                              -- Types
-                             , Version (..)
                              , ForeignCabal (..)
-                             , BinaryTarget (..)
+                             , ATSTarget (..)
                              , ATSToolConfig (..)
                              , CCompiler (..)
                              , ArtifactType (..)
@@ -53,12 +48,6 @@
 import           System.Environment                (getEnv)
 import           System.Exit                       (ExitCode (ExitSuccess))
 
--- | Whether generated libraries are to be considered compatible.
-compatible :: CCompiler -> CCompiler -> Bool
-compatible GCCStd Clang = True
-compatible Clang GCCStd = True
-compatible x y          = x == y
-
 -- | Run @patsopt@ given information about various things
 atsCommand :: CmdResult r => ATSToolConfig
                           -> String -- ^ Source file
@@ -67,11 +56,21 @@
 atsCommand tc sourceFile out = do
     path <- liftIO $ getEnv "PATH"
     home' <- home tc
-    h <- liftIO $ getEnv "HOME"
-    let env = patsEnv h home' path
+    let env = patsEnv home' path
     patsc <- patsopt tc
+
     command env patsc ["--output", out, "-dd", sourceFile, "-cc"]
 
+-- | Filter any generated errors with @pats-filter@.
+withPF :: Bool -> Action (Exit, Stderr String, Stdout String) -> Action (Exit, Stderr String, Stdout String)
+withPF False = id
+withPF True = \act -> do
+    ret@(Exit c, Stderr err, Stdout _) <- act :: Action (Exit, Stderr String, Stdout String)
+    cmd_ [Stdin err] Shell "pats-filter"
+    if c /= ExitSuccess
+        then error "patsopt failure"
+        else pure ret
+
 gcFlag :: Bool -> String
 gcFlag False = "-DATS_MEMALLOC_LIBC"
 gcFlag True  = "-DATS_MEMALLOC_GCBDW"
@@ -86,9 +85,10 @@
         liftIO $ createDirectoryIfMissing True (home' ++ "/" ++ takeDirectory dep)
         liftIO $ copyFile dep (home' ++ "/" ++ dep)
 
--- This is the @$PATSHOMELOCS@ variable to be passed to the shell.
-patsHomeLocs :: FilePath -> Int -> String
-patsHomeLocs _ n = intercalate ":" $ (<> ".atspkg/contrib") . ("./" <>) <$> g
+-- | This is the @$PATSHOMELOCS@ variable to be passed to the shell.
+patsHomeLocs :: Int
+             -> String
+patsHomeLocs n = intercalate ":" $ (<> ".atspkg/contrib") . ("./" <>) <$> g
     where g = [ join $ replicate i "../" | i <- [0..n] ]
 
 makeCFlags :: [String] -- ^ Inputs
@@ -129,6 +129,7 @@
     h' <- pkgHome cc'
     home' <- home tc
     let libs' = ("atslib" :) $ bool libs ("gc" : libs) gc
+    -- TODO only include /ccomp/atslib/lib if it's not a cross build
     pure $ CConfig [h ++ "ccomp/runtime/", h, h' ++ "include", ".atspkg/contrib"] libs' [h' ++ "lib", home' ++ "/ccomp/atslib/lib"] extras
 
 home :: MonadIO m => ATSToolConfig -> m String
@@ -136,11 +137,11 @@
     h <- patsHome (compilerVer tc)
     pure $ h ++ "lib/ats2-postiats-" ++ show (libVersion tc)
 
-patsEnv :: FilePath -> FilePath -> FilePath -> [CmdOption]
-patsEnv h home' path = EchoStderr False :
+patsEnv :: FilePath -> FilePath -> [CmdOption]
+patsEnv home' path = EchoStderr False :
     zipWith AddEnv
         ["PATSHOME", "PATH", "PATSHOMELOCS"]
-        [home', home' ++ "/bin:" ++ path, patsHomeLocs h 5]
+        [home', home' ++ "/bin:" ++ path, patsHomeLocs 5]
 
 atsToC :: FilePath -> FilePath
 atsToC = (-<.> "c") . (".atspkg/c/" <>)
@@ -154,17 +155,14 @@
 doLib Executable = pure mempty
 doLib _          = id
 
-atsBin :: BinaryTarget -> Rules ()
-atsBin tgt@BinaryTarget{..} = do
+atsBin :: ATSTarget -> Rules ()
+atsBin ATSTarget{..} = do
 
-    unless (null linkTargets) $
-        mapM_ (uncurry genLinks) linkTargets
+    mapM_ (uncurry genLinks) linkTargets
 
-    unless (null genTargets) $
-        mapM_ (uncurry3 genATS) genTargets
+    mapM_ (uncurry3 genATS) genTargets
 
-    unless (null hsLibs) $
-        mapM_ cabalExport hsLibs
+    mapM_ cabalExport hsLibs
 
     let cTargets = atsToC <$> src
 
@@ -178,7 +176,9 @@
 
     cconfig' <- cconfig toolConfig libs gc (makeCFlags cFlags mempty (pure undefined) gc)
 
-    zipWithM_ (atsCGen toolConfig tgt) src cTargets
+    let atsGen = (snd <$> linkTargets) <> ((^._2) <$> genTargets)
+        atsExtras = otherDeps <> (TL.unpack . objectFile <$> hsLibs)
+    zipWithM_ (cgen toolConfig atsExtras atsGen) src cTargets
 
     doLib tgtType (zipWithM_ (objectFileR (cc toolConfig) cconfig') cTargets (h' cTargets))
 
@@ -192,73 +192,40 @@
 
         unit $ g tgtType (cc toolConfig) (h' cTargets) binTarget cconfig''
 
-atsCGen :: ATSToolConfig
-        -> BinaryTarget
-        -> FilePath -- ^ ATS source
-        -> FilePattern -- ^ Pattern for C file to be generated
-        -> Rules ()
-atsCGen tc BinaryTarget{..} atsSrc cFiles =
+cgen :: ATSToolConfig
+     -> [FilePath] -- ^ Extra files to track
+     -> [FilePath] -- ^ ATS source that may be generated.
+     -> FilePath -- ^ ATS source
+     -> FilePattern -- ^ Pattern for C file to be generated
+     -> Rules ()
+cgen toolConfig extras atsGens atsSrc cFiles =
     cFiles %> \out -> do
 
         -- tell shake which files to track and copy them to the appropriate
         -- directory
-        need (otherDeps ++ (TL.unpack . objectFile <$> hsLibs))
-        sources <- (<> cDeps) <$> transitiveDeps ((snd <$> linkTargets) <> ((^._2) <$> genTargets)) [atsSrc]
-        need sources
-        copySources tc sources
-
-        atsCommand tc atsSrc out
-
-cgen :: ATSToolConfig
-     -> [String] -- ^ Additional source files
-     -> FilePath -- ^ Directory containing ATS source code
-     -> Rules ()
-cgen tc extras dir =
-
-    "//*.c" %> \out -> do
         need extras
-        let sourceFile = dir ++ "/" ++ (takeBaseName out -<.> "dats")
-        handleSource tc sourceFile
-        atsCommand tc sourceFile out
+        sources <- transitiveDeps atsGens [atsSrc]
+        need sources
+        copySources toolConfig sources
 
-handleSource :: ATSToolConfig -> FilePath -> Action ()
-handleSource tc sourceFile = do
-    sources <- transitiveDeps [] [sourceFile]
-    need sources
-    copySources tc sources
+        atsCommand toolConfig atsSrc out
 
 -- | This provides rules for generating C code from ATS source files in the
 trim :: String -> String
 trim = init . drop 1
 
 -- | Print any errors to standard error.
-maybeError :: (MonadIO m) => Either ATSError b -> m ()
-maybeError Right{}  = pure ()
-maybeError (Left y) = printErr y
+maybeError :: (MonadIO m) => FilePath -> Either ATSError b -> m ()
+maybeError _ Right{}  = pure ()
+maybeError p (Left y) = warnErr p y
 
 transitiveDeps :: (MonadIO m) => [FilePath] -> [FilePath] -> m [FilePath]
 transitiveDeps _ [] = pure []
 transitiveDeps gen ps = fmap join $ forM ps $ \p -> if p `elem` gen then pure mempty else do
     contents <- liftIO $ readFile p
-    let (ats, err) = (fromRight mempty &&& maybeError) . parse $ contents
+    let (ats, err) = (fromRight mempty &&& maybeError p) . parseM $ contents
     err
     let dir = takeDirectory p
     deps <- filterM (\f -> ((f `elem` gen) ||) <$> (liftIO . doesFileExist) f) $ fixDir dir . trim <$> getDependencies ats
     deps' <- transitiveDeps gen deps
     pure $ (p:deps) ++ deps'
-
--- | This uses @pats-filter@ to prettify the errors.
-cgenPretty :: ATSToolConfig
-           -> FilePath
-           -> Rules ()
-cgenPretty tc dir =
-
-    "//*.c" %> \out -> do
-
-        let sourceFile = dir ++ "/" ++ (takeBaseName out -<.> "dats")
-        handleSource tc sourceFile
-        (Exit c, Stderr err, Stdout _) :: (Exit, Stderr String, Stdout String) <- atsCommand tc sourceFile out
-        cmd_ [Stdin err] Shell "pats-filter"
-        if c /= ExitSuccess
-            then error "patscc failure"
-            else pure ()
diff --git a/src/Development/Shake/ATS/Generate.hs b/src/Development/Shake/ATS/Generate.hs
--- a/src/Development/Shake/ATS/Generate.hs
+++ b/src/Development/Shake/ATS/Generate.hs
@@ -6,7 +6,7 @@
 import           Lens.Micro
 
 generateLinks :: String -> Either ATSError String
-generateLinks = fmap (printATS . generateLinks') . parse
+generateLinks = fmap (printATS . generateLinks') . parseM
 
 generateLinks' :: ATS a -> ATS a
 generateLinks' (ATS ds) = ATS (fmap g ds <> [macDecl]) --  ATS [Local undefined (ATS (fmap g ds <> [macDecl])) (ATS mempty)]
diff --git a/src/Development/Shake/ATS/Rules.hs b/src/Development/Shake/ATS/Rules.hs
--- a/src/Development/Shake/ATS/Rules.hs
+++ b/src/Development/Shake/ATS/Rules.hs
@@ -7,19 +7,19 @@
                                    ) where
 
 import           Control.Monad
-import           Data.List                      (isPrefixOf)
 import           Data.Semigroup                 (Semigroup (..))
 import qualified Data.Text.Lazy                 as TL
 import           Development.Shake              hiding (doesDirectoryExist)
 import           Development.Shake.ATS.Generate
-import           Development.Shake.ATS.Type     hiding (BinaryTarget (..))
+import           Development.Shake.ATS.Type     hiding (ATSTarget (..))
 import           Development.Shake.Cabal
 import           Development.Shake.FilePath
+import           Development.Shake.Version
 import           Language.ATS.Generate
 import           System.Directory
 
 -- | Given a plain Haskell source file, generate a @.sats@ file containing
--- analogous types.
+-- the equivalent types.
 genATS :: FilePath -- ^ Haskell source
        -> FilePath -- ^ @.sats@ file to generate
        -> Bool -- ^ Whether to call cpphs preprocessor
@@ -46,7 +46,12 @@
             ss <- mapM getSubdirs ds'
             pure $ ds' <> join ss
 
--- TODO cabal exports can happen concurrently w/ compiler & whatnot
+-- libHSforeign-0.1.0.0-inplace-ghc8.2.2.so
+-- libHSforeign-0.1.0.0-inplace.a
+-- Foreign_stub.h
+
+-- | These rules take a @.cabal@ file and the @.o@ file to be produced from
+-- them, building the @.o@ file.
 cabalExport :: ForeignCabal -> Rules ()
 cabalExport (ForeignCabal cbp' cf' obf') = do
 
@@ -56,27 +61,32 @@
         obfDir = takeDirectory (obf -<.> "hs")
         libName = takeBaseName cf
 
-    trDeps <- liftIO $ getCabalDeps cf
+    (v, trDeps) <- liftIO $ getCabalDeps cf
     obf %> \out -> do
 
         need (cf : fmap ((obfDir <> "/") <>) trDeps)
-        command_ [Cwd obfDir] "cabal" ["new-build", "all", "-O2"]
+        command_ [Cwd obfDir] "cabal" ["new-build", "all"]
 
+        ghcV <- quietly ghcVersion
         let subdir = takeDirectory cbp ++ "/"
-            correctDir = (libName `isPrefixOf`)
+            correctDir = (== "build")
             endsBuild = correctDir . last . splitPath
-        dir <- filter endsBuild <$> liftIO (getSubdirs $ subdir ++ "dist-newstyle/build")
-        let obj = head dir ++ "/opt/build/" ++ takeFileName obf
+            pkgDir = subdir ++ "dist-newstyle/build/" ++ platform ++ "/ghc-" ++ ghcV ++ "/" ++ libName ++ "-" ++ showVersion v ++ "/"
+
+        dir <- filter endsBuild <$> liftIO (getSubdirs pkgDir)
+        let obj = head dir ++ "/" ++ takeFileName obf
         liftIO $ copyFile obj out
 
         let hdr = dropExtension obj ++ "_stub.h"
         liftIO $ copyFile hdr (takeDirectory out ++ "/" ++ takeFileName hdr)
 
 -- | Build a @.lats@ file.
-atsLex :: FilePattern -> Rules ()
-atsLex fp =
+atsLex :: FilePath -- ^ Filepath of @.lats@ file
+       -> FilePattern -- ^ File pattern for generated output
+       -> Rules ()
+atsLex latsIn fp =
     fp %> \out -> do
-        lats <- liftIO $ readFile (out -<.> "lats")
+        lats <- liftIO $ readFile latsIn
         (Stdout contents) <- command [Stdin lats] "atslex" []
         liftIO $ writeFile out contents
 
diff --git a/src/Development/Shake/ATS/Type.hs b/src/Development/Shake/ATS/Type.hs
--- a/src/Development/Shake/ATS/Type.hs
+++ b/src/Development/Shake/ATS/Type.hs
@@ -5,7 +5,7 @@
 
 module Development.Shake.ATS.Type ( ForeignCabal (..)
                                   , Version (..)
-                                  , BinaryTarget (..)
+                                  , ATSTarget (..)
                                   , ArtifactType (..)
                                   , ATSToolConfig (..)
                                   ) where
@@ -59,19 +59,18 @@
                                    } deriving (Generic, Binary)
 
 -- | Type for binary and library builds with ATS.
-data BinaryTarget = BinaryTarget { cFlags      :: [String] -- ^ Flags to be passed to the C compiler
-                                 , toolConfig  :: ATSToolConfig
-                                 , gc          :: Bool -- ^ Whether to configure build for use with the garbage collector.
-                                 , libs        :: [String] -- ^ Libraries against which to link
-                                 , src         :: [String] -- ^ ATS source files. If building an executable, at most one may contain @main0@.
-                                 , hsLibs      :: [ForeignCabal] -- ^ Cabal-based Haskell libraries
-                                 , genTargets  :: [(String, String, Bool)] -- ^ Files to be run through @hs2ats@.
-                                 , linkTargets :: [(String, String)] -- ^ Targets for @_link.hats@ generation.
-                                 , binTarget   :: String -- ^ Binary target
-                                 , cDeps       :: [String] -- ^ C files necessary to compile the target
-                                 , otherDeps   :: [String] -- ^ Other files necessary to compile target
-                                 , tgtType     :: ArtifactType -- ^ Build type
-                                 } deriving (Generic, Binary)
+data ATSTarget = ATSTarget { cFlags      :: [String] -- ^ Flags to be passed to the C compiler
+                           , toolConfig  :: ATSToolConfig
+                           , gc          :: Bool -- ^ Whether to configure build for use with the garbage collector.
+                           , libs        :: [String] -- ^ Libraries against which to link
+                           , src         :: [String] -- ^ ATS source files. If building an executable, at most one may contain @main0@.
+                           , hsLibs      :: [ForeignCabal] -- ^ Cabal-based Haskell libraries
+                           , genTargets  :: [(String, String, Bool)] -- ^ Files to be run through @hs2ats@.
+                           , linkTargets :: [(String, String)] -- ^ Targets for @_link.hats@ generation.
+                           , binTarget   :: String -- ^ Binary target
+                           , otherDeps   :: [String] -- ^ Other files necessary to compile target
+                           , tgtType     :: ArtifactType -- ^ Build type
+                           } deriving (Generic, Binary)
 
 -- | Data type containing information about Haskell components of a build.
 data ForeignCabal = ForeignCabal { projectFile :: Maybe TL.Text -- ^ @cabal.project@ file to track
