diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+# 2.1.0 (2023-02-15)
+- spec: list out ghc-*-prof BRs separately from ghc-*-devel
+- spec: output SPDX license tags
+- spec: for standalone f36+ cabal-install needs %ghc_set_gcc_flags"
+- spec: handle '.' paragraph separator lines in description
+- spec: initial support for --with-ghc version to build with ghcX.Y
+- spec: check if deps of missing deps available
+- spec: for --standalone define %cabal_install for cabal
+- Stackage: default to latest lts-20 stream
+- refresh: build cabal-rpm in tempdir
+- PackageUtils rpmbuild: no longer override _builddir, _rpmdir, _srcrpmdir
+- PackageUtils tryUnpack: now into %_builddir
+- PackageUtils patchSpec: show .rej if patch fails
+- PackageUtils: handle tools like ghc-tags which are not a library
+- always assume revised .cabal is wanted/used
+- remove all the keep logic for tmpdir processing
+- allow Cabal-3.8
+- GH action: add 9.4 and bump actions versions
+- Diff: use extra withTempDir
+- simplify withTempDirectory with withCurrentDirectory
+
 # 2.0.11.1 (2022-03-28)
 - support building with Cabal 3.6
 
diff --git a/cabal-rpm.cabal b/cabal-rpm.cabal
--- a/cabal-rpm.cabal
+++ b/cabal-rpm.cabal
@@ -1,5 +1,5 @@
 Name:                cabal-rpm
-Version:             2.0.11.1
+Version:             2.1.0
 Synopsis:            RPM packaging tool for Haskell Cabal-based packages
 Description:
     This package provides a RPM packaging tool for Haskell Cabal-based packages.
@@ -20,15 +20,15 @@
                      Bryan O'Sullivan <bos@serpentine.com>
 Maintainer:          Jens Petersen <petersen@fedoraproject.org>
 Copyright:           2007-2008 Bryan O'Sullivan <bos@serpentine.com>,
-                     2012-2022 Jens Petersen <juhpetersen@gmail.com>
+                     2012-2023 Jens Petersen <juhpetersen@gmail.com>
 Category:            Distribution
 Build-type:          Simple
 Extra-doc-files:     ChangeLog README.md TODO
 Extra-source-files:  man/cabal-rpm.1.md
 Cabal-version:       1.18
-Tested-with:         GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.3,
-                     GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4,
-                     GHC == 8.6.5, GHC == 8.8.4, GHC == 8.10.5
+Tested-with:         GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4,
+                     GHC == 8.6.5, GHC == 8.8.4, GHC == 8.10.7,
+                     GHC == 9.0.2, GHC == 9.2.5
 
 source-repository head
   type:     git
@@ -45,14 +45,14 @@
 Executable cabal-rpm
     Main-is:            Main.hs
     Build-depends: base < 5,
-                   Cabal > 1.10 && < 3.7,
+                   Cabal > 1.10 && < 3.9,
                    directory,
                    extra,
-                   filepath,
+                   filepath >= 1.4,
                    optparse-applicative,
                    process,
                    simple-cabal >= 0.1.3,
-                   simple-cmd >= 0.2.0,
+                   simple-cmd >= 0.2.3,
                    simple-cmd-args >= 0.1.6,
                    unix
     if flag(old-locale)
diff --git a/src/Commands/Depends.hs b/src/Commands/Depends.hs
--- a/src/Commands/Depends.hs
+++ b/src/Commands/Depends.hs
@@ -25,8 +25,7 @@
 import PackageUtils (PackageData (..), prepare)
 import Types
 
-#if (defined(MIN_VERSION_base) && MIN_VERSION_base(4,8,0))
-#else
+#if !MIN_VERSION_base(4,8,0)
 import Control.Applicative ((<$>))
 #endif
 import Control.Monad (filterM, unless, void)
@@ -39,7 +38,7 @@
 
 depends :: Depends -> Flags -> Maybe PackageVersionSpecifier -> IO ()
 depends action flags mpvs = do
-  pkgdata <- prepare flags mpvs False False
+  pkgdata <- prepare flags mpvs
   let pkgDesc = packageDesc pkgdata
   case action of
     Depends -> do
diff --git a/src/Commands/Diff.hs b/src/Commands/Diff.hs
--- a/src/Commands/Diff.hs
+++ b/src/Commands/Diff.hs
@@ -20,39 +20,36 @@
   ) where
 
 import Commands.Spec (createSpecFile)
-import FileUtils (mktempdir)
 import PackageUtils (dropChangelog, editSpecField, getSpecField,
                      PackageData (..), prepare)
 import Types
 
-#if (defined(MIN_VERSION_base) && MIN_VERSION_base(4,8,0))
-#else
+#if !MIN_VERSION_base(4,8,0)
 import Control.Applicative ((<$>))
 #endif
 import Control.Monad
 import Distribution.Verbosity (silent)
 import SimpleCmd (grep_, error', pipe)
-import System.Directory (removeDirectoryRecursive)
 import System.FilePath ((<.>))
+import System.IO.Extra (withTempDir)
 import System.Posix.Env (getEnvDefault)
 
 diff :: Flags -> PackageType -> Maybe PackageVersionSpecifier -> IO ()
 diff flags pkgtype mpvs = do
-  pkgdata <- prepare flags mpvs True False
+  pkgdata <- prepare flags mpvs
   case specFilename pkgdata of
     Nothing -> error' "No (unique) .spec file in directory."
     Just spec -> do
       subpkg <- grep_ "%{subpkgs}" spec
-      tmpdir <- mktempdir
-      speccblrpm <- createSpecFile False True False silent flags False False pkgtype (if subpkg then Just Nothing else Nothing) (Just tmpdir) mpvs
-      currel <- getSpecField "Release" spec
-      let suffix = "%{?dist}"
-      editSpecField "Release" (currel ++ suffix) speccblrpm
-      diffcmd <- words <$> getEnvDefault "CBLRPM_DIFF" "diff -u"
-      out <- dropChangelog <$> pipe (head diffcmd, tail diffcmd ++ [spec, speccblrpm])
-      ---- was for %autorelease:
-      -- out <- pipe (head diffcmd, tail diffcmd ++ [spec, speccblrpm])
-        ("sed", ["-e", "s%" ++ speccblrpm ++ "%" ++ spec <.> "cblrpm" ++ "%"])
-      unless (null out) $
-        putStrLn out
-      removeDirectoryRecursive tmpdir
+      withTempDir $ \tmpdir -> do
+        speccblrpm <- createSpecFile False silent flags False False pkgtype (if subpkg then Just Nothing else Nothing) Nothing (Just tmpdir) mpvs
+        currel <- getSpecField "Release" spec
+        let suffix = "%{?dist}"
+        editSpecField "Release" (currel ++ suffix) speccblrpm
+        diffcmd <- words <$> getEnvDefault "CBLRPM_DIFF" "diff -u"
+        out <- dropChangelog <$> pipe (head diffcmd, tail diffcmd ++ [spec, speccblrpm])
+        ---- was for %autorelease:
+        -- out <- pipe (head diffcmd, tail diffcmd ++ [spec, speccblrpm])
+          ("sed", ["-e", "s%" ++ speccblrpm ++ "%" ++ spec <.> "cblrpm" ++ "%"])
+        unless (null out) $
+          putStrLn out
diff --git a/src/Commands/Install.hs b/src/Commands/Install.hs
--- a/src/Commands/Install.hs
+++ b/src/Commands/Install.hs
@@ -30,10 +30,6 @@
 import SimpleCmd (cmd_, (+-+))
 import SimpleCmd.Rpm (rpmspec)
 
-#if (defined(MIN_VERSION_base) && MIN_VERSION_base(4,8,0))
-#else
---import Control.Applicative ((<$>))
-#endif
 import Control.Monad (unless, when)
 import Distribution.Text (display)
 import System.FilePath ((</>))
@@ -47,7 +43,7 @@
   mspec <- checkForSpecFile (pvsPackage =<< mpvs)
   case mspec of
     Nothing ->
-      withTempDirectory $ \ _ -> do
+      withTempDirectory $ do
       spec <- rpmBuild Binary False flags pkgtype subpackage mpvs
       rpmdir <- rpmEval "%{_rpmdir}"
       rpmspec [] (fmap (</> "%{arch}/%{name}-%{version}-%{release}.%{arch}.rpm") rpmdir) spec >>= rpmInstall False
@@ -61,6 +57,6 @@
   noPkg <- notInstalled $ RpmHsLib Prof pkg
   when noPkg $ do
     let dep = display pkg
-    withTempDirectory $ \ _ -> do
+    withTempDirectory $ do
       putStrLn $ "Running cabal-rpm install" +-+ dep
       cmd_ "cabal-rpm" ["install", dep]
diff --git a/src/Commands/Refresh.hs b/src/Commands/Refresh.hs
--- a/src/Commands/Refresh.hs
+++ b/src/Commands/Refresh.hs
@@ -27,23 +27,19 @@
 import SimpleCmd (cmd, cmd_, error', grep_)
 import SimpleCmd.Git (rwGitDir)
 
-#if (defined(MIN_VERSION_base) && MIN_VERSION_base(4,8,0))
-#else
-import Control.Applicative ((<$>))
-#endif
 import Control.Monad (unless, when)
-import Data.Maybe
 import Data.Version (showVersion)
 import Distribution.Verbosity (silent)
-import SimpleCabal (customFieldsPD)
-import System.Directory (createDirectoryIfMissing, doesFileExist, renameFile)
+import System.Directory (createDirectoryIfMissing, doesFileExist,
+                         renameFile, withCurrentDirectory)
 import System.Environment (getEnv)
 --import System.Exit (exitSuccess)
 import System.FilePath ((</>), (<.>))
+import System.IO.Extra (withTempDir)
 
 refresh :: Bool -> PackageType -> Maybe PackageVersionSpecifier -> IO ()
 refresh dryrun pkgtype mpvs = do
-  pkgdata <- prepare [] mpvs True True
+  pkgdata <- prepare [] mpvs
   case specFilename pkgdata of
     Nothing -> error' "No (unique) .spec file in directory."
     Just spec -> do
@@ -63,9 +59,8 @@
                   DefaultPkg | "--standalone" `elem` headerwords -> StandalonePkg
                   _ -> pkgtype
           subpkg <- grep_ "%{subpkgs}" spec
-          let wasrevised = isJust $ lookup "x-revision" $ customFieldsPD (packageDesc pkgdata)
           oldspec <- createOldSpec subpkg cblrpmver spec
-          newspec <- createSpecFile True wasrevised False silent [] False False spectype (if subpkg then Just Nothing else Nothing) Nothing mpvs
+          newspec <- createSpecFile False silent [] False False spectype (if subpkg then Just Nothing else Nothing) Nothing Nothing mpvs
           patchSpec dryrun Nothing oldspec newspec
 --          setCurrentDirectory cwd
 --          when rwGit $
@@ -91,7 +86,9 @@
         haveExe <- doesFileExist $ bindir </> cblrpmver
         unless haveExe $ do
           createDirectoryIfMissing True bindir
-          cabal_ "install" ["--enable-executable-stripping",
-                            "--installdir=" ++ bindir, cblrpmver]
-          renameFile (bindir </> "cabal-rpm") (bindir </> cblrpmver)
+          withTempDir $ \tmpdir ->
+            withCurrentDirectory tmpdir $ do
+            cabal_ "install" ["--enable-executable-stripping",
+                              "--installdir=" ++ bindir, cblrpmver]
+            renameFile (bindir </> "cabal-rpm") (bindir </> cblrpmver)
         cmd_ (bindir </> cblrpmver) $ "spec" : "--quiet" : ["--subpackage" | subpkg]
diff --git a/src/Commands/RpmBuild.hs b/src/Commands/RpmBuild.hs
--- a/src/Commands/RpmBuild.hs
+++ b/src/Commands/RpmBuild.hs
@@ -30,26 +30,22 @@
 import SimpleCabal (package)
 import SimpleCmd ((+-+))
 
-#if (defined(MIN_VERSION_base) && MIN_VERSION_base(4,8,0))
-#else
---import Control.Applicative ((<$>))
-#endif
 import Control.Monad (void, when)
 import Distribution.Verbosity (normal)
 
 rpmBuild :: RpmStage -> Bool -> Flags -> PackageType -> Bool
          -> Maybe PackageVersionSpecifier -> IO FilePath
 rpmBuild stage quiet flags pkgtype subpackage mpvs = do
-  pkgdata <- prepare flags mpvs True False
+  pkgdata <- prepare flags mpvs
   when (stage == Binary) $
     void $ pkgInstallMissing' pkgdata
   let pkgDesc = packageDesc pkgdata
       mspec = specFilename pkgdata
-  specFile <- maybe (createSpecFile False True False normal flags False False pkgtype (if subpackage then Just Nothing else Nothing) Nothing mpvs)
+  specFile <- maybe (createSpecFile False normal flags False False pkgtype (if subpackage then Just Nothing else Nothing) Nothing Nothing mpvs)
               (\ s -> putStrLn ("Using existing" +-+ s) >> return s)
               mspec
   let pkgid = package pkgDesc
-  bringTarball pkgid True (Just specFile)
+  bringTarball pkgid (Just specFile)
   rpmbuild quiet stage specFile
 
   return specFile
diff --git a/src/Commands/Spec.hs b/src/Commands/Spec.hs
--- a/src/Commands/Spec.hs
+++ b/src/Commands/Spec.hs
@@ -27,14 +27,12 @@
 import Header (headerOption, withSpecHead)
 import PackageUtils (bringTarball, latestPackage, PackageData (..), prepare)
 import SimpleCabal (buildable, mkPackageName, PackageDescription (..),
-                    PackageIdentifier(..), PackageName, showVersion)
-import SimpleCmd ((+-+),
-#if MIN_VERSION_simple_cmd(0,2,2)
-                  grep,
+                    PackageIdentifier(..), PackageName
+#if !MIN_VERSION_Cabal(2,2,0)
+                    , showVersion
 #endif
-                  cmd,
-                  cmdMaybe,
-                  grep_, removePrefix)
+                   )
+import SimpleCmd ((+-+), cmd, cmdMaybe, grep, grep_, removePrefix)
 import Stackage (defaultLTS)
 import Types
 
@@ -46,36 +44,36 @@
 
 import Data.Char        (toUpper)
 import Data.List.Extra
-import Data.Maybe       (isJust, fromMaybe, fromJust)
+import Data.Maybe       (isJust, isNothing, fromMaybe, fromJust)
 import Data.Time.Clock  (getCurrentTime)
 import Data.Time.Format (formatTime)
 import qualified Data.Version as V
 
-import Distribution.Text (display)
-import Distribution.License  (License (..)
-#if defined(MIN_VERSION_Cabal) && MIN_VERSION_Cabal(2,2,0)
-                             , licenseFromSPDX
+#if !MIN_VERSION_Cabal(2,2,0)
+import Distribution.License (License (..))
 #endif
-                             )
-
 import Distribution.PackageDescription (
                                         Executable (buildInfo),
                                         Library (exposedModules), exeName,
                                         hasExes, hasLibs,
-#if defined(MIN_VERSION_Cabal) && MIN_VERSION_Cabal(2,2,0)
+#if MIN_VERSION_Cabal(2,2,0)
                                         license,
 #endif
                                        )
+#if MIN_VERSION_Cabal(2,2,0)
+import Distribution.Pretty (prettyShow)
+#endif
 import Distribution.Simple.Utils (warn)
+import Distribution.Text (display)
 
-#if defined(MIN_VERSION_Cabal) && MIN_VERSION_Cabal(2,0,0)
+#if MIN_VERSION_Cabal(2,0,0)
 import Distribution.Types.UnqualComponentName (unUnqualComponentName)
 #endif
 import Distribution.Verbosity (Verbosity)
 
 import System.Directory (doesFileExist)
 import System.IO     (IOMode (..), hClose, hPutStrLn, openFile)
-#if defined(MIN_VERSION_time) && MIN_VERSION_time(1,5,0)
+#if MIN_VERSION_time(1,5,0)
 import Data.Time.Format (defaultTimeLocale)
 #else
 import System.Locale (defaultTimeLocale)
@@ -84,24 +82,23 @@
 
 import qualified Paths_cabal_rpm (version)
 
-#if defined(MIN_VERSION_Cabal) && MIN_VERSION_Cabal(3,2,0)
+#if MIN_VERSION_Cabal(3,2,0)
 import qualified Distribution.Utils.ShortText as ST (fromShortText)
 #endif
 
 
-#if defined(MIN_VERSION_Cabal) && MIN_VERSION_Cabal(2,0,0)
-#else
+#if !MIN_VERSION_Cabal(2,0,0)
 unUnqualComponentName :: String -> String
 unUnqualComponentName = id
 #endif
 
 -- FIXME use datatype for options
-createSpecFile :: Bool -> Bool -> Bool -> Verbosity -> Flags -> Bool -> Bool
-               -> PackageType -> Maybe (Maybe Stream) -> Maybe FilePath
-               -> Maybe PackageVersionSpecifier
+createSpecFile :: Bool -> Verbosity -> Flags -> Bool -> Bool
+               -> PackageType -> Maybe (Maybe Stream) -> Maybe V.Version
+               -> Maybe FilePath -> Maybe PackageVersionSpecifier
                -> IO FilePath
-createSpecFile keep revise ignoreMissing verbose flags testsuite force pkgtype subpkgStream mdest mpvs = do
-  pkgdata <- prepare flags mpvs revise keep
+createSpecFile ignoreMissing verbose flags testsuite force pkgtype subpkgStream mwithghc mdest mpvs = do
+  pkgdata <- prepare flags mpvs
   let mspec = case pkgtype of
                 SpecFile f -> Just f
                 _ -> specFilename pkgdata
@@ -151,11 +148,15 @@
       hasLibPkg = hasLib && not standalone
       dupdocs = docs `intersect` dataFiles pkgDesc
       datafiles = dataFiles pkgDesc \\ dupdocs
-  (pkgname, binlib) <- getPkgName mspec pkgDesc (pkgtype == BinaryPkg || standalone)
+      ghc_name = if isJust mwithghc then "%{ghc_name}" else "ghc"
+      majorVer = V.showVersion . V.makeVersion . take 2 . V.versionBranch
+      ghcname = "ghc" ++ maybe "" majorVer mwithghc
+  -- FIXME is binlib misnamed?
+  (pkgname, binlib) <- getPkgName mspec ghcname pkgDesc (pkgtype == BinaryPkg || standalone)
   let pkg_name = if pkgname == name then "%{name}" else "%{pkg_name}"
       basename | binlib = "%{pkg_name}"
                | hasExecPkg = name
-               | otherwise = "ghc-%{pkg_name}"
+               | otherwise = ghc_name ++ "-%{pkg_name}"
       targetSpecFile = fromMaybe "" mdest </> pkgname <.> "spec"
       hasExecPkg = binlib || (hasExec && not hasLibPkg)
   targetSpecAlreadyExists <- doesFileExist targetSpecFile
@@ -196,16 +197,20 @@
       sectionNewline = putNewline >> putNewline
       put = hPutStrLn h
       global m v = put $ "%global" +-+ m +-+ v
-      subpkgParam lt = if binlib then "-n ghc-%{name}" ++ pkgSuffix lt else show lt
+      subpkgParam lt = if binlib then "-n" +-+ ghc_name ++ "-%{name}" ++ pkgSuffix lt else show lt
 
   put $ "# generated by cabal-rpm-" ++ V.showVersion Paths_cabal_rpm.version
     +-+ unwords (["--standalone" | standalone] ++ ["--stream " ++ showStream (fromJust mstream) | isJust mstream, mstream /= Just defaultLTS] ++ ["--subpackage" | subpackage])
   put "# https://docs.fedoraproject.org/en-US/packaging-guidelines/Haskell/"
   putNewline
 
+  when (isJust mwithghc) $ do
+    global "ghc_name" ghcname
+    putNewline
+
   -- Some packages conflate the synopsis and description fields.  Ugh.
   let syn =
-#if defined(MIN_VERSION_Cabal) && MIN_VERSION_Cabal(3,2,0)
+#if MIN_VERSION_Cabal(3,2,0)
         ST.fromShortText $
 #endif
         synopsis pkgDesc
@@ -221,13 +226,15 @@
     warn verbose "this package has a long synopsis."
 
   let descr =
-#if defined(MIN_VERSION_Cabal) && MIN_VERSION_Cabal(3,2,0)
+#if MIN_VERSION_Cabal(3,2,0)
         ST.fromShortText $
 #endif
         description pkgDesc
   when (null descr) $
     warn verbose "this package has no description."
-  let descLines = (formatParagraphs . initialCapital . filterSymbols . finalPeriod) $ if null descr then syn' else descr
+  let descLines = (formatParagraphs . initialCapital . filterSymbols . finalPeriod . paragraphPeriods) $ if null descr then syn' else descr
+      paragraphPeriods =
+        unlines . map (\l -> if l == "." then "" else l) . lines
       finalPeriod cs = case last cs of
                          '.' -> cs
                          '\n' -> finalPeriod $ init cs
@@ -274,7 +281,7 @@
 
   let (testsuiteDeps,testsuiteTools) = testsuiteDependencies' pkgDesc
   missTestDeps <- filterM (notSrcOrInst . RpmHsLib Devel) testsuiteDeps
-  let testable = notNull testsuiteDeps && not standalone && (null missTestDeps || testsuite)
+  let testable = notNull testsuiteDeps && not standalone && (null missTestDeps || testsuite) && isNothing mwithghc
   if testable then do
     put "%bcond_without tests"
     putNewline
@@ -287,11 +294,9 @@
     if isJust $ lookup "x-revision" (customFieldsPD pkgDesc)
     then return True
     else do
-      if revise then do
-        let local = display pkgid <.> "cabal"
-        have <- doesFileExist local
-        if have then grep_ "x-revision" local else return False
-      else return False
+    let local = display pkgid <.> "cabal"
+    have <- doesFileExist local
+    if have then grep_ "x-revision" local else return False
   revisedDOS <- if revised then do
     filetype <- cmd "file" ["-b", display pkgid <.> "cabal"]
     return $ "CRLF" `isInfixOf` filetype
@@ -307,11 +312,7 @@
     putHdr "Release" $ release ++ "%{?dist}"
   putHdr "Summary" summary
   putNewline
-#if defined(MIN_VERSION_Cabal) && MIN_VERSION_Cabal(2,2,0)
-#else
-  let licenseFromSPDX = id
-#endif
-  putHdr "License" $ (showLicense . licenseFromSPDX . license) pkgDesc
+  putHdr "License" $ (prettyShow . license) pkgDesc
   putHdr "Url" $ "https://hackage.haskell.org/package" </> pkg_name
   put "# Begin cabal-rpm sources:"
   putHdr "Source0" $ sourceUrl pkgver
@@ -325,31 +326,38 @@
   when (mkPackageName "Cabal" `notElem` buildDeps pkgdeps || not hasLib || notNull (setupDeps pkgdeps)) $ do
 --    put "# Setup"
     when (mkPackageName "Cabal" `notElem` buildDeps pkgdeps) $
-      putHdr "BuildRequires" "ghc-Cabal-devel"
+      putHdr "BuildRequires" $ ghc_name ++ "-Cabal-devel"
     mapM_ (\ d -> (if d `elem` missingLibs then putHdrComment else putHdr) "BuildRequires" (showRpm (RpmHsLib Devel d))) $ setupDeps pkgdeps
   putHdr "BuildRequires" $ "ghc-rpm-macros" ++ (if hasSubpkgs then "-extra" else "")
 
   unless (null (buildDeps pkgdeps)) $ do
 --    put "# Build"
+    when (isJust mwithghc) $ do
+      put "%if %{defined ghc_name}"
+      putHdr "BuildRequires" $ "%{ghc_name}" ++ "-devel"
+      putHdr "BuildRequires" $ "%{ghc_name}" ++ "-prof"
+      put "%else"
+
     let metaPackages = map mkPackageName ["haskell-gi-overloading"]
-        ghcLibDep d | d `elem` metaPackages = RpmHsLib Devel d
-                    | otherwise = (RpmHsLib $ if standalone then Devel else if hasLibPkg then Prof else Static) d
-    mapM_ (\ d -> (if d `elem` missingLibs then putHdrComment else putHdr) "BuildRequires" (showRpm (ghcLibDep d))) $ sort $ buildDeps pkgdeps
+    mapM_ (\ d -> (if d `elem` missingLibs then putHdrComment else putHdr) "BuildRequires" (showRpm (RpmHsLib Devel d))) $ sort $ buildDeps pkgdeps
+    when hasLibPkg $ do
+      put "%if %{with ghc_prof}"
+      mapM_ (\ d -> (if d `elem` missingLibs then putHdrComment else putHdr) "BuildRequires" (showRpm (RpmHsLib Prof d))) $ sort $ buildDeps pkgdeps \\ metaPackages
+      put "%endif"
   let otherdeps = sort $ toolDeps pkgdeps ++ clibDeps pkgdeps ++ pkgcfgDeps pkgdeps
   unless (null otherdeps) $ do
 --    put "# Other"
     missingOthers <- missingOtherPkgs pkgDesc
     mapM_ (\ d -> (if d `elem` missingOthers then putHdrComment else putHdr) "BuildRequires" d) otherdeps
-    -- -- for ghc < 7.8:
-    -- when (epel7 &&
-    --       any (\ d -> d `elem` map showDep ["template-haskell", "hamlet"]) deps) $
-    --   putHdr "ExclusiveArch" "%{ghc_arches_with_ghci}"
   let testDeps = testsuiteDeps \\ (mkPackageName "Cabal" : (buildDeps pkgdeps ++ setupDeps pkgdeps))
   when (testable && notNull testDeps) $ do
     put "%if %{with tests}"
     mapM_ (putHdr "BuildRequires") $ (sort . map showRpm) (map (RpmHsLib Devel) testDeps ++ map RpmOther (testsuiteTools \\ toolDeps pkgdeps))
     put "%endif"
 
+  when (isJust mwithghc) $
+    put "%endif"
+
   let common = binlib && datafiles /= [] && not standalone
       versionRelease = " = %{version}-%{release}"
   when common $
@@ -359,13 +367,21 @@
       putHdr "BuildRequires" "cabal-install > 1.18"
     unless (null missingLibs || ignoreMissing) $ do
       putStrLn "checking for deps of missing dependencies:"
-      let deptype = if standalone then Devel else Prof
+      -- let deptype = if standalone then Devel else Prof
+      when (isJust mwithghc) $
+        put "%if %{undefined ghc_name}"
       forM_ missingLibs $ \ pkg -> do
         more <- packageDeps flags (streamSubpackage mstream subpkgStream) pkg
         let moredeps = sort $ more \\ (buildDeps pkgdeps ++ missingLibs)
         unless (null moredeps) $ do
           put $ "# for missing dep '" ++ display pkg ++ "':"
-          mapM_ (\ d -> (if d `elem` missingLibs then putHdrComment else putHdr) "BuildRequires" (showRpm (RpmHsLib deptype d))) moredeps
+          missingMore <- filterM (notSrcOrInst . RpmHsLib Devel) moredeps
+          mapM_ (\ d -> (if d `elem` missingMore then putHdrComment else putHdr) "BuildRequires" (showRpm (RpmHsLib Devel d))) moredeps
+          put "%if %{with ghc_prof}"
+          mapM_ (\ d -> (if d `elem` missingMore then putHdrComment else putHdr) "BuildRequires" (showRpm (RpmHsLib Prof d))) moredeps
+          put "%endif"
+      when (isJust mwithghc) $
+        put "%endif"
   put "# End cabal-rpm deps"
   putNewline
 
@@ -389,7 +405,7 @@
   --  but libraries wihout exposedModules should be useless/redundant)
   let hasModules =
         hasLib && (isJust (library pkgDesc) && (notNull . exposedModules . fromJust . library) pkgDesc || mkPackageName "haskell-gi" `elem` (buildDeps pkgdeps ++ setupDeps pkgdeps))
-      baselibpkg = if binlib then "ghc-%{name}" else "%{name}"
+      baselibpkg = if binlib then ghc_name ++ "-%{name}" else "%{name}"
 
   when hasLibPkg $ do
     when (binlib && hasModules) $ do
@@ -408,7 +424,7 @@
       putHdr "Provides" $ baselibpkg ++ "-static" ++ versionRelease
       putHdr "Provides" $ baselibpkg ++ "-static" ++ isa ++ versionRelease
     put "%if %{defined ghc_version}"
-    putHdr "Requires" "ghc-compiler = %{ghc_version}"
+    putHdr "Requires" $ ghc_name ++ "-compiler = %{ghc_version}"
     put "%endif"
     when hasModules $
       putHdr "Requires" $ baselibpkg ++ isa ++ versionRelease
@@ -425,7 +441,7 @@
       put $ "%package" +-+ subpkgParam Doc
       putHdr "Summary" $ "Haskell" +-+ pkg_name +-+ "library documentation"
       putHdr "BuildArch" "noarch"
-      putHdr "Requires" "ghc-filesystem"
+      putHdr "Requires" $ ghc_name ++ "-filesystem"
       putNewline
       put $ "%description" +-+ subpkgParam Doc
       put $ wrapGenDesc $ "This package provides the Haskell" +-+ pkg_name +-+ "library documentation."
@@ -436,7 +452,7 @@
       put $ "%package" +-+ subpkgParam Prof
       putHdr "Summary" $ "Haskell" +-+ pkg_name +-+ "profiling library"
       putHdr "Requires" $ baselibpkg ++ "-devel" ++ isa ++ versionRelease
-      putHdr "Supplements" $ "(" ++ baselibpkg ++ "-devel and ghc-prof)"
+      putHdr "Supplements" $ "(" ++ baselibpkg ++ "-devel and" +-+ ghc_name ++ "-prof)"
       putNewline
       put $ "%description" +-+ subpkgParam Prof
       put $ wrapGenDesc $ "This package provides the Haskell" +-+ pkg_name +-+ "profiling library."
@@ -469,10 +485,12 @@
   put "%build"
   put "# Begin cabal-rpm build:"
   if standalone then do
-    put "cabal update"
+    global "cabal_install" "%{_bindir}/cabal"
+    put "%cabal_install update"
     put "%if 0%{?rhel} && 0%{?rhel} < 9"
-    put "cabal sandbox init"
-    put "cabal install"
+    put "%cabal_install sandbox init"
+    -- FIXME support mwithghc?
+    put "%cabal_install install"
     put "%endif"
   else do
     when hasSubpkgs $
@@ -487,7 +505,10 @@
   if standalone then do
     put "mkdir -p %{buildroot}%{_bindir}"
     put "%if 0%{?fedora} >= 33 || 0%{?rhel} > 8"
-    put "cabal install --install-method=copy --enable-executable-stripping --installdir=%{buildroot}%{_bindir}"
+    put "%if 0%{?fedora} >= 36"
+    put "%ghc_set_gcc_flags"
+    put "%endif"
+    put $ "%cabal_install install" +-+ maybe "" (\v -> "-w ghc-" ++ V.showVersion v) mwithghc +-+ "--install-method=copy --enable-executable-stripping --installdir=%{buildroot}%{_bindir}"
     put "%else"
     put "for i in .cabal-sandbox/bin/*; do"
     put "strip -s -o %{buildroot}%{_bindir}/$(basename $i) $i"
@@ -607,41 +628,44 @@
   return outputFile
 
 createSpecFile_ :: Bool -> Verbosity -> Flags -> Bool -> Bool -> PackageType
-                -> Maybe (Maybe Stream) -> Maybe PackageVersionSpecifier -> IO ()
-createSpecFile_ ignoreMissing verbose flags testsuite force pkgtype subpkgStream mpvs =
-  void (createSpecFile True True ignoreMissing verbose flags testsuite force pkgtype subpkgStream Nothing mpvs)
+                -> Maybe (Maybe Stream) -> Maybe V.Version
+                -> Maybe PackageVersionSpecifier -> IO ()
+createSpecFile_ ignoreMissing verbose flags testsuite force pkgtype subpkgStream mwithghc mpvs =
+  void (createSpecFile ignoreMissing verbose flags testsuite force pkgtype subpkgStream mwithghc Nothing mpvs)
 
 isBuildable :: Executable -> Bool
 isBuildable exe = buildable $ buildInfo exe
 
-showLicense :: License -> String
-showLicense (GPL Nothing) = "GPL+"
-showLicense (GPL (Just ver)) = "GPLv" ++ showVersion ver ++ "+"
-showLicense (LGPL Nothing) = "LGPLv2+"
-showLicense (LGPL (Just ver)) = "LGPLv" ++ [head $ showVersion ver] ++ "+"
-showLicense BSD3 = "BSD"
-showLicense BSD4 = "BSD"
-showLicense MIT = "MIT"
-showLicense PublicDomain = "Public Domain"
-showLicense AllRightsReserved = "Proprietary"
-showLicense OtherLicense = "Unknown"
-showLicense (UnknownLicense l) = removePrefix "LicenseRef" l  -- FIXME
-#if defined(MIN_VERSION_Cabal) && MIN_VERSION_Cabal(1,16,0)
-showLicense (Apache Nothing) = "ASL ?"
-showLicense (Apache (Just ver)) = "ASL" +-+ showVersion ver
+#if !MIN_VERSION_Cabal(2,2,0)
+prettyShow :: License -> String
+prettyShow (GPL Nothing) = "GPL+"
+prettyShow (GPL (Just ver)) = "GPLv" ++ showVersion ver ++ "+"
+prettyShow (LGPL Nothing) = "LGPLv2+"
+prettyShow (LGPL (Just ver)) = "LGPLv" ++ [head $ showVersion ver] ++ "+"
+prettyShow BSD3 = "BSD"
+prettyShow BSD4 = "BSD"
+prettyShow MIT = "MIT"
+prettyShow PublicDomain = "Public Domain"
+prettyShow AllRightsReserved = "Proprietary"
+prettyShow OtherLicense = "Unknown"
+prettyShow (UnknownLicense l) = removePrefix "LicenseRef" l  -- FIXME
+#if MIN_VERSION_Cabal(1,16,0)
+prettyShow (Apache Nothing) = "ASL ?"
+prettyShow (Apache (Just ver)) = "ASL" +-+ showVersion ver
 #endif
-#if defined(MIN_VERSION_Cabal) && MIN_VERSION_Cabal(1,18,0)
-showLicense (AGPL Nothing) = "AGPLv?"
-showLicense (AGPL (Just ver)) = "AGPLv" ++ showVersion ver
+#if MIN_VERSION_Cabal(1,18,0)
+prettyShow (AGPL Nothing) = "AGPLv?"
+prettyShow (AGPL (Just ver)) = "AGPLv" ++ showVersion ver
 #endif
-#if defined(MIN_VERSION_Cabal) && MIN_VERSION_Cabal(1,20,0)
-showLicense BSD2 = "BSD"
-showLicense (MPL ver) = "MPLv" ++ showVersion ver
+#if MIN_VERSION_Cabal(1,20,0)
+prettyShow BSD2 = "BSD"
+prettyShow (MPL ver) = "MPLv" ++ showVersion ver
 #endif
-#if defined(MIN_VERSION_Cabal) && MIN_VERSION_Cabal(1,22,0)
-showLicense ISC = "ISC"
-showLicense UnspecifiedLicense = "Unspecified license!"
+#if MIN_VERSION_Cabal(1,22,0)
+prettyShow ISC = "ISC"
+prettyShow UnspecifiedLicense = "Unspecified license!"
 #endif
+#endif
 
 sourceUrl :: String -> String
 sourceUrl pv = "https://hackage.haskell.org/package" </> pv </> pv <.> ".tar.gz"
@@ -674,34 +698,28 @@
 getsubpkgMacro mstream mspec pkg = do
   let macro = filter (/= '-') $ display pkg
   pkgid <- latestPackage mstream pkg
-  bringTarball pkgid False mspec
+  bringTarball pkgid mspec
   return (macro, pkgid)
 
 number :: [a] -> [(String,a)]
 number = zip (map show [(1::Int)..])
 
-getPkgName :: Maybe FilePath -> PackageDescription -> Bool -> IO (String, Bool)
-getPkgName (Just spec) pkgDesc binary = do
+getPkgName :: Maybe FilePath -> String -> PackageDescription -> Bool
+           -> IO (String, Bool)
+getPkgName (Just spec) _ pkgDesc binary = do
   let name = display . pkgName $ package pkgDesc
       pkgname = takeBaseName spec
       hasLib = hasLibs pkgDesc
   return $ if name == pkgname || binary then (name, hasLib) else (pkgname, False)
-getPkgName Nothing pkgDesc binary = do
+getPkgName Nothing ghcname pkgDesc binary = do
   let name = display . pkgName $ package pkgDesc
       hasExec = hasExes pkgDesc
       hasLib = hasLibs pkgDesc
-  return $ if binary || hasExec && not hasLib then (name, hasLib) else ("ghc-" ++ name, False)
+  return $ if binary || hasExec && not hasLib then (name, hasLib) else (ghcname ++ "-" ++ name, False)
 
 quoteMacros :: String -> String
 quoteMacros "" = ""
 quoteMacros (c:cs) = (if c == '%' then "%%" else [c]) ++ quoteMacros cs
-
-#if !MIN_VERSION_simple_cmd(0,2,2)
-grep :: String -> FilePath -> IO [String]
-grep pat file = do
-  mres <- cmdMaybe "grep" [pat, file]
-  return $ maybe [] lines mres
-#endif
 
 streamSubpackage :: Maybe Stream -> Maybe (Maybe Stream) -> Maybe Stream
 streamSubpackage _ (Just (Just stream)) = Just stream
diff --git a/src/Commands/Update.hs b/src/Commands/Update.hs
--- a/src/Commands/Update.hs
+++ b/src/Commands/Update.hs
@@ -29,16 +29,8 @@
 import SimpleCabal (customFieldsPD, package,
                     PackageIdentifier (..), showVersion)
 import SimpleCmd
-#if MIN_VERSION_simple_cmd(0,2,1)
-  hiding (ifM,whenM)
-#endif
-import SimpleCmd.Git (grepGitConfig, rwGitDir,
-#if MIN_VERSION_simple_cmd(0,2,2)
-                      gitBool
-#endif
-                     )
-#if (defined(MIN_VERSION_base) && MIN_VERSION_base(4,8,0))
-#else
+import SimpleCmd.Git (gitBool, grepGitConfig, rwGitDir)
+#if !MIN_VERSION_base(4,8,0)
 import Control.Applicative ((<$>))
 #endif
 import Control.Monad.Extra
@@ -54,7 +46,7 @@
 -- FIXME check kerberos before new-sources
 update :: Maybe PackageVersionSpecifier -> IO ()
 update mpvs = do
-  pkgdata <- pkgSpecPkgData [] (pvsPackage =<< mpvs) True True
+  pkgdata <- pkgSpecPkgData [] (pvsPackage =<< mpvs)
   case specFilename pkgdata of
     Nothing -> error' "No (unique) .spec file in directory."
     Just spec -> do
@@ -129,7 +121,7 @@
             when (rwGit && subpkg) $ do
               cmd_ "cp" ["-p", "sources", "sources.cblrpm"]
               cmd_ "sed" ["-i", "/" ++ display oldPkgId <.> "tar.gz" ++ "/d", "sources.cblrpm"]
-            bringTarball newPkgId False (Just spec)
+            bringTarball newPkgId (Just spec)
           distgit <- grepGitConfig "\\(pkgs\\|src\\)."
           when (rwGit && distgit) $ do
             when updated $ do
@@ -161,16 +153,7 @@
       direxists <- doesDirectoryExist dir
       when direxists $ removeDirectoryRecursive dir
       createDirectoryIfMissing True dir
-      createSpecFile True revise False silent [] False False (SpecFile spec) subpkgStream (Just dir) (streamPkgToPVS Nothing (Just pkgid))
-
-#if !MIN_VERSION_simple_cmd(0,2,2)
--- | @gitBool c args@ runs git command and return result
-gitBool :: String -- ^ git command
-        -> [String] -- ^ arguments
-        -> IO Bool -- ^ result
-gitBool c args =
-  cmdBool "git" (c:args)
-#endif
+      createSpecFile False silent [] False False (SpecFile spec) subpkgStream Nothing (Just dir) (streamPkgToPVS Nothing (Just pkgid))
 
 krbTicket :: IO ()
 krbTicket = do
diff --git a/src/Dependencies.hs b/src/Dependencies.hs
--- a/src/Dependencies.hs
+++ b/src/Dependencies.hs
@@ -253,7 +253,7 @@
 
 pkgInstallMissing :: Flags -> Maybe PackageVersionSpecifier -> IO [PackageName]
 pkgInstallMissing flags mpvs = do
-  pkgdata <- prepare flags mpvs True False
+  pkgdata <- prepare flags mpvs
   pkgInstallMissing' pkgdata
 
 pkgInstallMissing' :: PackageData -> IO [PackageName]
@@ -310,7 +310,7 @@
   where
     missingDepsPkg :: PackageName -> IO [RpmPackage]
     missingDepsPkg pkg = do
-      pkgdata <- prepare flags (streamPkgToPVS mstream (Just (unversionedPkgId pkg))) False False
+      pkgdata <- prepare flags (streamPkgToPVS mstream (Just (unversionedPkgId pkg)))
       missingPackages (packageDesc pkgdata) >>= filterM notAvail
 
     putMissing :: [RpmPackage] -> IO ()
@@ -331,7 +331,7 @@
 
 packageDeps :: Flags -> Maybe Stream -> PackageName -> IO [PackageName]
 packageDeps flags mstream pkg = do
-  pkgdata <- prepare flags (streamPkgToPVS mstream (Just (unversionedPkgId pkg))) False False
+  pkgdata <- prepare flags (streamPkgToPVS mstream (Just (unversionedPkgId pkg)))
   let pkgDesc = packageDesc pkgdata
       (deps, setup, _, _, _) = dependencies pkgDesc
   return $ nub $ (deps ++ setup) \\ [pkg]
diff --git a/src/FileUtils.hs b/src/FileUtils.hs
--- a/src/FileUtils.hs
+++ b/src/FileUtils.hs
@@ -26,8 +26,7 @@
   withCurrentDirectory,
   withTempDirectory) where
 
-#if (defined(MIN_VERSION_base) && MIN_VERSION_base(4,8,0))
-#else
+#if !MIN_VERSION_base(4,8,0)
 import Control.Applicative ((<$>))
 #endif
 import Control.Exception (bracket)
@@ -35,13 +34,15 @@
 import Data.List
 import Data.Maybe (isJust)
 import SimpleCmd
-import System.Directory (getCurrentDirectory, listDirectory,
-                         setCurrentDirectory, removeDirectoryRecursive,
-#if (defined(MIN_VERSION_directory) && MIN_VERSION_directory(1,2,3))
+import System.Directory (listDirectory,
+                         removeDirectoryRecursive,
+#if MIN_VERSION_directory(1,2,3)
                          withCurrentDirectory
 #endif
                          )
+#if !MIN_VERSION_simple_cmd(0,2,4) || !MIN_VERSION_filepath(1,4,2)
 import System.FilePath
+#endif
 import System.Posix.Files (fileSize, getFileStatus)
 
 #if !MIN_VERSION_simple_cmd(0,2,4)
@@ -67,24 +68,18 @@
 mktempdir :: IO FilePath
 mktempdir = cmd "mktemp" ["-d", "--tmpdir", "cblrpm.XXXXXXXXXX"]
 
-withTempDirectory :: (FilePath -> IO a) -> IO a
+withTempDirectory :: IO a -> IO a
 withTempDirectory run = bracket
                         mktempdir
                         removeDirectoryRecursive
-                        (\ tmpdir -> do
-                            cwd <- getCurrentDirectory
-                            setCurrentDirectory tmpdir
-                            res <- run cwd
-                            setCurrentDirectory cwd
-                            return res)
+                        (`withCurrentDirectory` run)
 
 -- listDirectory without hidden files
 listDirectory' :: FilePath -> IO [FilePath]
 listDirectory' dir =
   filter (not . isPrefixOf ".") <$> listDirectory dir
 
-#if (defined(MIN_VERSION_directory) && MIN_VERSION_directory(1,2,3))
-#else
+#if !MIN_VERSION_directory(1,2,3)
 withCurrentDirectory :: FilePath -> IO a -> IO a
 withCurrentDirectory dir action =
   bracket getCurrentDirectory setCurrentDirectory $ \ _ -> do
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -18,15 +18,14 @@
 
 module Main where
 
-#if (defined(MIN_VERSION_base) && MIN_VERSION_base(4,13,0))
-#else
+#if !MIN_VERSION_base(4,13,0)
 import Control.Applicative ((<|>)
-#if (defined(MIN_VERSION_base) && MIN_VERSION_base(4,8,0))
-#else
+#if !MIN_VERSION_base(4,8,0)
                          , (<$>), (<*>)
 #endif
                            )
 #endif
+import Data.Version.Extra (readVersion)
 import Distribution.Text (simpleParse)
 import Distribution.Verbosity (normal, silent)
 #if !MIN_VERSION_simple_cmd_args(0,1,7)
@@ -45,7 +44,7 @@
 
 import PackageUtils (RpmStage (..))
 import Paths_cabal_rpm (version)
-import Types
+import Types hiding (readVersion)
 
 import SimpleCabal (PackageIdentifier(..))
 import SimpleCmdArgs
@@ -57,33 +56,81 @@
     "RPM package tool for Haskell Stackage/Hackage packages" $
     subcommands
     [ Subcommand "spec" "Generate a spec file" $
-      createSpecFile_ <$> ignoreMissing <*> quietOpt <*> flags <*> testsuite <*> force <*> pkgtype <*> fmap toSubpkgStream subpackage <*> pkgVerSpecifier
+      createSpecFile_
+      <$> ignoreMissing
+      <*> quietOpt
+      <*> flags
+      <*> testsuite
+      <*> force
+      <*> pkgtype
+      <*> fmap toSubpkgStream subpackage
+      <*> optional (readVersion <$> strOptionWith 'w' "with-ghc" "VERSION" "ghc compiler version")
+      <*> pkgVerSpecifier
     , Subcommand "srpm" "Generate an srpm" $
-      rpmBuild_ Source <$> verboseRpmbuild <*> flags <*> pkgtype <*> subpackage <*> pkgVerSpecifier
+      rpmBuild_ Source
+      <$> verboseRpmbuild
+      <*> flags
+      <*> pkgtype
+      <*> subpackage
+      <*> pkgVerSpecifier
     , Subcommand "prep" "Unpack source" $
-      rpmBuild_ Prep <$> verboseRpmbuild <*> flags <*> pkgtype <*> subpackage <*> pkgVerSpecifier
+      rpmBuild_ Prep
+      <$> verboseRpmbuild
+      <*> flags
+      <*> pkgtype
+      <*> subpackage
+      <*> pkgVerSpecifier
     , Subcommand "local" "Build rpm package locally" $
-      rpmBuild_ Binary <$> quietRpmbuild <*> flags <*> pkgtype <*> subpackage <*> pkgVerSpecifier
+      rpmBuild_ Binary
+      <$> quietRpmbuild
+      <*> flags
+      <*> pkgtype
+      <*> subpackage
+      <*> pkgVerSpecifier
     , Subcommand "build" "Alias for 'local' - builds rpm locally" $
-      rpmBuild_ Binary <$> quietRpmbuild <*> flags <*> pkgtype <*> subpackage <*> pkgVerSpecifier
+      rpmBuild_ Binary
+      <$> quietRpmbuild
+      <*> flags
+      <*> pkgtype
+      <*> subpackage
+      <*> pkgVerSpecifier
     , Subcommand "builddep" "Install build dependencies with dnf" $
-      builddep <$> flags <*> pkgVerSpecifier
+      builddep
+      <$> flags
+      <*> pkgVerSpecifier
     , Subcommand "install" "Build and install recursively" $
-      install <$> flags <*> pkgtype <*> subpackage <*> pkgVerSpecifier
+      install
+      <$> flags
+      <*> pkgtype
+      <*> subpackage
+      <*> pkgVerSpecifier
     -- should be (optional versionArg) not pkgid
     , Subcommand "diff" "Diff with pristine generated spec file" $
-      diff <$> flags <*> pkgtype <*> pkgVerSpecifier
+      diff
+      <$> flags
+      <*> pkgtype
+      <*> pkgVerSpecifier
     , Subcommand "depends" "List Haskell dependencies" $
-      depends Depends <$> flags <*> pkgVerSpecifier
+      depends Depends
+      <$> flags
+      <*> pkgVerSpecifier
     , Subcommand "requires" "List buildrequires for package" $
-      depends Requires <$> flags <*> pkgVerSpecifier
+      depends Requires
+      <$> flags
+      <*> pkgVerSpecifier
     , Subcommand "missingdeps" "List dependencies not available" $
-      depends Missing <$> flags <*> pkgVerSpecifier
+      depends Missing
+      <$> flags
+      <*> pkgVerSpecifier
     -- should be just Maybe PackageName
     , Subcommand "refresh" "Refresh spec file to latest packaging" $
-      refresh <$> dryrun <*> pkgtype <*> pkgVerSpecifier
+      refresh
+      <$> dryrun
+      <*> pkgtype
+      <*> pkgVerSpecifier
     , Subcommand "update" "Update package to latest version" $
-      update <$> pkgVerSpecifier
+      update
+      <$> pkgVerSpecifier
     ]
   where
     pkgId :: Parser (Maybe PackageIdentifier)
diff --git a/src/PackageUtils.hs b/src/PackageUtils.hs
--- a/src/PackageUtils.hs
+++ b/src/PackageUtils.hs
@@ -36,24 +36,16 @@
   ) where
 
 import FileUtils (assertFileNonEmpty, filesWithExtension, fileWithExtension,
-                  listDirectory', mktempdir,
-                  withTempDirectory)
+                  listDirectory', withTempDirectory)
 import SimpleCabal (finalPackageDescription, licenseFiles, mkPackageName,
                     PackageDescription, PackageIdentifier(..), PackageName,
                     tryFindPackageDesc)
 import SimpleCmd (cmd, cmd_, cmdBool, cmdIgnoreErr, cmdLines,
-#if MIN_VERSION_simple_cmd(0,2,2)
-                  cmdStderrToStdout,
-#else
-                  cmdSilent,
-#endif
-                  error', grep_, removePrefix, sudo, sudo_, (+-+))
+                  cmdStderrToStdoutIn,
+                  error', grep_, removePrefix, shell_, sudo, sudo_, (+-+))
 import SimpleCmd.Git (isGitDir, grepGitConfig)
 import SimpleCmd.Rpm (rpmspec)
 import SysCmd (optionalProgram, requireProgram, rpmEval)
-#if MIN_VERSION_simple_cmd(0,2,2)
-import System.Exit (ExitCode (..))
-#endif
 import Stackage (defaultLTS, latestStackage)
 import Types
 
@@ -103,8 +95,8 @@
         likely names name = any (`isPrefixOf` lower name) names
         unlikely name = not $ any (`isSuffixOf` name) ["~", ".cabal"]
 
-bringTarball :: PackageIdentifier -> Bool -> Maybe FilePath -> IO ()
-bringTarball pkgid revise mspec = do
+bringTarball :: PackageIdentifier -> Maybe FilePath -> IO ()
+bringTarball pkgid mspec = do
   let tarfile = display pkgid <.> "tar.gz"
   havespec <- case mspec of
                 Nothing -> return False
@@ -124,7 +116,7 @@
       createDirectoryIfMissing True srcdir
     mapM_ (copyTarball False srcdir) sources
     haveLocalCabal <- doesFileExist $ srcdir </> display pkgid <.> "cabal"
-    when (not haveLocalCabal && revise) $
+    unless haveLocalCabal $
       void $ getRevisedCabal pkgid
     allExist' <- and <$> mapM (doesFileExist . (srcdir </>)) sources
     when (not allExist' && havespec) $
@@ -180,17 +172,14 @@
       else fromJust <$> rpmEval "%{_sourcedir}"
 
 getBuildDir :: IO FilePath
-getBuildDir = do
-    git <- isGitDir "."
-    if git
-      then getCurrentDirectory
-      else fromJust <$> rpmEval "%{_builddir}"
+getBuildDir =
+  fromJust <$> rpmEval "%{_builddir}"
 
 getRevisedCabal :: PackageIdentifier -> IO Bool
 getRevisedCabal pkgid = do
   let file = display (pkgName pkgid) <.> "cabal"
   dir <- getSourceDir
-  withTempDirectory $ \ _ -> do
+  withTempDirectory $ do
     -- FIXME use cabal-file
     dl <- cmdBool "wget" ["--quiet", "https://hackage.haskell.org/package" </> display pkgid </> file]
     if not dl
@@ -219,20 +208,18 @@
   cwd <- getCurrentDirectory
   gitDir <- isGitDir "."
   let rpmdirs_override =
-        [ "--define="++ mcr +-+ cwd | gitDir,
-          mcr <- ["_builddir", "_rpmdir", "_srcrpmdir", "_sourcedir"]]
+        [ "--define="++ mcr +-+ cwd | gitDir, mcr <- ["_sourcedir"]]
   let args = ["-b" ++ rpmCmd] ++ ["--nodeps" | mode == Prep] ++
              rpmdirs_override ++ [spec]
   if not quiet then
     cmd_ "rpmbuild" args
     else do
     putStr $ "rpmbuild" +-+ show mode ++ ": "
-#if MIN_VERSION_simple_cmd(0,2,2)
     -- may hang for build
-    (ret, out) <- cmdStderrToStdout "rpmbuild" args
-    case ret of
-      ExitSuccess -> putStrLn "done"
-      ExitFailure _ -> error' $ "\n" ++ dropToPrefix "+ /usr/bin/chmod -Rf" out
+    (ok, out) <- cmdStderrToStdoutIn "rpmbuild" args ""
+    if ok
+    then putStrLn "done"
+    else error' $ "\n" ++ dropToPrefix "+ /usr/bin/chmod -Rf" out
   where
     dropToPrefix :: String -> String -> String
     dropToPrefix _ "" = ""
@@ -240,10 +227,6 @@
       let ls = lines cs
           rest = dropWhile (not . (prefix `isPrefixOf`)) ls
       in unlines (if null rest then tail ls else tail rest)
-#else
-    cmdSilent "rpmbuild" args
-    putStrLn "done"
-#endif
 
 cabalUpdate :: IO ()
 cabalUpdate = do
@@ -281,30 +264,22 @@
   cmd_ "cabal" (c:args)
 
 
-tryUnpack :: PackageIdentifier -> Bool -> Bool
-          -> IO (FilePath, Maybe FilePath) -- (cabalfile, mtmpdir)
-tryUnpack pkgid revise keep = do
-  let dir = display pkgid
+tryUnpack :: PackageIdentifier -> IO FilePath
+tryUnpack pkgid = do
+  builddir <- getBuildDir
+  let dir = builddir </> display pkgid
   isdir <- doesDirectoryExist dir
   if isdir
     then do
     mcabal <- withCurrentDirectory dir $ checkForCabalFile (Just (pkgName pkgid))
-    if isJust mcabal then do
-      pth <- tryFindPackageDesc dir
-      return (pth, Nothing)
-      else
-      error $ "could not find" +-+ display (pkgName pkgid) <.> "cabal"
+    if isJust mcabal
+      then tryFindPackageDesc dir
+      else error $ "could not find" +-+ display (pkgName pkgid) <.> "cabal"
     else do
-    cwd <- getCurrentDirectory
-    mtmpdir <- if keep then return Nothing
-      else do
-      tmpdir <- mktempdir
-      setCurrentDirectory tmpdir
-      return $ Just tmpdir
-    cabal_ "unpack" $ ["-v0"] ++ ["--pristine" | not revise] ++ [display pkgid]
-    pth <- tryFindPackageDesc dir
-    setCurrentDirectory cwd
-    return (fromMaybe "" mtmpdir </> pth, mtmpdir)
+    createDirectoryIfMissing True builddir
+    withCurrentDirectory builddir $ do
+      cabal_ "unpack" ["-v0", display pkgid]
+      tryFindPackageDesc dir
 
 latestPackage :: Maybe Stream -> PackageName -> IO PackageIdentifier
 latestPackage (Just Hackage) pkg = latestHackage pkg
@@ -336,7 +311,7 @@
 checkForSpecFile mpkg = do
   allSpecs <- filesWithExtension "." ".spec"
   -- emacs makes ".#*.spec" tmp files
-  let predicate = maybe ((/= '.') . head) (\ pkg -> (`elem` [pkg <.> "spec", "ghc-" ++ pkg <.> "spec"])) (display <$> mpkg)
+  let predicate = maybe ((/= '.') . head) ((\ pkg -> (`elem` [pkg <.> "spec", "ghc-" ++ pkg <.> "spec"])) . display) mpkg
       specs = filter predicate allSpecs
   when (specs /= allSpecs && isNothing mpkg) $
     putStrLn "Warning: dir contains a hidden spec file"
@@ -348,7 +323,7 @@
 checkForCabalFile :: Maybe PackageName -> IO (Maybe FilePath)
 checkForCabalFile mpkg = do
   allCabals <- filesWithExtension "." ".cabal"
-  let predicate = maybe (const True) (\ pkg -> (== pkg <.> "cabal")) (display <$> mpkg)
+  let predicate = maybe (const True) ((\ pkg -> (== pkg <.> "cabal")) . display) mpkg
       cabals = filter predicate allCabals
   case cabals of
     [one] -> return $ Just one
@@ -368,8 +343,8 @@
       then fileWithExtension (display pkgid) ".cabal"
       else return Nothing
 
-pkgSpecPkgData :: Flags -> Maybe PackageName -> Bool -> Bool -> IO PackageData
-pkgSpecPkgData flags mpkg revise keep = do
+pkgSpecPkgData :: Flags -> Maybe PackageName -> IO PackageData
+pkgSpecPkgData flags mpkg = do
   mspec <- checkForSpecFile mpkg
   case mspec of
     Just spec -> specPackageData spec
@@ -381,12 +356,12 @@
           return $ PackageData Nothing docs licenses pkgDesc
         Nothing ->
           case mpkg of
-            Just pkg -> prepStreamPkg flags Nothing defaultLTS pkg revise keep
+            Just pkg -> prepStreamPkg flags Nothing defaultLTS pkg
             Nothing -> do
               cwd <- getCurrentDirectory
               case simpleParse (takeFileName cwd) of
                 Just pdir ->
-                  prepare flags (streamPkgToPVS Nothing (Just pdir)) revise keep
+                  prepare flags (streamPkgToPVS Nothing (Just pdir))
                 Nothing -> error' "package not found for directory"
   where
     specPackageData :: FilePath -> IO PackageData
@@ -398,10 +373,14 @@
       where
         cabalFromSpec :: FilePath -> IO FilePath
         cabalFromSpec specFile = do
-          namever <- removePrefix "ghc-" . head <$> rpmspec ["--srpm"] (Just "%{name}-%{version}") specFile
+          -- FIXME handle ghcX.Y
+          havePkgname <- grep_ "%{pkg_name}" specFile
+          -- handle bin packages starting with ghc, like "ghc-tags"
+          namever <- (if havePkgname then removePrefix "ghc-" else id) . head
+            <$> rpmspec ["--srpm"] (Just "%{name}-%{version}") specFile
           case simpleParse namever of
             Nothing -> error "pkgid could not be parsed"
-            Just pkgid -> bringTarball pkgid revise (Just specFile)
+            Just pkgid -> bringTarball pkgid (Just specFile)
           builddir <- getBuildDir
           let pkgsrcdir = builddir </> namever
           dExists <- doesDirectoryExist pkgsrcdir
@@ -431,33 +410,31 @@
               , packageDesc :: PackageDescription
               }
 
-prepPkgId :: Flags -> Maybe FilePath -> PackageIdentifier -> Bool -> Bool
-          -> IO PackageData
-prepPkgId flags mspec pkgid revise keep = do
-  (cabalfile, mtmp) <- tryUnpack pkgid revise keep
+prepPkgId :: Flags -> Maybe FilePath -> PackageIdentifier -> IO PackageData
+prepPkgId flags mspec pkgid = do
+  void $ getRevisedCabal pkgid
+  cabalfile <- tryUnpack pkgid
   (pkgDesc, docs, licenses) <- simplePackageDescription flags cabalfile
-  unless keep $ maybe (return ()) removeDirectoryRecursive mtmp
   return $ PackageData mspec docs licenses pkgDesc
 
-prepStreamPkg :: Flags -> Maybe FilePath -> Stream -> PackageName -> Bool -> Bool
+prepStreamPkg :: Flags -> Maybe FilePath -> Stream -> PackageName
               -> IO PackageData
-prepStreamPkg flags mspec stream pkg revise keep = do
+prepStreamPkg flags mspec stream pkg = do
   pkgid <- latestPackage (Just stream) pkg
   mcabal <- checkForPkgCabalFile pkgid
   case mcabal of
     Just cabalfile -> do
       (pkgDesc, docs, licenses) <- simplePackageDescription flags cabalfile
       return $ PackageData mspec docs licenses pkgDesc
-    Nothing -> prepPkgId flags mspec pkgid revise keep
+    Nothing -> prepPkgId flags mspec pkgid
 
 -- Nothing means package in cwd
-prepare :: Flags -> Maybe PackageVersionSpecifier -> Bool -> Bool
-        -> IO PackageData
-prepare flags Nothing revise keep = pkgSpecPkgData flags Nothing revise keep
+prepare :: Flags -> Maybe PackageVersionSpecifier -> IO PackageData
+prepare flags Nothing = pkgSpecPkgData flags Nothing
 -- Something implies either new packaging or some existing spec file in dir
-prepare flags (Just pvs) revise keep =
+prepare flags (Just pvs) =
   case pvs of
-    PVPackageName pkg -> pkgSpecPkgData flags (Just pkg) revise keep
+    PVPackageName pkg -> pkgSpecPkgData flags (Just pkg)
     PVPackageId pkgid -> do
       mspec <- checkForSpecFile $ Just (pkgName pkgid)
       mcabal <- checkForPkgCabalFile pkgid
@@ -465,7 +442,7 @@
         Just cabalfile -> do
           (pkgDesc, docs, licenses) <- simplePackageDescription flags cabalfile
           return $ PackageData mspec docs licenses pkgDesc
-        Nothing -> prepPkgId flags mspec pkgid revise keep
+        Nothing -> prepPkgId flags mspec pkgid
     PVStreamPackage stream Nothing -> do
       mspec <- checkForSpecFile Nothing
       case mspec of
@@ -474,24 +451,27 @@
           let trydir = simpleParse (takeFileName cwd)
           case trydir of
             Just pdir | pkgVersion pdir == nullVersion ->
-                          prepare flags (streamPkgToPVS (Just stream) trydir) revise keep
+                          prepare flags (streamPkgToPVS (Just stream) trydir)
             _ -> error' "package not found"
         Just spec -> do
           let pkg = mkPackageName $ removePrefix "ghc-" $ takeBaseName spec
-          prepStreamPkg flags (Just spec) stream pkg revise keep
+          prepStreamPkg flags (Just spec) stream pkg
     PVStreamPackage stream (Just pkg) -> do
       mspec <- checkForSpecFile (Just pkg)
-      prepStreamPkg flags mspec stream pkg revise keep
+      prepStreamPkg flags mspec stream pkg
 
 -- redundant mdir was earlier for update
 patchSpec :: Bool -> Maybe FilePath -> FilePath -> FilePath -> IO ()
 patchSpec dryrun mdir oldspec newspec = do
   diff <- cmdIgnoreErr "diff" ["-u2", "-I", "- spec file generated by cabal-rpm", "-I", "Fedora Haskell SIG <haskell@lists.fedoraproject.org>", oldspec, newspec] "" >>= cmdIgnoreErr "sed" ["-e", "s%.Cblrpm/%%", "-e", "s/.cblrpm//"] . dropChangelog
-  putStrLn diff
-  unless dryrun $ do
-    putStrLn ""
-    out <- cmdIgnoreErr "patch" opts diff
-    putStrLn out
+  unless (null diff) $ do
+    putStrLn diff
+    unless dryrun $ do
+      putStrLn ""
+      (ok,out) <- cmdStderrToStdoutIn "patch" opts (diff ++ "\n")
+      putStrLn out
+      unless ok $
+        shell_ "echo *.rej; cat *.rej"
   where
     opts = ["--fuzz=1"] ++ ["-p" ++ show n | let n = count '/' (removePrefix ".Cblrpm/" newspec)] ++ maybe [] (\ d -> ["-d", d]) mdir
 
diff --git a/src/Stackage.hs b/src/Stackage.hs
--- a/src/Stackage.hs
+++ b/src/Stackage.hs
@@ -24,8 +24,7 @@
 
 #ifdef CURL
 import Network.Curl
-#if (defined(MIN_VERSION_base) && MIN_VERSION_base(4,8,0))
-#else
+#if !MIN_VERSION_base(4,8,0)
 import Control.Applicative ((<$>))
 #endif
 #else
@@ -41,10 +40,10 @@
 import Types
 
 defaultLTS :: Stream
-defaultLTS = LTS 18
+defaultLTS = LTS 20
 
 latestLTS :: Stream
-latestLTS = LTS 18
+latestLTS = LTS 20
 
 stackageList :: Stream -> PackageName -> IO (Maybe PackageIdentifier)
 stackageList stream pkg = do
diff --git a/src/SysCmd.hs b/src/SysCmd.hs
--- a/src/SysCmd.hs
+++ b/src/SysCmd.hs
@@ -22,8 +22,7 @@
   rpmEval
   ) where
 
-#if (defined(MIN_VERSION_base) && MIN_VERSION_base(4,8,0))
-#else
+#if !MIN_VERSION_base(4,8,0)
 import Control.Applicative ((<$>))
 #endif
 import Control.Monad
diff --git a/src/Types.hs b/src/Types.hs
--- a/src/Types.hs
+++ b/src/Types.hs
@@ -34,13 +34,12 @@
 import Data.Char (isDigit {--, toLower--})
 import Data.List
 import Data.Maybe (fromMaybe)
-#if (defined(MIN_VERSION_base) && MIN_VERSION_base(4,11,0))
-#else
+#if !MIN_VERSION_base(4,11,0)
 import Data.Semigroup ((<>))
 #endif
 import Distribution.Text (display)
 import Distribution.Version (
-#if (defined(MIN_VERSION_Cabal) && MIN_VERSION_Cabal(2,0,0))
+#if MIN_VERSION_Cabal(2,0,0)
                      Version,
                      mkVersion,
                      nullVersion
@@ -128,8 +127,7 @@
 unversionedPkgId :: PackageName -> PackageIdentifier
 unversionedPkgId pn = PackageIdentifier pn nullVersion
 
-#if (defined(MIN_VERSION_Cabal) && MIN_VERSION_Cabal(2,0,0))
-#else
+#if !MIN_VERSION_Cabal(2,0,0)
 mkVersion :: [Int] -> Version
 mkVersion is = Version is []
 
