diff --git a/hpack.cabal b/hpack.cabal
--- a/hpack.cabal
+++ b/hpack.cabal
@@ -3,7 +3,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           hpack
-version:        0.13.0
+version:        0.14.0
 synopsis:       An alternative format for Haskell packages
 category:       Development
 homepage:       https://github.com/sol/hpack#readme
diff --git a/src/Hpack.hs b/src/Hpack.hs
--- a/src/Hpack.hs
+++ b/src/Hpack.hs
@@ -1,6 +1,9 @@
 {-# LANGUAGE CPP #-}
 module Hpack (
   hpack
+, hpackResult
+, Result(..)
+, Status(..)
 , version
 , main
 #ifdef TEST
@@ -86,27 +89,46 @@
 hpack :: FilePath -> Bool -> IO ()
 hpack = hpackWithVersion version
 
+hpackResult :: FilePath -> IO Result
+hpackResult = hpackWithVersionResult version
+
+data Result = Result {
+  resultWarnings :: [String]
+, resultCabalFile :: String
+, resultStatus :: Status
+}
+
+data Status = Generated | AlreadyGeneratedByNewerHpack | OutputUnchanged
+
 hpackWithVersion :: Version -> FilePath -> Bool -> IO ()
 hpackWithVersion v dir verbose = do
-  (warnings, name, new) <- run dir
-  forM_ warnings $ \warning -> hPutStrLn stderr ("WARNING: " ++ warning)
+    r <- hpackWithVersionResult v dir
+    forM_ (resultWarnings r) $ \warning -> hPutStrLn stderr ("WARNING: " ++ warning)
+    when verbose $ putStrLn $
+      case resultStatus r of
+        Generated -> "generated " ++ resultCabalFile r
+        OutputUnchanged -> resultCabalFile r ++ " is up-to-date"
+        AlreadyGeneratedByNewerHpack -> resultCabalFile r ++ " was generated with a newer version of hpack, please upgrade and try again."
 
-  old <- either (const Nothing) (Just . splitHeader) <$> tryJust (guard . isDoesNotExistError) (readFile name >>= (return $!!))
+hpackWithVersionResult :: Version -> FilePath -> IO Result
+hpackWithVersionResult v dir = do
+  (warnings, cabalFile, new) <- run dir
+  old <- either (const Nothing) (Just . splitHeader) <$> tryJust (guard . isDoesNotExistError) (readFile cabalFile >>= (return $!!))
   let oldVersion = fmap fst old >>= extractVersion
-
-  if (oldVersion <= Just v) then do
-    if (fmap snd old == Just (lines new)) then do
-      output (name ++ " is up-to-date")
-    else do
-      (writeFile name $ header v ++ new)
-      output ("generated " ++ name)
-  else do
-    output (name ++ " was generated with a newer version of hpack, please upgrade and try again.")
+  status <-
+    if (oldVersion <= Just v) then
+      if (fmap snd old == Just (lines new)) then
+        return OutputUnchanged
+      else do
+        writeFile cabalFile $ header v ++ new
+        return Generated
+    else
+      return AlreadyGeneratedByNewerHpack
+  return Result
+    { resultWarnings = warnings
+    , resultCabalFile = cabalFile
+    , resultStatus = status
+    }
   where
     splitHeader :: String -> ([String], [String])
     splitHeader = fmap (dropWhile null) . span ("--" `isPrefixOf`) . lines
-
-    output :: String -> IO ()
-    output message
-      | verbose = putStrLn message
-      | otherwise = return ()
diff --git a/src/Hpack/Config.hs b/src/Hpack/Config.hs
--- a/src/Hpack/Config.hs
+++ b/src/Hpack/Config.hs
@@ -91,7 +91,7 @@
   ++ maybe [] sectionDependencies packageLibrary
 
 section :: a -> Section a
-section a = Section a [] [] [] [] [] [] [] [] [] [] [] [] [] Nothing []
+section a = Section a [] [] [] [] [] [] [] [] [] [] [] [] [] Nothing [] []
 
 packageConfig :: FilePath
 packageConfig = "package.yaml"
@@ -189,6 +189,7 @@
 , commonOptionsLdOptions :: Maybe (List LdOption)
 , commonOptionsBuildable :: Maybe Bool
 , commonOptionsWhen :: Maybe (List ConditionalSection)
+, commonOptionsBuildTools :: Maybe (List Dependency)
 } deriving (Eq, Show, Generic)
 
 instance HasFieldNames CommonOptions
@@ -395,6 +396,7 @@
 , sectionLdOptions :: [LdOption]
 , sectionBuildable :: Maybe Bool
 , sectionConditionals :: [Conditional]
+, sectionBuildTools :: [Dependency]
 } deriving (Eq, Show, Functor, Foldable, Traversable)
 
 data Conditional = Conditional {
@@ -614,6 +616,7 @@
   , sectionBuildable = sectionBuildable options <|> sectionBuildable globalOptions
   , sectionDependencies = sectionDependencies globalOptions ++ sectionDependencies options
   , sectionConditionals = sectionConditionals globalOptions ++ sectionConditionals options
+  , sectionBuildTools = sectionBuildTools globalOptions ++ sectionBuildTools options
   }
 
 toSection :: a -> CommonOptions -> ([FieldName], Section a)
@@ -636,6 +639,7 @@
       , sectionBuildable = commonOptionsBuildable
       , sectionDependencies = fromMaybeList commonOptionsDependencies
       , sectionConditionals = conditionals
+      , sectionBuildTools = fromMaybeList commonOptionsBuildTools
       }
     )
   where
diff --git a/src/Hpack/Run.hs b/src/Hpack/Run.hs
--- a/src/Hpack/Run.hs
+++ b/src/Hpack/Run.hs
@@ -216,6 +216,7 @@
   , Field "extra-libraries" (LineSeparatedList sectionExtraLibraries)
   , renderLdOptions sectionLdOptions
   , renderDependencies sectionDependencies
+  , renderBuildTools sectionBuildTools
   ]
   ++ maybe [] (return . renderBuildable) sectionBuildable
   ++ map renderConditional sectionConditionals
@@ -265,3 +266,6 @@
 
 renderOtherExtensions :: [String] -> Element
 renderOtherExtensions = Field "other-extensions" . WordList
+
+renderBuildTools :: [Dependency] -> Element
+renderBuildTools = Field "build-tools" . CommaSeparatedList . map dependencyName
diff --git a/test/Hpack/ConfigSpec.hs b/test/Hpack/ConfigSpec.hs
--- a/test/Hpack/ConfigSpec.hs
+++ b/test/Hpack/ConfigSpec.hs
@@ -594,6 +594,15 @@
           |]
           (packageLibrary >>> (`shouldBe` Just (section library) {sectionSourceDirs = ["foo", "bar"]}))
 
+      it "accepts build-tools" $ do
+        withPackageConfig_ [i|
+          library:
+            build-tools:
+              - alex
+              - happy
+          |]
+          (packageLibrary >>> (`shouldBe` Just (section library) {sectionBuildTools = ["alex", "happy"]}))
+
       it "accepts default-extensions" $ do
         withPackageConfig_ [i|
           library:
@@ -621,6 +630,15 @@
           |]
           (packageLibrary >>> (`shouldBe` Just (section library) {sectionSourceDirs = ["foo", "bar"]}))
 
+      it "accepts global build-tools" $ do
+        withPackageConfig_ [i|
+          build-tools:
+            - alex
+            - happy
+          library: {}
+          |]
+          (packageLibrary >>> (`shouldBe` Just (section library) {sectionBuildTools = ["alex", "happy"]}))
+
       it "allows to specify exposed" $ do
         withPackageConfig_ [i|
           library:
@@ -728,6 +746,17 @@
           |]
           (packageExecutables >>> (`shouldBe` [(section $ executable "foo" "Main.hs") {sectionSourceDirs = ["foo", "bar"]}]))
 
+      it "accepts build-tools" $ do
+        withPackageConfig_ [i|
+          executables:
+            foo:
+              main: Main.hs
+              build-tools:
+                - alex
+                - happy
+          |]
+          (packageExecutables >>> (`shouldBe` [(section $ executable "foo" "Main.hs") {sectionBuildTools = ["alex", "happy"]}]))
+
       it "accepts global source-dirs" $ do
         withPackageConfig_ [i|
           source-dirs:
@@ -738,6 +767,17 @@
               main: Main.hs
           |]
           (packageExecutables >>> (`shouldBe` [(section $ executable "foo" "Main.hs") {sectionSourceDirs = ["foo", "bar"]}]))
+
+      it "accepts global build-tools" $ do
+        withPackageConfig_ [i|
+          build-tools:
+            - alex
+            - happy
+          executables:
+            foo:
+              main: Main.hs
+          |]
+          (packageExecutables >>> (`shouldBe` [(section $ executable "foo" "Main.hs") {sectionBuildTools = ["alex", "happy"]}]))
 
       it "infers other-modules" $ do
         withPackageConfig [i|
