diff --git a/Changelog.md b/Changelog.md
new file mode 100644
--- /dev/null
+++ b/Changelog.md
@@ -0,0 +1,7 @@
+# Changelog for `proto-lens-setup`
+
+## v0.4
+- Split out from `proto-lens-protoc`.
+
+## Older
+See `Changelog.md` for `proto-lens-protoc`.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2016, Google Inc.
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Google Inc. nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/proto-lens-setup.cabal b/proto-lens-setup.cabal
new file mode 100644
--- /dev/null
+++ b/proto-lens-setup.cabal
@@ -0,0 +1,83 @@
+-- This file has been generated from package.yaml by hpack version 0.28.2.
+--
+-- see: https://github.com/sol/hpack
+--
+-- hash: f1feed5b1976417184fb9af0ad32240ff5ce3534e0d0d8d6471b20fe0d95a41d
+
+name:           proto-lens-setup
+version:        0.4.0.0
+synopsis:       Cabal support for codegen with proto-lens.
+description:    This package provides Cabal support for the @proto-lens@ package.
+                It automatically generates Haskell source files from protocol buffer
+                files (@.proto@).
+                .
+                To generate Haskell modules for a Cabal package, import
+                "Data.ProtoLens.Setup" from the @Setup.hs@ file.  For example:
+                .
+                > import Data.ProtoLens.Setup
+                > -- Here, "src" is the directory where .proto source files may be found
+                > main = defaultMainGeneratingProtos "src"
+                .
+                Then, edit the @.cabal@ file of your project to:
+                .
+                * Specify @build-type: Custom@, and add a @custom-setup@ clause that
+                  depends on @proto-lens-setup@.
+                .
+                * List the .proto files in @extra-source-files@.  Note that the field belongs
+                  at the top level of the @.cabal@ file, rather than once per
+                  library\/executable\/etc.
+                .
+                * List the generated modules (e.g. @Proto.Foo.Bar@) in @exposed-modules@
+                  or @other-modules@ of the rule(s) that use them (e.g. the library or
+                  executables).  Additionally, add @proto-lens-runtime@ to the @build-depends@
+                  of those rules.
+                .
+                For example, in @foo-bar-proto.cabal@:
+                .
+                > build-type: Custom
+                > extra-source-files: src/foo/bar.proto
+                > ...
+                > custom-setup
+                >   setup-depends: base, Cabal, proto-lens-setup
+                .
+                > library
+                >     exposed-modules: Proto.Foo.Bar, Proto.Foo.Bar_Fields
+                >     autogen-modules: Proto.Foo.Bar, Proto.Foo.Bar_Fields
+                >     build-depends: proto-lens-runtime, ...
+homepage:       https://github.com/google/proto-lens#readme
+bug-reports:    https://github.com/google/proto-lens/issues
+author:         Judah Jacobson
+maintainer:     proto-lens@googlegroups.com
+copyright:      Google Inc.
+license:        BSD3
+license-file:   LICENSE
+build-type:     Simple
+cabal-version:  >= 1.10
+extra-source-files:
+    Changelog.md
+
+source-repository head
+  type: git
+  location: https://github.com/google/proto-lens
+  subdir: proto-lens-setup
+
+library
+  exposed-modules:
+      Data.ProtoLens.Setup
+  other-modules:
+      Paths_proto_lens_setup
+  hs-source-dirs:
+      src
+  build-depends:
+      Cabal >=1.22 && <2.3
+    , base >=4.9 && <4.12
+    , bytestring ==0.10.*
+    , containers ==0.5.*
+    , deepseq ==1.4.*
+    , directory >=1.2 && <1.4
+    , filepath >=1.4 && <1.6
+    , process >=1.2 && <1.7
+    , proto-lens-protoc ==0.4.*
+    , temporary >=1.2 && <1.4
+    , text ==1.2.*
+  default-language: Haskell2010
diff --git a/src/Data/ProtoLens/Setup.hs b/src/Data/ProtoLens/Setup.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/ProtoLens/Setup.hs
@@ -0,0 +1,458 @@
+-- Copyright 2016 Google Inc. All Rights Reserved.
+--
+-- Use of this source code is governed by a BSD-style
+-- license that can be found in the LICENSE file or at
+-- https://developers.google.com/open-source/licenses/bsd
+
+-- | Helper functions to generate proto files as part of a @Setup.hs@ script.
+--
+-- These functions assume that the @proto-lens-protoc@ executable is on the
+-- PATH, and throw an exception otherwise.  That executable will be installed
+-- automatically as part of installing this package; in particular, it should
+-- be enough to just list `proto-lens-protoc` in a user package's
+-- `build-dependencies`.
+--
+-- See @README.md@ for instructions on how to use proto-lens with Cabal.
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE BangPatterns #-}
+module Data.ProtoLens.Setup
+    ( defaultMainGeneratingProtos
+    , defaultMainGeneratingSpecificProtos
+    , generatingProtos
+    , generatingSpecificProtos
+    , generateProtosWithImports
+    , generateProtos
+    ) where
+
+import Control.Monad (filterM, forM_, when)
+import qualified Data.ByteString as BS
+import qualified Data.Map as Map
+import Data.Maybe (maybeToList)
+import qualified Data.Set as Set
+import qualified Data.Text as T
+import Distribution.ModuleName (ModuleName)
+import qualified Distribution.ModuleName as ModuleName
+import qualified Distribution.InstalledPackageInfo as InstalledPackageInfo
+import Distribution.PackageDescription
+    ( PackageDescription(..)
+    , benchmarkBuildInfo
+    , benchmarkName
+    , buildInfo
+    , exeName
+    , exposedModules
+    , extraSrcFiles
+#if !MIN_VERSION_Cabal(2,0,0)
+    , hsSourceDirs
+#endif
+    , libBuildInfo
+    , otherModules
+    , testBuildInfo
+    , testBuildInfo
+    , testName
+    )
+import qualified Distribution.Simple.BuildPaths as BuildPaths
+import Distribution.Simple.InstallDirs (datadir)
+import Distribution.Simple.LocalBuildInfo
+    ( LocalBuildInfo(..)
+    , absoluteInstallDirs
+    , ComponentName(..)
+    , ComponentLocalBuildInfo
+    , componentPackageDeps
+#if MIN_VERSION_Cabal(2,0,0)
+    , allComponentsInBuildOrder
+    , componentNameMap
+#endif
+    )
+import qualified Distribution.Simple.PackageIndex as PackageIndex
+import Distribution.Simple.Setup (fromFlag, copyDest, copyVerbosity)
+import Distribution.Simple.Utils
+    ( createDirectoryIfMissingVerbose
+    , installOrdinaryFile
+    , matchFileGlob
+    )
+import Distribution.Simple
+    ( defaultMainWithHooks
+    , simpleUserHooks
+    , UserHooks(..)
+    )
+import Distribution.Verbosity (Verbosity)
+import System.FilePath
+    ( (</>)
+    , equalFilePath
+    , isRelative
+    , makeRelative
+    , takeDirectory
+    , takeExtension
+    )
+import System.Directory
+    ( copyFile
+    , createDirectoryIfMissing
+    , doesDirectoryExist
+    , doesFileExist
+    , findExecutable
+    , removeDirectoryRecursive
+    )
+import System.IO (hPutStrLn, stderr)
+import System.IO.Temp (withSystemTempDirectory)
+import System.Process (callProcess)
+
+import qualified Data.ProtoLens.Compiler.Plugin as Plugin
+
+-- | This behaves the same as 'Distribution.Simple.defaultMain', but
+-- auto-generates Haskell files from .proto files which are:
+--
+-- * Listed in the @.cabal@ file under @extra-source-files@,
+--
+-- * Located under the given root directory, and
+--
+-- * Correspond to a module (@"Proto.*"@) in `exposed-modules` or
+-- `other-modules` of some component in the @.cabal@ file.
+--
+-- Writes the generated files to the autogen directory (@dist\/build\/autogen@
+-- for Cabal, and @.stack-work\/dist\/...\/build\/autogen@ for stack).
+--
+-- Throws an exception if the @proto-lens-protoc@ executable is not on the PATH.
+defaultMainGeneratingProtos
+    :: FilePath -- ^ The root directory under which .proto files can be found.
+    -> IO ()
+defaultMainGeneratingProtos root
+    = defaultMainWithHooks $ generatingProtos root simpleUserHooks
+
+-- | This behaves the same as 'Distribution.Simple.defaultMain', but
+-- auto-generates Haskell files from the .proto files listed. The given .proto
+-- files should be under the given root directory.
+--
+-- Writes the generated files to the autogen directory (@dist\/build\/autogen@
+-- for Cabal, and @.stack-work\/dist\/...\/build\/autogen@ for stack).
+--
+-- Throws an exception if the @proto-lens-protoc@ executable is not on the PATH.
+defaultMainGeneratingSpecificProtos
+    :: FilePath -- ^ The root directory under which .proto files can be found.
+    -> (LocalBuildInfo -> IO [FilePath])
+    -- ^ A function to return a list of .proto files. Takes the Cabal package
+    -- description as input. Non-absolute paths are treated as relative to the
+    -- provided root directory.
+    -> IO ()
+defaultMainGeneratingSpecificProtos root getProtos
+    = defaultMainWithHooks
+    $ generatingSpecificProtos root getProtos simpleUserHooks
+
+-- | Augment the given 'UserHooks' to auto-generate Haskell files from the
+-- .proto files which are:
+--
+-- * Listed in the @.cabal@ file under @extra-source-files@,
+--
+-- * Located under the given root directory, and
+--
+-- * Correspond to a module (@"Proto.*"@) in `exposed-modules` or
+-- `other-modules` of some component in the @.cabal@ file.
+--
+-- Writes the generated files to the autogen directory (@dist\/build\/autogen@
+-- for Cabal, and @.stack-work\/dist\/...\/build\/autogen@ for stack).
+--
+-- Throws an exception if the @proto-lens-protoc@ executable is not on the PATH.
+generatingProtos
+    :: FilePath -- ^ The root directory under which .proto files can be found.
+    -> UserHooks -> UserHooks
+generatingProtos root = generatingSpecificProtos root getProtos
+  where
+    getProtos l = do
+      -- Replicate Cabal's own logic for parsing file globs.
+      files <- concat <$> mapM matchFileGlob (extraSrcFiles $ localPkgDescr l)
+      pure
+           . filter (\f -> takeExtension f == ".proto")
+           . map (makeRelative root)
+           . filter (isSubdirectoryOf root)
+           $ files
+
+
+-- | Augment the given 'UserHooks' to auto-generate Haskell files from the
+-- .proto files returned by a function @getProtos@.
+--
+-- Writes the generated files to the autogen directory (@dist\/build\/autogen@
+-- for Cabal, and @.stack-work\/dist\/...\/build\/autogen@ for stack).
+--
+-- Throws an exception if the @proto-lens-protoc@ executable is not on the PATH.
+generatingSpecificProtos
+    :: FilePath -- ^ The root directory under which .proto files can be found.
+    -> (LocalBuildInfo -> IO [FilePath])
+    -- ^ A function to return a list of .proto files. Takes the Cabal package
+    -- description as input. Non-absolute paths are treated as relative to the
+    -- provided root directory.
+    -> UserHooks -> UserHooks
+generatingSpecificProtos root getProtos hooks = hooks
+    { buildHook = \p l h f -> generate l >> buildHook hooks p l h f
+    , haddockHook = \p l h f -> generate l >> haddockHook hooks p l h f
+    , replHook = \p l h f args -> generate l >> replHook hooks p l h f args
+#if !MIN_VERSION_Cabal(2,0,0)
+    -- Older versions of Cabal don't support the autogen-modules field.
+    -- Work around it by manually generating the modules and putting them
+    -- in a place where `cabal sdist` will pick them up.
+    , sDistHook = \p maybe_l h f -> case maybe_l of
+            Nothing -> error "Can't run protoc; run 'cabal configure' first."
+            Just l -> do
+                        generate l
+                        sDistHook hooks (fudgePackageDesc l p) maybe_l h f
+#endif
+    , postCopy = \a flags pkg lbi -> do
+                  let verb = fromFlag $ copyVerbosity flags
+                  let destDir = datadir (absoluteInstallDirs pkg lbi
+                                             $ fromFlag $ copyDest flags)
+                              </> protoLensImportsPrefix
+                  getProtos lbi >>= copyProtosToDataDir verb root destDir
+                  postCopy hooks a flags pkg lbi
+    }
+  where
+    generate l = getProtos l >>= generateSources root l
+
+-- | Generate Haskell source files for the given input .proto files.
+--
+-- Process all the proto files that are referenced in the exposed-modules
+-- or other-modules of some "active" component, and write them all to a
+-- single temporary directory.  (For example, passing --no-enable-tests
+-- makes all test-suite components inactive.)
+--
+-- Then, for each active component, copy the corresponding module files
+-- over to its specific autogen directory (if Cabal-2.*) or to the global
+-- autogen directory (if Cabal-1.*).  However, don't actually do the copy
+-- if it's the same as what's already there.  This way, we don't needlessly
+-- touch the generated .hs files when nothing changes, and thus don't
+-- needlessly make GHC recompile them (as it considers their modification
+-- times for that).
+generateSources :: FilePath -- ^ The root directory
+                -> LocalBuildInfo
+                -> [FilePath] -- ^ Proto files relative to the root directory.
+                -> IO ()
+generateSources root l files = withSystemTempDirectory "protoc-out" $ \tmpDir -> do
+    -- Collect import paths from build-depends of this package.
+    importDirs <- filterM doesDirectoryExist
+                     [ InstalledPackageInfo.dataDir info </> protoLensImportsPrefix
+                     | info <- collectDeps l
+                     ]
+    -- Generate .hs files for all active components into a single temporary
+    -- directory.
+    let activeModules = collectActiveModules l
+    let allModules = Set.fromList . concat . map snd $ activeModules
+    let usedInComponent f = ModuleName.fromString (Plugin.moduleNameStr "Proto" f)
+                          `Set.member` allModules
+    generateProtosWithImports (root : importDirs) tmpDir
+                              -- Applying 'root </>' does nothing if the path is already
+                              -- absolute.
+                              $ map (root </>) $ filter usedInComponent files
+    -- Copy each active component's files over to its autogen directory, but
+    -- only if they've changed since last time.
+    forM_ activeModules $ \(compBI, mods) -> forM_ mods $ \m -> do
+          let f = T.unpack (Plugin.outputFilePath $ ModuleName.toFilePath m)
+          let sourcePath = tmpDir </> f
+          sourceExists <- doesFileExist sourcePath
+          when sourceExists $ do
+            let dest = autogenComponentModulesDir l compBI </> f
+            copyIfDifferent sourcePath dest
+
+-- Note: we do a copy rather than a move since a given module may be used in
+-- more than one component.
+copyIfDifferent :: FilePath -> FilePath -> IO ()
+copyIfDifferent sourcePath targetPath = do
+    targetExists <- doesFileExist targetPath
+    identical <- do
+        if not targetExists
+            then return False
+            else do
+                -- This could be done in a streaming fashion,
+                -- but since the .hs files usually easily fit
+                -- into RAM, this is OK.
+                sourceContents <- BS.readFile sourcePath
+                targetContents <- BS.readFile targetPath
+                return (sourceContents == targetContents)
+    -- Do the move if necessary.
+    when (not identical) $ do
+        createDirectoryIfMissing True (takeDirectory targetPath)
+        copyFile sourcePath targetPath
+
+
+-- | Copy each .proto file into the installed "data-dir" path,
+-- so that it can be included by other packages that depend on this one.
+copyProtosToDataDir :: Verbosity
+                    -> FilePath -- ^ The root for source .proto files in this
+                                -- package.
+                    -> FilePath -- ^ The final location where .proto files should
+                                -- be installed.
+                    -> [FilePath] -- ^ .proto files relative to the root
+                    -> IO ()
+copyProtosToDataDir verb root destDir files = do
+    -- Make the build more hermetic by clearing the output
+    -- directory.
+    exists <- doesDirectoryExist destDir
+    when exists $ removeDirectoryRecursive destDir
+    forM_ files $ \f -> do
+        let srcFile = root </> f
+        let destFile = destDir </> f
+        createDirectoryIfMissingVerbose verb True
+            (takeDirectory destFile)
+        installOrdinaryFile verb srcFile destFile
+
+-- | Imports are stored as $datadir/proto-lens-imports/**/*.proto.
+protoLensImportsPrefix :: FilePath
+protoLensImportsPrefix = "proto-lens-imports"
+
+#if !MIN_VERSION_Cabal(2,0,0)
+-- | Add the autogen directory to the hs-source-dirs of all the targets in the
+-- .cabal file.  Used to fool 'sdist' by pointing it to the generated source
+-- files.
+fudgePackageDesc :: LocalBuildInfo -> PackageDescription -> PackageDescription
+fudgePackageDesc lbi p = p
+    { library =
+        (\lib -> lib { libBuildInfo = fudgeBuildInfo CLibName $ libBuildInfo lib })
+            <$> library p
+    , executables =
+        (\exe -> exe { buildInfo = fudgeBuildInfo (CExeName $ exeName exe)
+                                        $ buildInfo exe })
+            <$> executables p
+    , testSuites =
+        (\test -> test { testBuildInfo = fudgeBuildInfo (CTestName $ testName test)
+                                            $ testBuildInfo test })
+            <$> testSuites p
+    , benchmarks =
+        (\bench -> bench { benchmarkBuildInfo =
+                              fudgeBuildInfo (CBenchName $ benchmarkName bench)
+                                  $ benchmarkBuildInfo bench })
+            <$> benchmarks p
+    }
+  where
+    comps = allComponents lbi
+    fudgeBuildInfo n bi
+        | Just compLBI <- Map.lookup n comps
+            = bi { hsSourceDirs = autogenComponentModulesDir lbi compLBI
+                                    : hsSourceDirs bi }
+        | otherwise = bi -- Could happen if a component isn't active; try
+                         -- anyway and see whether Cabal complains later on.
+#endif
+
+-- | Returns whether the @root@ is a parent folder of @f@.
+isSubdirectoryOf :: FilePath -> FilePath -> Bool
+isSubdirectoryOf root f
+    = isRelative f
+      -- Note: `makeRelative root f` returns `f` when f doesn't live under the
+      -- root.
+      && equalFilePath f (root </> makeRelative root f)
+
+-- | Run the proto compiler to generate Haskell files from the given .proto files.
+--
+-- Writes the generated files to the autogen directory (@dist\/build\/autogen@
+-- for Cabal, and @.stack-work\/dist\/...\/build\/autogen@ for stack).
+--
+-- Throws an exception if the @proto-lens-protoc@ executable is not on the PATH.
+generateProtos
+    :: FilePath -- ^ The root directory under which .proto files can be found.
+    -> FilePath -- ^ The output directory for the generated Haskell files.
+    -> [FilePath] -- ^ The .proto files to process.
+    -> IO ()
+generateProtos root = generateProtosWithImports [root]
+--
+-- | Run the proto compiler to generate Haskell files from the given .proto files.
+--
+-- Writes the generated files to the autogen directory (@dist\/build\/autogen@
+-- for Cabal, and @.stack-work\/dist\/...\/build\/autogen@ for stack).
+--
+-- Throws an exception if the @proto-lens-protoc@ executable is not on the PATH.
+generateProtosWithImports
+    :: [FilePath] -- ^ Directories under which .proto files and/or files that
+                  -- they import can be found.
+    -> FilePath -- ^ The output directory for the generated Haskell files.
+    -> [FilePath] -- ^ The .proto files to process.
+    -> IO ()
+generateProtosWithImports _ _ [] = return ()
+generateProtosWithImports imports output files = do
+    protoLensProtoc
+        <- findExecutableOrDie "proto-lens-protoc"
+              $ "Please file a bug at "
+                  ++ "https://github.com/google/proto-lens/issues ."
+    protoc <- findExecutableOrDie "protoc"
+                $ "Follow the installation instructions at "
+                    ++ "https://google.github.io/proto-lens/installing-protoc.html ."
+    createDirectoryIfMissing True output
+    callProcess protoc $
+        [ "--plugin=protoc-gen-haskell=" ++ protoLensProtoc
+        , "--haskell_out=" ++ output
+        ]
+        ++ ["--proto_path=" ++ p | p <- imports]
+        ++ files
+
+-- | Search the PATH for an executable, printing an error message if it's not
+-- found.
+findExecutableOrDie :: String -> String -> IO FilePath
+findExecutableOrDie name debugMsg = do
+    maybePath <- findExecutable name
+    case maybePath of
+        Just path -> return path
+        Nothing -> do
+            let sep = "=========="
+            hPutStrLn stderr sep
+            hPutStrLn stderr $ "Error: couldn't find the executable " ++ show name
+                            ++ " in your $PATH."
+                            ++ "\n    " ++ debugMsg
+            hPutStrLn stderr sep
+            error $ "Missing executable " ++ show name
+
+-- | Collect all the module names that we need to build.
+-- For example: only include test-suites if we're building with tests enabled
+-- (e.g., `stack test` vs `stack build`).
+collectActiveModules
+    :: LocalBuildInfo -> [(ComponentLocalBuildInfo, [ModuleName])]
+collectActiveModules l = map (\(n, c) -> (c, f n)) $ Map.toList $ allComponents l
+  where
+    p = localPkgDescr l
+    f CLibName = maybeToList (library p) >>=
+                    \lib -> exposedModules lib
+                                ++ otherModules (libBuildInfo lib)
+    f (CExeName n) = otherModules . buildInfo $ exes Map.! n
+    f (CTestName n) = otherModules . testBuildInfo $ tests Map.! n
+    f (CBenchName n) = otherModules . benchmarkBuildInfo $ benchs Map.! n
+#if MIN_VERSION_Cabal(2,0,0)
+    f _ = []  -- TODO: other lib kinds; for now just suppress the warning
+#endif
+    exes = Map.fromList [(exeName e, e) | e <- executables p]
+    tests = Map.fromList [(testName e, e) | e <- testSuites p]
+    benchs = Map.fromList [(benchmarkName e, e) | e <- benchmarks p]
+
+-------------------------------------------------------
+-- Compatibility layer between Cabal-1.* and Cabal-2.*
+
+-- | List all the packages that this one depends on.
+collectDeps :: LocalBuildInfo -> [InstalledPackageInfo.InstalledPackageInfo]
+#if MIN_VERSION_Cabal(2,0,0)
+collectDeps l = do
+    c <- allComponentsInBuildOrder l
+    (i,_) <- componentPackageDeps c
+    Just p <- [PackageIndex.lookupUnitId (installedPkgs l) i]
+    return p
+#else
+collectDeps l = do
+    (_, c ,_) <- componentsConfigs l
+    (_, i) <- componentPackageDeps c
+    PackageIndex.lookupSourcePackageId (installedPkgs l) i
+#endif
+
+-- | All the components that will be built by this Cabal command.
+allComponents :: LocalBuildInfo -> Map.Map ComponentName ComponentLocalBuildInfo
+#if MIN_VERSION_Cabal(2,0,0)
+allComponents l = fmap requireOne $ componentNameMap l
+  where
+    -- TODO: this doesn't support Backpack, which can have more than one
+    -- ComponentLocalBuildInfo associated with a name.
+    requireOne [x] = x
+    requireOne xs = error $ "Data.ProtoLens.Setup.allComponents: expected one "
+                          ++ "component per name, got " ++ show xs
+
+#else
+allComponents l = Map.fromList [(c, b) | (c, b, _) <- componentsConfigs l]
+#endif
+
+-- | Get the component-level "autogen" directory where we're putting the
+-- generated .hs files.  (For Cabal-1.0, use the shared 'BuildPaths.autogenModulesDir'.)
+autogenComponentModulesDir :: LocalBuildInfo -> ComponentLocalBuildInfo -> FilePath
+#if MIN_VERSION_Cabal(2,0,0)
+autogenComponentModulesDir = BuildPaths.autogenComponentModulesDir
+#else
+autogenComponentModulesDir lbi _ = BuildPaths.autogenModulesDir lbi
+#endif
