diff --git a/shakers.cabal b/shakers.cabal
--- a/shakers.cabal
+++ b/shakers.cabal
@@ -1,5 +1,5 @@
 name:                  shakers
-version:               0.0.8
+version:               0.0.9
 synopsis:              Shake helpers.
 description:           Primitive helpers for Shake files.
 homepage:              https://github.com/swift-nav/shakers
diff --git a/src/Development/Shakers.hs b/src/Development/Shakers.hs
--- a/src/Development/Shakers.hs
+++ b/src/Development/Shakers.hs
@@ -15,6 +15,7 @@
   , cmdArgsDir_
   , stack
   , stack_
+  , stackExec
   , stackExec_
   , git
   , m4
@@ -23,13 +24,10 @@
   , ssh_
   , sshDir
   , sshDir_
-  , touchFile
-  , copyFileChanged'
   , fake
   , fake'
   , meta
   , preprocess
-  , preprocess'
   , mirror
   , getHashedVersion
   , stackRules
@@ -125,6 +123,11 @@
 
 -- | Stack exec command.
 --
+stackExec :: String -> [String] -> Action String
+stackExec cmd' args = stack $ "exec" : cmd' : "--" : args
+
+-- | Stack exec command without return.
+--
 stackExec_ :: String -> [String] -> Action ()
 stackExec_ cmd' args = stack_ $ "exec" : cmd' : "--" : args
 
@@ -178,27 +181,14 @@
 gitVersion :: Action String
 gitVersion = git [ "describe", "--tags", "--abbrev=0" ]
 
--- | Touch a file for fake files.
---
-touchFile :: FilePath -> Action ()
-touchFile = flip writeFile' mempty
-
--- | Copy a file if changed, creating parent directories.
---
-copyFileChanged' :: FilePath -> FilePath -> Action ()
-copyFileChanged' a b = do
-  liftIO $ createDirectoryIfMissing True $ dropFileName b
-  copyFileChanged a b
-
 -- | Use a fake file to keep track of the last time an file-free action ran.
 --
 fake :: [FilePattern] -> String -> ([FilePath] -> Action ()) -> Rules ()
 fake pats target act =
   fakeFile target %> \out -> do
     files <- getDirectoryFiles "." pats
-    need files
     act files
-    touchFile out
+    writeFile' out mempty
 
 -- | Wraps fake with a phony target.
 --
@@ -240,7 +230,8 @@
 mirror pats =
   fake' pats "mirror" $ mapM_ $ \file -> do
     dir <- mirrorDir
-    copyFileChanged' file $ dir </> file
+    liftIO $ createDirectoryIfMissing True dir
+    copyFileChanged file (dir </> file)
 
 -- | Build a hash version from a directory and file pattern.
 --
@@ -348,7 +339,7 @@
 
   -- | cabal
   --
-  preprocess' file $ do
+  preprocess file (file <.> "m4") $ do
     need [ metaFile "gitVersion" ]
     version <- gitVersion
     return [ ("VERSION", version) ]
