diff --git a/shake-ext.cabal b/shake-ext.cabal
--- a/shake-ext.cabal
+++ b/shake-ext.cabal
@@ -1,6 +1,6 @@
 cabal-version: 1.18
 name: shake-ext
-version: 2.11.0.1
+version: 2.11.0.2
 license: BSD3
 license-file: LICENSE
 copyright: Copyright: (c) 2018 Vanessa McHale
@@ -41,11 +41,13 @@
     other-modules:
         Development.Shake.TH
     default-language: Haskell2010
+    other-extensions: GeneralizedNewtypeDeriving PatternSynonyms
+                      TypeFamilies DeriveAnyClass DeriveGeneric
     ghc-options: -Wall
     build-depends:
-        base >=4.11 && <5,
+        base >=4.9 && <5,
         Cabal >=2.2,
-        cdeps,
+        cdeps -any,
         composition-prelude -any,
         cpphs -any,
         directory -any,
diff --git a/src/Development/Shake/C.hs b/src/Development/Shake/C.hs
--- a/src/Development/Shake/C.hs
+++ b/src/Development/Shake/C.hs
@@ -1,10 +1,15 @@
-{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE DeriveAnyClass             #-}
+{-# LANGUAGE DeriveGeneric              #-}
+{-# LANGUAGE DerivingStrategies         #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE PatternSynonyms            #-}
+{-# LANGUAGE TypeFamilies               #-}
 
 -- | This module provides functions for easy C builds of binaries, static
 -- libraries, and dynamic libraries.
 module Development.Shake.C ( -- * Types
                              CConfig (..)
-                           , CCompiler (GCC, Clang, GHC, Other, GCCStd, GHCStd, CompCert)
+                           , CCompiler (ICC, GCC, Clang, GHC, Other, GCCStd, GHCStd, CompCert)
                            -- * Rules
                            , staticLibR
                            , sharedLibR
@@ -18,6 +23,11 @@
                            , staticLibA
                            , sharedLibA
                            , stripA
+                           -- * Oracle helpers
+                           , queryCC
+                           , queryCfg
+                           , examineCC
+                           , examineCfg
                            -- * Reëxports from "Language.C.Dependency"
                            , getCDepends
                            -- * Helper functions
@@ -30,7 +40,9 @@
 import           Control.Monad
 import           Data.List                  (isPrefixOf, isSuffixOf)
 import           Development.Shake
+import           Development.Shake.Classes
 import           Development.Shake.FilePath
+import           GHC.Generics               (Generic)
 import           Language.C.Dependency
 import           System.Info
 
@@ -39,7 +51,7 @@
 pkgConfig pkg = do
     (Stdout o) <- command [] "pkg-config" ["--cflags", pkg]
     (Stdout o') <- command [] "pkg-config" ["--libs", pkg]
-    pure (words o <> words o')
+    pure (words o ++ words o')
 
 mkQualified :: Monoid a => Maybe a -> Maybe a -> a -> a
 mkQualified pre suff = h [f suff, g pre]
@@ -63,6 +75,7 @@
 
 -- | Get the executable name for a 'CCompiler'
 ccToString :: CCompiler -> String
+ccToString ICC            = "icc"
 ccToString Clang          = "clang"
 ccToString (Other s)      = s
 ccToString (GCC pre)      = mkQualified pre Nothing "gcc"
@@ -82,6 +95,7 @@
 -- | Attempt to parse a string as a 'CCompiler', defaulting to @cc@ if parsing
 -- fails.
 ccFromString :: String -> CCompiler
+ccFromString "icc" = ICC
 ccFromString "gcc" = GCC Nothing
 ccFromString "ccomp" = CompCert
 ccFromString "clang" = Clang
@@ -102,11 +116,12 @@
                      , _postfix :: Maybe String -- ^ The compiler version
                      }
                | CompCert
+               | ICC
                | Other String
-               deriving (Eq)
+               deriving (Show, Eq, Generic, Typeable, Hashable, Binary, NFData)
 
 mapFlags :: String -> ([String] -> [String])
-mapFlags s = fmap (s <>)
+mapFlags s = fmap (s ++)
 
 data CConfig = CConfig { includes   :: [String] -- ^ Directories to be included.
                        , libraries  :: [String] -- ^ Libraries against which to link.
@@ -114,7 +129,33 @@
                        , extras     :: [String] -- ^ Extra flags to be passed to the compiler
                        , staticLink :: Bool -- ^ Whether to link against static versions of libraries
                        }
+             deriving (Show, Eq, Generic, Typeable, Hashable, Binary, NFData)
 
+newtype CC = CC ()
+    deriving (Show, Eq)
+    deriving newtype (Typeable, Hashable, Binary, NFData)
+
+newtype Cfg = Cfg ()
+    deriving (Show, Eq)
+    deriving newtype (Typeable, Hashable, Binary, NFData)
+
+type instance RuleResult CC = CCompiler
+type instance RuleResult Cfg = CConfig
+
+-- | Set a 'CCompiler' that can be depended on later.
+examineCC :: CCompiler -> Rules ()
+examineCC cc = void $ addOracle $ \(CC _) -> pure cc
+
+examineCfg :: CConfig -> Rules ()
+examineCfg cfg = void $ addOracle $ \(Cfg _) -> pure cfg
+
+-- | Depend on the C compiler being used.
+queryCC :: Action ()
+queryCC = void $ askOracle (CC ())
+
+queryCfg :: Action ()
+queryCfg =void $ askOracle (Cfg ())
+
 -- | Rules for making a static library from C source files. Unlike 'staticLibR',
 -- this also creates rules for creating object files.
 cToLib :: CCompiler
@@ -153,14 +194,14 @@
         -> Action r
 binaryA cc sources out cfg =
     need sources >>
-    (command [EchoStderr False] (ccToString cc) . (("-o" : out : sources) <>) . cconfigToArgs) cfg
+    (command [EchoStderr False] (ccToString cc) . (("-o" : out : sources) ++) . cconfigToArgs) cfg
 
 -- | Generate compiler flags for a given configuration.
 cconfigToArgs :: CConfig -> [String]
 cconfigToArgs (CConfig is ls ds es sl) = join [ mapFlags "-I" is, mapFlags "-l" (g sl <$> ls), mapFlags "-L" ds, es ]
     where g :: Bool -> (String -> String)
           g False = id
-          g True  = (":lib" <>) . (<> ".a")
+          g True  = (":lib" ++) . (++ ".a")
 
 -- | These rules build a dynamic library (@.so@ on Linux).
 dynLibR :: CCompiler
@@ -171,7 +212,7 @@
 dynLibR cc objFiles shLib cfg =
     shLib %> \out ->
         need objFiles >>
-        command [EchoStderr False] (ccToString cc) ("-shared" : "-o" : out : objFiles <> cconfigToArgs cfg)
+        command [EchoStderr False] (ccToString cc) ("-shared" : "-o" : out : objFiles ++ cconfigToArgs cfg)
 
 -- | These rules build an object file from a C source file.
 objectFileR :: CCompiler
diff --git a/src/Development/Shake/CCJS.hs b/src/Development/Shake/CCJS.hs
--- a/src/Development/Shake/CCJS.hs
+++ b/src/Development/Shake/CCJS.hs
@@ -11,6 +11,6 @@
 ccjs sources fp =
     fp %> \out -> do
         need sources
-        (Stdout sout) <- command mempty "ccjs" (sources <> ["--externs=node"])
+        (Stdout sout) <- command mempty "ccjs" (sources ++ ["--externs=node"])
         liftIO $ createDirectoryIfMissing True (takeDirectory out)
         liftIO $ writeFile out sout
diff --git a/src/Development/Shake/Cabal.hs b/src/Development/Shake/Cabal.hs
--- a/src/Development/Shake/Cabal.hs
+++ b/src/Development/Shake/Cabal.hs
@@ -36,9 +36,9 @@
 
 hsCompiler :: HsCompiler -> String
 hsCompiler (GHC Nothing)    = "ghc"
-hsCompiler (GHC (Just v))   = "ghc-" <> v
+hsCompiler (GHC (Just v))   = "ghc-" ++ v
 hsCompiler (GHCJS Nothing)  = "ghcjs"
-hsCompiler (GHCJS (Just v)) = "ghcjs-" <> v
+hsCompiler (GHCJS (Just v)) = "ghcjs-" ++ v
 
 -- | E.g. @x86_64-linux@
 platform :: String
@@ -47,7 +47,7 @@
 libraryToFiles :: Library -> [FilePath]
 libraryToFiles lib = mconcat [cs, is, hs]
     where (cs, is) = (cSources &&& includes) $ libBuildInfo lib
-          hs = (<> ".hs") . toFilePath <$> explicitLibModules lib
+          hs = (++ ".hs") . toFilePath <$> explicitLibModules lib
 
 extract :: CondTree a b Library -> [Library]
 extract (CondNode d _ []) = [d]
@@ -82,8 +82,8 @@
         vers = pkgVersion (package descr)
         libs = toList (condLibrary pkg)
         normalSrc = (libraryToFiles <=< extract) =<< libs
-        dir = (fmap (<> "/") . hsSourceDirs . libBuildInfo <=< extract) =<< libs
-        dirge = ((<>) <$> dir <*>)
+        dir = (fmap (++ "/") . hsSourceDirs . libBuildInfo <=< extract) =<< libs
+        dirge = ((++) <$> dir <*>)
         h = filterM doesFileExist
     norms <- h (dirge normalSrc)
-    pure (vers, extraSrc <> norms)
+    pure (vers, extraSrc ++ norms)
diff --git a/src/Development/Shake/Elm.hs b/src/Development/Shake/Elm.hs
--- a/src/Development/Shake/Elm.hs
+++ b/src/Development/Shake/Elm.hs
@@ -10,5 +10,5 @@
         -> Rules ()
 elmMake sources extras fp =
     fp %> \out -> do
-        need (sources <> extras)
+        need (sources ++ extras)
         command mempty "elm-make" ("--yes" : "--output" : out : "--warn" : sources)
diff --git a/src/Development/Shake/Literate.hs b/src/Development/Shake/Literate.hs
--- a/src/Development/Shake/Literate.hs
+++ b/src/Development/Shake/Literate.hs
@@ -35,8 +35,8 @@
 literateRules :: String -- ^ File extension
               -> Rules ()
 literateRules ext = pat %> g
-    where pat = "//*." <> ('l' : ext)
-          g out = let new = fst (splitExtension out) <> ('.' : ext)
+    where pat = "//*." ++ ('l' : ext)
+          g out = let new = fst (splitExtension out) ++ ('.' : ext)
             in unlitA out new
 
 -- | Rules for building @.lhs@ files.
