diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,17 @@
+0.4.0 (2018-08-21)
+==================
+
+*   Drop support for GHC < 7.10 and base < 4.8
+*   Drop support for Cabal < 1.24
+*   Drop support for transformers < 0.4
+*   Don't run CI tests for Cabal < 2
+
+*   With Cabal 2.0 or later package info modules are placed in per component
+    `autogen` directories. All package info modules are named just `PkgInfo`.
+    For backward compatibility modules with the old legacy names (`PkgInfo_*`)
+    are still generated but marked deprecated. With Cabal 1.24 only the legacy
+    behavior is available and a deprecation warning is raised.
+
 0.3.1 (2018-03-16)
 ==================
 
diff --git a/INSTALL_ON_WINDOWS.md b/INSTALL_ON_WINDOWS.md
deleted file mode 100644
--- a/INSTALL_ON_WINDOWS.md
+++ /dev/null
@@ -1,118 +0,0 @@
-When using the `Setup.hs` script from the *configuration-tools* package
-with a source build from a git repository a git binary must be available
-in the `PATH` environment of the installation command. This is, for instance,
-the case for the test-suite of the *configuration-tools* package itself.
-
-The first step in the following description installs a git binary that
-is globally available in the system. Steps two through seven explain
-how to setup a Haskell build environment on a Windows system in general.
-Those steps are not specific to the *configuration-tools* package. Steps
-eight and nine explain how to install and test the *configuration-tools*
-package.
-
-Windows
-=======
-
-The following steps make use of the `Git Bash` terminal. Beside of being
-convenient for users that are familiar with POSIX systems, it is also a
-requirement for installing the *network* package, which is a dependency of
-*cabal*. Most other Haskell packages can be installed from a windows shell
-(PowerShell or cmd shell) as well.
-
-1.  Install Git from: [Git for windows](http://git-scm.com/download/win)
-
-    During the installation, when ask about the environment settings,
-    select the second option that makes the git command available at
-    the windows shell prompt. Otherwise the git binary is available
-    only when `cabal` is executed from the *Git Bash* terminal.
-
-2.  Download the
-    [GHC binary distribution for windows](http://www.haskell.org/ghc/dist/7.8.3/ghc-7.8.3-x86_64-unknown-mingw32.tar.bz2)
-    and unpack it in a convenient place.
-
-    In the following we assume that it was unpacked in `C:\` into the default directory `C:\ghc-7.8.3`.
-
-3.  Obtain a windows cabal binary, for example from the Haskell Platform distribution
-    or a previous GHC installation (the version doesn't matter).
-
-4.  Open the *Git Bash* terminal. A link to it should have been created in the start menu
-    during the Git installation.
-
-5.  Include the `bin` directory and `mingw/bin` directory from the GHC binary distribution into
-    the `PATH` environment:
-
-    ~~~{.sh}
-    export PATH=/c/ghc-7.8.3/bin:/c/ghc-7.8.3/mingw/bin:$PATH
-    ~~~
-
-6.  Make sure a cabal binary is available in the `PATH`
-
-    ~~~{.sh}
-    which cabal
-    ~~~
-
-    and check that `ghc`, `ld`, and `gcc` are used from the respective directories under 
-    `/c/ghc-7.8.3/*`:
-
-    ~~~{.sh}
-    which ghc
-    which ld
-    which gcc
-    ~~~
-
-7.  Install an updated version of `cabal`:
-
-    ~~~{.sh}
-    cabal update
-    cabal install cabal-install
-    ~~~
-
-    Make sure that the location into which the resulting cabal binary is installed
-    (the location is configured in `~/AppData/Roaming/cabal/config` and it is also
-    printed to the installation logs) is in your `PATH`.
-
-    Check that you are now using the most recent version of cabal:
-
-    ~~~{.sh}
-    which cabal
-    cabal --version
-    ~~~
-
-8.  Install the *configuration-tools* package from Hackage:
-
-    ~~~{.sh}
-    cabal install configuration-tools --enable-tests
-    ~~~
-
-    Alternativly, you my clone and install it from
-    [GitHub](https://github.com/alephcloud/hs-configuration-tools.git):
-
-    ~~~{.sh}
-    git clone https://github.com/alephcloud/hs-configuration-tools.git
-    cd hs-configuration-tools
-    cabal install --enable-tests
-    ~~~
-
-9.  When you installed *configuration-tools* from source you may run the tests
-    from within the package directory as follows:
-
-    ~~~{.sh}
-    cabal test
-    ~~~
-
-    You can run the test with different command line options using cabals `--test-option`
-    flag. For instance[^1]:
-
-    ~~~{.sh}
-    cabal test --show-details=always --test-option=--help
-    cabal test --show-details=always --test-option=--long-info
-    ~~~
-
-    [^1]: Note: the windows terminal reacts ungracefully to Unicode characters. In order to have
-        it at least not crash the program you should run the following command before you
-        exectute any command that may print unicode characters (like the copyright symbol in the
-        test examples):
-
-        ~~~{.sh}
-        chcp.com 65001
-        ~~~
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,9 +1,8 @@
 -- ------------------------------------------------------ --
--- Copyright © 2015-2016 Lars Kuhtz <lakuhtz@gmail.com>
+-- Copyright © 2015-2018 Lars Kuhtz <lakuhtz@gmail.com>
 -- Copyright © 2014 AlephCloud Systems, Inc.
 -- ------------------------------------------------------ --
 
-{-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE ScopedTypeVariables #-}
@@ -14,19 +13,8 @@
 -- process at the end of the configuration phase and generates a module with
 -- package information for each component of the cabal package.
 --
--- The modules are created in the /autogen/ build directory where also the
--- @Path_@ module is created by cabal's simple build setup. This is usually the
--- directory @.\/dist\/build\/autogen@.
---
--- For a library component the module is named just @PkgInfo@. For all other
--- components the module is named @PkgInfo_COMPONENT_NAME@ where
--- @COMPONENT_NAME@ is the name of the component with @-@ characters replaced by
--- @_@.
---
--- For instance, if a cabal package contains a library and an executable that is
--- called /my-app/, the following modules are created: @PkgInfo@ and
--- @PkgInfo_my_app@.
---
+-- The modules are created in the /autogen/ build directories where also the
+-- @Path_@ modules are created by cabal's simple build setup.
 --
 -- = Usage as Setup Script
 --
@@ -111,7 +99,6 @@
 ) where
 
 #ifndef MIN_VERSION_Cabal
-#define NO_CABAL_MACROS 1
 #define MIN_VERSION_Cabal(a,b,c) 0
 #endif
 
@@ -125,6 +112,7 @@
 import Distribution.Text
 
 #if MIN_VERSION_Cabal(2,0,0)
+import qualified Distribution.Compat.Graph as Graph
 import Distribution.Types.LocalBuildInfo
 import Distribution.Types.UnqualComponentName
 #endif
@@ -146,15 +134,16 @@
 
 import Prelude hiding (readFile, writeFile)
 
-import System.Directory (doesFileExist, doesDirectoryExist, createDirectoryIfMissing, getCurrentDirectory, canonicalizePath)
+import System.Directory
+    ( doesFileExist
+    , doesDirectoryExist
+    , createDirectoryIfMissing
+    , getCurrentDirectory
+    , canonicalizePath
+    )
 import System.FilePath (isDrive, (</>), takeDirectory)
 import System.Exit (ExitCode(ExitSuccess))
 
-#ifdef NO_CABAL_MACROS
-import Data.Maybe
-import Data.Typeable
-#endif
-
 -- | Include this function when your setup doesn't contain any
 -- extra functionality.
 --
@@ -168,14 +157,8 @@
 -- If your setup doesn't contain any other function you can just import
 -- the 'main' function from this module.
 --
--- The modules are created in the /autogen/ build directory where also the
--- @Path_@ module is created by cabal's simple build setup. This is usually the
--- directory @.\/dist\/build\/autogen@.
---
--- For a library component the module is named just @PkgInfo@. For all other
--- components the module is named @PkgInfo_COMPONENT_NAME@ where
--- @COMPONENT_NAME@ is the name of the component with @-@ characters replaced by
--- @_@.
+-- The modules are created in the /autogen/ build directories where also the
+-- @Path_@ modules are created by cabal's simple build setup.
 --
 mkPkgInfoModules
     :: UserHooks
@@ -184,6 +167,41 @@
     { postConf = mkPkgInfoModulesPostConf (postConf hooks)
     }
 
+-- -------------------------------------------------------------------------- --
+-- Compat Implementations
+
+#if !MIN_VERSION_Cabal(2,0,0)
+unFlagName :: FlagName -> String
+unFlagName (FlagName s) = s
+#endif
+
+#if !MIN_VERSION_Cabal(2,2,0)
+unFlagAssignment :: FlagAssignment -> [(FlagName, Bool)]
+unFlagAssignment = id
+#endif
+
+#if !MIN_VERSION_Cabal(2,2,0)
+prettyShow :: Text a => a -> String
+prettyShow = display
+#endif
+
+#if !MIN_VERSION_Cabal(2,0,0)
+-- unUnqualComponentName :: UnqualComponentName -> String
+unUnqualComponentName :: String -> String
+unUnqualComponentName = id
+#endif
+
+prettyLicense :: I.InstalledPackageInfo -> String
+#if MIN_VERSION_Cabal(2,2,0)
+prettyLicense = either prettyShow prettyShow . I.license
+#else
+prettyLicense = prettyShow . I.license
+#endif
+
+-- -------------------------------------------------------------------------- --
+-- Cabal 2.0
+
+#if MIN_VERSION_Cabal(2,0,0)
 mkPkgInfoModulesPostConf
     :: (Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ())
     -> Args
@@ -192,6 +210,42 @@
     -> LocalBuildInfo
     -> IO ()
 mkPkgInfoModulesPostConf hook args flags pkgDesc bInfo = do
+    mapM_ (updatePkgInfoModule pkgDesc bInfo) $ Graph.toList $ componentGraph bInfo
+    hook args flags pkgDesc bInfo
+
+updatePkgInfoModule :: PackageDescription -> LocalBuildInfo -> ComponentLocalBuildInfo -> IO ()
+updatePkgInfoModule pkgDesc bInfo clbInfo = do
+    createDirectoryIfMissing True dirName
+    moduleBytes <- pkgInfoModule moduleName cName pkgDesc bInfo
+    updateFile fileName moduleBytes
+
+    -- legacy module
+    legacyModuleBytes <- pkgInfoModule legacyModuleName cName pkgDesc bInfo
+    updateFile legacyFileName legacyModuleBytes
+
+  where
+    dirName = autogenComponentModulesDir bInfo clbInfo
+    cName = unUnqualComponentName <$> componentNameString (componentLocalName clbInfo)
+
+    moduleName = pkgInfoModuleName
+    fileName = dirName ++ "/" ++ moduleName ++ ".hs"
+
+    legacyModuleName = legacyPkgInfoModuleName cName
+    legacyFileName = dirName ++ "/" ++ legacyModuleName ++ ".hs"
+
+-- -------------------------------------------------------------------------- --
+-- Cabal 1.24
+
+#else
+
+mkPkgInfoModulesPostConf
+    :: (Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ())
+    -> Args
+    -> ConfigFlags
+    -> PackageDescription
+    -> LocalBuildInfo
+    -> IO ()
+mkPkgInfoModulesPostConf hook args flags pkgDesc bInfo = do
     mkModules
     hook args flags pkgDesc bInfo
   where
@@ -202,22 +256,41 @@
         CTestName s -> updatePkgInfoModule (Just $ unUnqualComponentName s) pkgDesc bInfo
         CBenchName s -> updatePkgInfoModule (Just $ unUnqualComponentName s) pkgDesc bInfo
 
-#if !MIN_VERSION_Cabal(2,0,0)
-    unUnqualComponentName = id
+updatePkgInfoModule :: Maybe String -> PackageDescription -> LocalBuildInfo -> IO ()
+updatePkgInfoModule cName pkgDesc bInfo = do
+    createDirectoryIfMissing True dirName
+    moduleBytes <- pkgInfoModule moduleName cName pkgDesc bInfo
+    updateFile fileName moduleBytes
+  where
+    dirName = autogenModulesDir bInfo
+    moduleName = legacyPkgInfoModuleName cName
+    fileName = dirName ++ "/" ++ moduleName ++ ".hs"
 #endif
 
-pkgInfoModuleName :: Maybe String -> String
-pkgInfoModuleName Nothing = "PkgInfo"
-pkgInfoModuleName (Just cn) = "PkgInfo_" ++ map tr cn
+-- -------------------------------------------------------------------------- --
+-- Generate PkgInfo Module
+
+pkgInfoModuleName :: String
+pkgInfoModuleName = "PkgInfo"
+
+updateFile :: FilePath -> B.ByteString -> IO ()
+updateFile fileName content = do
+    doesFileExist fileName >>= \x -> if x
+    then do
+        oldRevisionFile <- B.readFile fileName
+        when (oldRevisionFile /= content) update
+    else
+        update
   where
+    update = B.writeFile fileName content
+
+legacyPkgInfoModuleName :: Maybe String -> String
+legacyPkgInfoModuleName Nothing = "PkgInfo"
+legacyPkgInfoModuleName (Just cn) = "PkgInfo_" ++ map tr cn
+  where
     tr '-' = '_'
     tr c = c
 
--- FIXME: autoModulesDir is deprecated and should be replaced by
--- autogenComponentModulesDir.
-pkgInfoFileName :: Maybe String -> LocalBuildInfo -> FilePath
-pkgInfoFileName cn bInfo = autogenModulesDir bInfo ++ "/" ++ pkgInfoModuleName cn ++ ".hs"
-
 trim :: String -> String
 trim = f . f
   where f = reverse . dropWhile isSpace
@@ -236,23 +309,8 @@
             then return Nothing
             else getVcsOfDir (takeDirectory canonicDir)
 
-#if !MIN_VERSION_Cabal(2,0,0)
-unFlagName :: FlagName -> String
-unFlagName (FlagName s) = s
-#endif
-
-#if !MIN_VERSION_Cabal(2,2,0)
-unFlagAssignment :: FlagAssignment -> [(FlagName, Bool)]
-unFlagAssignment = id
-#endif
-
-#if !MIN_VERSION_Cabal(2,2,0)
-prettyShow :: Text a => a -> String
-prettyShow = display
-#endif
-
-pkgInfoModule :: Maybe String -> PackageDescription -> LocalBuildInfo -> IO B.ByteString
-pkgInfoModule cName pkgDesc bInfo = do
+pkgInfoModule :: String -> Maybe String -> PackageDescription -> LocalBuildInfo -> IO B.ByteString
+pkgInfoModule moduleName cName pkgDesc bInfo = do
     (tag, revision, branch) <- getVCS >>= \x -> case x of
         Just Mercurial -> hgInfo
         Just Git -> gitInfo
@@ -268,10 +326,11 @@
             [ "{-# LANGUAGE OverloadedStrings #-}"
             , "{-# LANGUAGE RankNTypes #-}"
             , ""
-            , "module " <> (pack . pkgInfoModuleName) cName <> " where"
+            , "module " <> pack moduleName <> " " <> deprecatedMsg <> " where"
             , ""
             , "    import Data.String (IsString)"
             , "    import Data.Monoid"
+            , "    import Prelude hiding ((<>))"
             , ""
             , "    name :: IsString a => Maybe a"
             , "    name = " <> maybe "Nothing" (\x -> "Just \"" <> pack x <> "\"") cName
@@ -365,83 +424,19 @@
     displayOptimisationLevel NormalOptimisation = "normal"
     displayOptimisationLevel MaximumOptimisation = "maximum"
 
-updatePkgInfoModule :: Maybe String -> PackageDescription -> LocalBuildInfo -> IO ()
-updatePkgInfoModule cName pkgDesc bInfo = do
-    createDirectoryIfMissing True $ autogenModulesDir bInfo
-    newFile <- pkgInfoModule cName pkgDesc bInfo
-    let update = B.writeFile fileName newFile
-    doesFileExist fileName >>= \x -> if x
-    then do
-        oldRevisionFile <- B.readFile fileName
-        when (oldRevisionFile /= newFile) update
-    else
-        update
-  where
-    fileName = pkgInfoFileName cName bInfo
+    deprecatedMsg = if moduleName /= pkgInfoModuleName
+        then "{-# DEPRECATED \"Update to Cabal 2.0 or later and use just PkgInfo as module name.\" #-}"
+        else ""
 
 licenseFilesText :: PackageDescription -> IO B.ByteString
 licenseFilesText pkgDesc =
     B.intercalate "\n------------------------------------------------------------\n" <$> mapM fileText
-#ifdef NO_CABAL_MACROS
-        (getLicenseFiles pkgDesc)
-#elif MIN_VERSION_Cabal(1,20,0)
         (licenseFiles pkgDesc)
-#else
-        [licenseFile pkgDesc]
-#endif
   where
     fileText file = doesFileExist file >>= \x -> if x
         then B.readFile file
         else return ""
 
-#ifdef NO_CABAL_MACROS
--- The name and the type of the @licenseFile :: String@ field of
--- 'PackageDescription' changed in Cabal version 1.20 to @licenseFiles ::
--- [String]@. Both versions are used with GHC-7.8. In Cabal version 1.24 the
--- number of constructor fields changed for PackageDescription. When compiling
--- @Setup.hs@ the @MIN_VERSION_...@ macros are not available. This function is
--- an ugly hack to do conditional compilation without CPP. It depends on the
--- @RecordWildCards@ and @Typeable@ extensions and abuses shaddowing of
--- existing symbols.
---
--- Alternative methods would include:
---
--- *   Use typeable to pattern match on the number of constructor arguments for
---     'PackageDescription',
--- *   use TH hacks ala @$( if versionBranch cabalVersion < [...] ... )@, and/or
--- *   make guesses about the cabal version based on the @__GLASGOW_HASKELL__@
---     macro.
-
--- Return license files of from the @PackageDescription@.
---
-getLicenseFiles :: PackageDescription -> [FilePath]
-getLicenseFiles pkgDesc = f pkgDesc
-  where
-    -- Recent versions of @PackageDescription@ define a @licenseFiles@ field.
-    -- For older versions the function @licenseFiles@ that is defined below is
-    -- used.
-    --
-    f PackageDescription{..} = licenseFiles
-
-    -- If @PackageDescription@ doesn't define @licenseFiles@ this definition
-    -- will be used. In that case @PackageDescription@ is assumed to define
-    -- @licenseFile@.
-    --
-    licenseFiles :: [FilePath]
-    licenseFiles = fromMaybe (error "unsupported Cabal library version") $
-        return <$> cast (g pkgDesc)
-
-    g PackageDescription{..} = licenseFile
-
-    -- The only purpose of this function is to ensure that licenseFile is
-    -- defined in case PackageDescription doesn't have a @licenseFile@ field.
-    -- This function won't be called with any supported version of the Cabal
-    -- library.
-    --
-    licenseFile :: [FilePath]
-    licenseFile = error "unexpected Cabal library version"
-#endif
-
 hgInfo :: IO (String, String, String)
 hgInfo = do
     tag <- trim <$> readProcess "hg" ["id", "-r", "max(ancestors(\".\") and tag())", "-t"] ""
@@ -466,11 +461,7 @@
 pkgIdWithLicense :: I.InstalledPackageInfo -> String
 pkgIdWithLicense a = (display . packageId) a
     ++ " ["
-#if MIN_VERSION_Cabal(2,2,0)
-    ++ (either prettyShow prettyShow . I.license) a
-#else
-    ++ (prettyShow . I.license) a
-#endif
+    ++ prettyLicense a
     ++ (if cr /= "" then ", " ++ cr else "")
     ++ "]"
   where
diff --git a/configuration-tools.cabal b/configuration-tools.cabal
--- a/configuration-tools.cabal
+++ b/configuration-tools.cabal
@@ -4,7 +4,7 @@
 -- ------------------------------------------------------ --
 
 Name: configuration-tools
-Version: 0.3.1
+Version: 0.4.0
 Synopsis: Tools for specifying and parsing configurations
 description:
     Tools for specifying and parsing configurations
@@ -39,16 +39,25 @@
     (c) 2014-2015 AlephCloud, Inc.
 Category: Configuration, Console
 Build-type: Custom
-
-cabal-version:  >= 1.18
+cabal-version: 1.24
+tested-with:
+      GHC==8.4.3
+    , GHC==8.2.2
+    , GHC==8.0.2
+    , GHC==7.10.3
 
 extra-doc-files:
     README.md,
     CHANGELOG.md
-    INSTALL_ON_WINDOWS.md
 
-extra-source-files:
-    constraints
+custom-setup
+    setup-depends:
+        Cabal >= 1.24,
+        base >= 4.8 && < 5.0,
+        bytestring >= 0.10.0.2,
+        directory >= 1.2.1.0,
+        filepath >= 1.3.0.1,
+        process >= 1.2.0.0
 
 source-repository head
     type: git
@@ -58,18 +67,13 @@
 source-repository this
     type: git
     location: https://github.com/alephcloud/hs-configuration-tools.git
-    tag: 0.3.1
+    tag: 0.4.0
 
 flag remote-configs
     Description: enable loading of configuration files from HTTP URLs
     Default: True
     Manual: True
 
-flag old-transformers
-    Description: use old transformers
-    Default: False
-    Manual: False
-
 Library
     hs-source-dirs: src
     default-language: Haskell2010
@@ -91,11 +95,11 @@
             Configuration.Utils.Internal.HttpsCertPolicy
 
     build-depends:
-        Cabal >= 1.18,
+        Cabal >= 1.24,
         aeson >= 0.7.0.6,
         ansi-wl-pprint >= 0.6,
         attoparsec >= 0.11.3.4,
-        base >= 4.6 && < 5.0,
+        base >= 4.8 && < 5.0,
         base-unicode-symbols >= 0.2.2.4,
         bytestring >= 0.10.0.2,
         case-insensitive >= 1.2,
@@ -103,25 +107,16 @@
         directory >= 1.2.1.0,
         dlist >= 0.7.1,
         filepath >= 1.3.0.1,
+        mtl >= 2.2,
         network-uri >= 2.6.0.1,
         optparse-applicative >= 0.11.0.2,
         process >= 1.2.0.0,
+        profunctors >= 4.0.4,
+        semigroups >= 0.18,
         text >= 1.0,
+        transformers >= 0.4,
         unordered-containers >= 0.2.4.0,
-        yaml >= 0.8.8.3,
-        profunctors >= 4.0.4,
-        semigroups >= 0.18
-
-    if flag(old-transformers)
-        build-depends:
-            mtl >= 2.1,
-            mtl-compat >= 0.2,
-            transformers >= 0.3 && < 0.4,
-            transformers-compat >= 0.4
-    else
-        build-depends:
-            mtl >= 2.2,
-            transformers >= 0.4
+        yaml >= 0.8.8.3
 
     if flag(remote-configs)
         build-depends:
@@ -156,25 +151,17 @@
         Tests.MonoidConfig
 
     build-depends:
-        base >= 4.6 && < 5.0,
+        Cabal >= 1.24,
+        base >= 4.8 && < 5.0,
         base-unicode-symbols >= 0.2.2.4,
         bytestring >= 0.10,
-        Cabal >= 1.18,
         configuration-tools,
+        mtl >= 2.2,
         text >= 1.0,
+        transformers >= 0.4,
         unordered-containers >= 0.2.4.0,
         yaml >= 0.8.8.3
 
-    if flag(old-transformers)
-        build-depends:
-            mtl >= 2.1,
-            mtl-compat >= 0.2,
-            transformers-compat >= 0.4
-    else
-        build-depends:
-            mtl >= 2.2,
-            transformers >= 0.4
-
     if flag(remote-configs)
         build-depends:
             enclosed-exceptions >= 1.0,
@@ -195,7 +182,7 @@
     hs-source-dirs: examples
 
     build-depends:
-        base >= 4.6 && < 5.0,
+        base >= 4.8 && < 5.0,
         base-unicode-symbols >= 0.2.2.4,
         configuration-tools
 
diff --git a/constraints b/constraints
deleted file mode 100644
--- a/constraints
+++ /dev/null
@@ -1,94 +0,0 @@
-constraints: Cabal ==1.23.1.0,
-             array ==0.5.1.0,
-             base ==4.9.0.0,
-             ghc-prim ==0.5.0.0,
-             rts ==1.0,
-             integer-gmp ==1.0.0.1,
-             binary ==0.8.2.0,
-             bytestring ==0.10.7.0,
-             deepseq ==1.4.2.0,
-             containers ==0.5.7.1,
-             directory ==1.2.5.0,
-             filepath ==1.4.1.0,
-             time ==1.6,
-             unix ==2.7.2.0,
-             pretty ==1.1.3.2,
-             process ==1.4.2.0,
-             aeson ==0.11.0.0,
-             attoparsec ==0.13.0.1,
-             scientific ==0.3.4.4,
-             hashable ==1.2.4.0,
-             text ==1.2.2.0,
-             vector ==0.11.0.0,
-             primitive ==0.6.1.0,
-             transformers ==0.5.1.0,
-             dlist ==0.7.1.2,
-             fail ==4.9.0.0,
-             mtl ==2.2.1,
-             syb ==0.6,
-             template-haskell ==2.11.0.0,
-             ghc-boot ==8.0.0.20160204,
-             unordered-containers ==0.2.6.0,
-             ansi-wl-pprint ==0.6.7.3,
-             ansi-terminal ==0.6.2.3,
-             base-unicode-symbols ==0.2.2.4,
-             base64-bytestring ==1.0.0.1,
-             case-insensitive ==1.2.0.5,
-             connection ==0.2.5,
-             byteable ==0.1.1,
-             data-default-class ==0.0.1,
-             network ==2.6.2.1,
-             socks ==0.5.4,
-             cereal ==0.5.1.0,
-             tls ==1.3.4,
-             asn1-encoding ==0.9.3,
-             asn1-types ==0.3.2,
-             hourglass ==0.2.9,
-             memory ==0.11,
-             async ==2.1.0,
-             stm ==2.4.4.1,
-             cryptonite ==0.11,
-             x509 ==1.6.3,
-             asn1-parse ==0.9.4,
-             pem ==0.2.2,
-             x509-store ==1.6.1,
-             x509-validation ==1.6.3,
-             x509-system ==1.6.3,
-             data-default ==0.5.3,
-             data-default-instances-base ==0.0.1,
-             data-default-instances-containers ==0.0.1,
-             data-default-instances-dlist ==0.0.1,
-             data-default-instances-old-locale ==0.0.1,
-             old-locale ==1.0.0.7,
-             enclosed-exceptions ==1.0.1.1,
-             lifted-base ==0.2.3.6,
-             monad-control ==1.0.0.5,
-             transformers-base ==0.4.4,
-             transformers-compat ==0.5.1.4,
-             http-client ==0.4.27,
-             blaze-builder ==0.4.0.1,
-             cookie ==0.4.1.6,
-             exceptions ==0.8.2.1,
-             http-types ==0.9,
-             mime-types ==0.1.0.6,
-             network-uri ==2.6.0.3,
-             parsec ==3.1.9,
-             random ==1.0.1.1,
-             streaming-commons ==0.1.15.1,
-             zlib ==0.6.1.1,
-             http-client-tls ==0.2.2,
-             optparse-applicative ==0.12.1.0,
-             profunctors ==5.2,
-             base-orphans ==0.5.1,
-             bifunctors ==5.2.1,
-             comonad ==5,
-             contravariant ==1.4,
-             StateVar ==1.1.0.3,
-             semigroups ==0.18.1,
-             void ==0.7.1,
-             distributive ==0.5.0.2,
-             tagged ==0.8.3,
-             yaml ==0.8.16,
-             conduit ==1.2.6.2,
-             mmorph ==1.0.6,
-             resourcet ==1.1.7.2
diff --git a/examples/Example.hs b/examples/Example.hs
--- a/examples/Example.hs
+++ b/examples/Example.hs
@@ -44,7 +44,11 @@
 
 -- This assumes usage of cabal with custom Setup.hs
 --
+#if MIN_VERSION_Cabal(2,0,0)
+import PkgInfo
+#else
 import PkgInfo_url_example_test
+#endif
 
 -- | Specification of the authentication section of a URL.
 --
diff --git a/src/Configuration/Utils/Maybe.hs b/src/Configuration/Utils/Maybe.hs
--- a/src/Configuration/Utils/Maybe.hs
+++ b/src/Configuration/Utils/Maybe.hs
@@ -1,17 +1,11 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE UnicodeSyntax #-}
 
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
-#ifndef MIN_VERSION_base
-#define MIN_VERSION_base(x,y,z) 1
-#endif
-
 -- |
 -- Module: Configuration.Utils.Maybe
 -- Description: Configuration of Optional Values
@@ -33,9 +27,6 @@
 
 ) where
 
-#if ! MIN_VERSION_base(4,8,0)
-import Control.Applicative
-#endif
 import Data.Aeson
 
 -- -------------------------------------------------------------------------- --
diff --git a/src/Configuration/Utils/Operators.hs b/src/Configuration/Utils/Operators.hs
--- a/src/Configuration/Utils/Operators.hs
+++ b/src/Configuration/Utils/Operators.hs
@@ -1,13 +1,7 @@
 {-# LANGUAGE CPP #-}
-{-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE UnicodeSyntax #-}
 
-#ifndef MIN_VERSION_base
-#define MIN_VERSION_base(x,y,z) 1
-#endif
-
 -- |
 -- Module: Configuration.Utils.Operators
 -- Description: Useful operators for defining functions in an applicative context
@@ -28,10 +22,6 @@
 , (<.>)
 , (⊙)
 ) where
-
-#if ! MIN_VERSION_base(4,8,0)
-import Control.Applicative
-#endif
 
 -- -------------------------------------------------------------------------- --
 -- Useful Operators
diff --git a/src/Configuration/Utils/Setup.hs b/src/Configuration/Utils/Setup.hs
--- a/src/Configuration/Utils/Setup.hs
+++ b/src/Configuration/Utils/Setup.hs
@@ -1,9 +1,8 @@
 -- ------------------------------------------------------ --
--- Copyright © 2015-2016 Lars Kuhtz <lakuhtz@gmail.com>
+-- Copyright © 2015-2018 Lars Kuhtz <lakuhtz@gmail.com>
 -- Copyright © 2014 AlephCloud Systems, Inc.
 -- ------------------------------------------------------ --
 
-{-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE ScopedTypeVariables #-}
@@ -14,19 +13,8 @@
 -- process at the end of the configuration phase and generates a module with
 -- package information for each component of the cabal package.
 --
--- The modules are created in the /autogen/ build directory where also the
--- @Path_@ module is created by cabal's simple build setup. This is usually the
--- directory @.\/dist\/build\/autogen@.
---
--- For a library component the module is named just @PkgInfo@. For all other
--- components the module is named @PkgInfo_COMPONENT_NAME@ where
--- @COMPONENT_NAME@ is the name of the component with @-@ characters replaced by
--- @_@.
---
--- For instance, if a cabal package contains a library and an executable that is
--- called /my-app/, the following modules are created: @PkgInfo@ and
--- @PkgInfo_my_app@.
---
+-- The modules are created in the /autogen/ build directories where also the
+-- @Path_@ modules are created by cabal's simple build setup.
 --
 -- = Usage as Setup Script
 --
@@ -111,7 +99,6 @@
 ) where
 
 #ifndef MIN_VERSION_Cabal
-#define NO_CABAL_MACROS 1
 #define MIN_VERSION_Cabal(a,b,c) 0
 #endif
 
@@ -125,6 +112,7 @@
 import Distribution.Text
 
 #if MIN_VERSION_Cabal(2,0,0)
+import qualified Distribution.Compat.Graph as Graph
 import Distribution.Types.LocalBuildInfo
 import Distribution.Types.UnqualComponentName
 #endif
@@ -146,15 +134,16 @@
 
 import Prelude hiding (readFile, writeFile)
 
-import System.Directory (doesFileExist, doesDirectoryExist, createDirectoryIfMissing, getCurrentDirectory, canonicalizePath)
+import System.Directory
+    ( doesFileExist
+    , doesDirectoryExist
+    , createDirectoryIfMissing
+    , getCurrentDirectory
+    , canonicalizePath
+    )
 import System.FilePath (isDrive, (</>), takeDirectory)
 import System.Exit (ExitCode(ExitSuccess))
 
-#ifdef NO_CABAL_MACROS
-import Data.Maybe
-import Data.Typeable
-#endif
-
 -- | Include this function when your setup doesn't contain any
 -- extra functionality.
 --
@@ -168,14 +157,8 @@
 -- If your setup doesn't contain any other function you can just import
 -- the 'main' function from this module.
 --
--- The modules are created in the /autogen/ build directory where also the
--- @Path_@ module is created by cabal's simple build setup. This is usually the
--- directory @.\/dist\/build\/autogen@.
---
--- For a library component the module is named just @PkgInfo@. For all other
--- components the module is named @PkgInfo_COMPONENT_NAME@ where
--- @COMPONENT_NAME@ is the name of the component with @-@ characters replaced by
--- @_@.
+-- The modules are created in the /autogen/ build directories where also the
+-- @Path_@ modules are created by cabal's simple build setup.
 --
 mkPkgInfoModules
     :: UserHooks
@@ -184,6 +167,41 @@
     { postConf = mkPkgInfoModulesPostConf (postConf hooks)
     }
 
+-- -------------------------------------------------------------------------- --
+-- Compat Implementations
+
+#if !MIN_VERSION_Cabal(2,0,0)
+unFlagName :: FlagName -> String
+unFlagName (FlagName s) = s
+#endif
+
+#if !MIN_VERSION_Cabal(2,2,0)
+unFlagAssignment :: FlagAssignment -> [(FlagName, Bool)]
+unFlagAssignment = id
+#endif
+
+#if !MIN_VERSION_Cabal(2,2,0)
+prettyShow :: Text a => a -> String
+prettyShow = display
+#endif
+
+#if !MIN_VERSION_Cabal(2,0,0)
+-- unUnqualComponentName :: UnqualComponentName -> String
+unUnqualComponentName :: String -> String
+unUnqualComponentName = id
+#endif
+
+prettyLicense :: I.InstalledPackageInfo -> String
+#if MIN_VERSION_Cabal(2,2,0)
+prettyLicense = either prettyShow prettyShow . I.license
+#else
+prettyLicense = prettyShow . I.license
+#endif
+
+-- -------------------------------------------------------------------------- --
+-- Cabal 2.0
+
+#if MIN_VERSION_Cabal(2,0,0)
 mkPkgInfoModulesPostConf
     :: (Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ())
     -> Args
@@ -192,6 +210,42 @@
     -> LocalBuildInfo
     -> IO ()
 mkPkgInfoModulesPostConf hook args flags pkgDesc bInfo = do
+    mapM_ (updatePkgInfoModule pkgDesc bInfo) $ Graph.toList $ componentGraph bInfo
+    hook args flags pkgDesc bInfo
+
+updatePkgInfoModule :: PackageDescription -> LocalBuildInfo -> ComponentLocalBuildInfo -> IO ()
+updatePkgInfoModule pkgDesc bInfo clbInfo = do
+    createDirectoryIfMissing True dirName
+    moduleBytes <- pkgInfoModule moduleName cName pkgDesc bInfo
+    updateFile fileName moduleBytes
+
+    -- legacy module
+    legacyModuleBytes <- pkgInfoModule legacyModuleName cName pkgDesc bInfo
+    updateFile legacyFileName legacyModuleBytes
+
+  where
+    dirName = autogenComponentModulesDir bInfo clbInfo
+    cName = unUnqualComponentName <$> componentNameString (componentLocalName clbInfo)
+
+    moduleName = pkgInfoModuleName
+    fileName = dirName ++ "/" ++ moduleName ++ ".hs"
+
+    legacyModuleName = legacyPkgInfoModuleName cName
+    legacyFileName = dirName ++ "/" ++ legacyModuleName ++ ".hs"
+
+-- -------------------------------------------------------------------------- --
+-- Cabal 1.24
+
+#else
+
+mkPkgInfoModulesPostConf
+    :: (Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ())
+    -> Args
+    -> ConfigFlags
+    -> PackageDescription
+    -> LocalBuildInfo
+    -> IO ()
+mkPkgInfoModulesPostConf hook args flags pkgDesc bInfo = do
     mkModules
     hook args flags pkgDesc bInfo
   where
@@ -202,22 +256,41 @@
         CTestName s -> updatePkgInfoModule (Just $ unUnqualComponentName s) pkgDesc bInfo
         CBenchName s -> updatePkgInfoModule (Just $ unUnqualComponentName s) pkgDesc bInfo
 
-#if !MIN_VERSION_Cabal(2,0,0)
-    unUnqualComponentName = id
+updatePkgInfoModule :: Maybe String -> PackageDescription -> LocalBuildInfo -> IO ()
+updatePkgInfoModule cName pkgDesc bInfo = do
+    createDirectoryIfMissing True dirName
+    moduleBytes <- pkgInfoModule moduleName cName pkgDesc bInfo
+    updateFile fileName moduleBytes
+  where
+    dirName = autogenModulesDir bInfo
+    moduleName = legacyPkgInfoModuleName cName
+    fileName = dirName ++ "/" ++ moduleName ++ ".hs"
 #endif
 
-pkgInfoModuleName :: Maybe String -> String
-pkgInfoModuleName Nothing = "PkgInfo"
-pkgInfoModuleName (Just cn) = "PkgInfo_" ++ map tr cn
+-- -------------------------------------------------------------------------- --
+-- Generate PkgInfo Module
+
+pkgInfoModuleName :: String
+pkgInfoModuleName = "PkgInfo"
+
+updateFile :: FilePath -> B.ByteString -> IO ()
+updateFile fileName content = do
+    doesFileExist fileName >>= \x -> if x
+    then do
+        oldRevisionFile <- B.readFile fileName
+        when (oldRevisionFile /= content) update
+    else
+        update
   where
+    update = B.writeFile fileName content
+
+legacyPkgInfoModuleName :: Maybe String -> String
+legacyPkgInfoModuleName Nothing = "PkgInfo"
+legacyPkgInfoModuleName (Just cn) = "PkgInfo_" ++ map tr cn
+  where
     tr '-' = '_'
     tr c = c
 
--- FIXME: autoModulesDir is deprecated and should be replaced by
--- autogenComponentModulesDir.
-pkgInfoFileName :: Maybe String -> LocalBuildInfo -> FilePath
-pkgInfoFileName cn bInfo = autogenModulesDir bInfo ++ "/" ++ pkgInfoModuleName cn ++ ".hs"
-
 trim :: String -> String
 trim = f . f
   where f = reverse . dropWhile isSpace
@@ -236,23 +309,8 @@
             then return Nothing
             else getVcsOfDir (takeDirectory canonicDir)
 
-#if !MIN_VERSION_Cabal(2,0,0)
-unFlagName :: FlagName -> String
-unFlagName (FlagName s) = s
-#endif
-
-#if !MIN_VERSION_Cabal(2,2,0)
-unFlagAssignment :: FlagAssignment -> [(FlagName, Bool)]
-unFlagAssignment = id
-#endif
-
-#if !MIN_VERSION_Cabal(2,2,0)
-prettyShow :: Text a => a -> String
-prettyShow = display
-#endif
-
-pkgInfoModule :: Maybe String -> PackageDescription -> LocalBuildInfo -> IO B.ByteString
-pkgInfoModule cName pkgDesc bInfo = do
+pkgInfoModule :: String -> Maybe String -> PackageDescription -> LocalBuildInfo -> IO B.ByteString
+pkgInfoModule moduleName cName pkgDesc bInfo = do
     (tag, revision, branch) <- getVCS >>= \x -> case x of
         Just Mercurial -> hgInfo
         Just Git -> gitInfo
@@ -268,10 +326,11 @@
             [ "{-# LANGUAGE OverloadedStrings #-}"
             , "{-# LANGUAGE RankNTypes #-}"
             , ""
-            , "module " <> (pack . pkgInfoModuleName) cName <> " where"
+            , "module " <> pack moduleName <> " " <> deprecatedMsg <> " where"
             , ""
             , "    import Data.String (IsString)"
             , "    import Data.Monoid"
+            , "    import Prelude hiding ((<>))"
             , ""
             , "    name :: IsString a => Maybe a"
             , "    name = " <> maybe "Nothing" (\x -> "Just \"" <> pack x <> "\"") cName
@@ -365,83 +424,19 @@
     displayOptimisationLevel NormalOptimisation = "normal"
     displayOptimisationLevel MaximumOptimisation = "maximum"
 
-updatePkgInfoModule :: Maybe String -> PackageDescription -> LocalBuildInfo -> IO ()
-updatePkgInfoModule cName pkgDesc bInfo = do
-    createDirectoryIfMissing True $ autogenModulesDir bInfo
-    newFile <- pkgInfoModule cName pkgDesc bInfo
-    let update = B.writeFile fileName newFile
-    doesFileExist fileName >>= \x -> if x
-    then do
-        oldRevisionFile <- B.readFile fileName
-        when (oldRevisionFile /= newFile) update
-    else
-        update
-  where
-    fileName = pkgInfoFileName cName bInfo
+    deprecatedMsg = if moduleName /= pkgInfoModuleName
+        then "{-# DEPRECATED \"Update to Cabal 2.0 or later and use just PkgInfo as module name.\" #-}"
+        else ""
 
 licenseFilesText :: PackageDescription -> IO B.ByteString
 licenseFilesText pkgDesc =
     B.intercalate "\n------------------------------------------------------------\n" <$> mapM fileText
-#ifdef NO_CABAL_MACROS
-        (getLicenseFiles pkgDesc)
-#elif MIN_VERSION_Cabal(1,20,0)
         (licenseFiles pkgDesc)
-#else
-        [licenseFile pkgDesc]
-#endif
   where
     fileText file = doesFileExist file >>= \x -> if x
         then B.readFile file
         else return ""
 
-#ifdef NO_CABAL_MACROS
--- The name and the type of the @licenseFile :: String@ field of
--- 'PackageDescription' changed in Cabal version 1.20 to @licenseFiles ::
--- [String]@. Both versions are used with GHC-7.8. In Cabal version 1.24 the
--- number of constructor fields changed for PackageDescription. When compiling
--- @Setup.hs@ the @MIN_VERSION_...@ macros are not available. This function is
--- an ugly hack to do conditional compilation without CPP. It depends on the
--- @RecordWildCards@ and @Typeable@ extensions and abuses shaddowing of
--- existing symbols.
---
--- Alternative methods would include:
---
--- *   Use typeable to pattern match on the number of constructor arguments for
---     'PackageDescription',
--- *   use TH hacks ala @$( if versionBranch cabalVersion < [...] ... )@, and/or
--- *   make guesses about the cabal version based on the @__GLASGOW_HASKELL__@
---     macro.
-
--- Return license files of from the @PackageDescription@.
---
-getLicenseFiles :: PackageDescription -> [FilePath]
-getLicenseFiles pkgDesc = f pkgDesc
-  where
-    -- Recent versions of @PackageDescription@ define a @licenseFiles@ field.
-    -- For older versions the function @licenseFiles@ that is defined below is
-    -- used.
-    --
-    f PackageDescription{..} = licenseFiles
-
-    -- If @PackageDescription@ doesn't define @licenseFiles@ this definition
-    -- will be used. In that case @PackageDescription@ is assumed to define
-    -- @licenseFile@.
-    --
-    licenseFiles :: [FilePath]
-    licenseFiles = fromMaybe (error "unsupported Cabal library version") $
-        return <$> cast (g pkgDesc)
-
-    g PackageDescription{..} = licenseFile
-
-    -- The only purpose of this function is to ensure that licenseFile is
-    -- defined in case PackageDescription doesn't have a @licenseFile@ field.
-    -- This function won't be called with any supported version of the Cabal
-    -- library.
-    --
-    licenseFile :: [FilePath]
-    licenseFile = error "unexpected Cabal library version"
-#endif
-
 hgInfo :: IO (String, String, String)
 hgInfo = do
     tag <- trim <$> readProcess "hg" ["id", "-r", "max(ancestors(\".\") and tag())", "-t"] ""
@@ -466,11 +461,7 @@
 pkgIdWithLicense :: I.InstalledPackageInfo -> String
 pkgIdWithLicense a = (display . packageId) a
     ++ " ["
-#if MIN_VERSION_Cabal(2,2,0)
-    ++ (either prettyShow prettyShow . I.license) a
-#else
-    ++ (prettyShow . I.license) a
-#endif
+    ++ prettyLicense a
     ++ (if cr /= "" then ", " ++ cr else "")
     ++ "]"
   where
diff --git a/src/Configuration/Utils/Validation.hs b/src/Configuration/Utils/Validation.hs
--- a/src/Configuration/Utils/Validation.hs
+++ b/src/Configuration/Utils/Validation.hs
@@ -6,10 +6,6 @@
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE UnicodeSyntax #-}
 
-#ifndef MIN_VERSION_base
-#define MIN_VERSION_base(x,y,z) 1
-#endif
-
 -- |
 -- Module: Configuration.Utils.Validation
 -- Copyright: Copyright © 2014 AlephCloud Systems, Inc.
@@ -71,18 +67,12 @@
 
 import Configuration.Utils.Internal
 
-#if ! MIN_VERSION_base(4,8,0)
-import Control.Applicative
-#endif
 import Control.Monad.Error.Class
 import Control.Monad
 import Control.Monad.IO.Class
 import Control.Monad.Writer.Class
 
 import qualified Data.Foldable as F
-#if ! MIN_VERSION_base(4,8,0)
-import Data.Monoid
-#endif
 import Data.Monoid.Unicode
 import qualified Data.Text as T
 
diff --git a/test/TestExample.hs b/test/TestExample.hs
--- a/test/TestExample.hs
+++ b/test/TestExample.hs
@@ -2,7 +2,6 @@
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE GADTs #-}
-{-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ScopedTypeVariables #-}
@@ -38,7 +37,11 @@
 
 import Prelude.Unicode
 
+#if MIN_VERSION_Cabal(2,0,0)
+import PkgInfo
+#else
 import PkgInfo_url_example_test
+#endif
 
 -- -------------------------------------------------------------------------- --
 -- main
