diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,6 @@
+# shake-c
+
+## 0.4.1.0
+
+  * Add `idOracle`
+  * Exported rules now use oracles
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright Vanessa McHale (c) 2018
+Copyright Vanessa McHale (c) 2018-2019
 
 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 
diff --git a/Setup.hs b/Setup.hs
deleted file mode 100644
--- a/Setup.hs
+++ /dev/null
@@ -1,2 +0,0 @@
-import Distribution.Simple
-main = defaultMain
diff --git a/shake-c.cabal b/shake-c.cabal
--- a/shake-c.cabal
+++ b/shake-c.cabal
@@ -1,9 +1,9 @@
 cabal-version: 1.18
 name: shake-c
-version: 0.4.0.0
+version: 0.4.1.0
 license: BSD3
 license-file: LICENSE
-copyright: Copyright: (c) 2018 Vanessa McHale
+copyright: Copyright: (c) 2018-2019 Vanessa McHale
 maintainer: vanessa.mchale@iohk.io
 author: Vanessa McHale
 bug-reports: https://hub.darcs.net/vmchale/ats/issues
@@ -13,6 +13,7 @@
 category: Development, C
 build-type: Simple
 extra-doc-files: README.md
+                 CHANGELOG.md
 
 source-repository head
     type: darcs
@@ -29,20 +30,21 @@
         Development.Shake.C
     hs-source-dirs: src
     default-language: Haskell2010
-    other-extensions: DeriveAnyClass DeriveGeneric
+    other-extensions: DeriveAnyClass DeriveGeneric DeriveDataTypeable
+                      TypeFamilies
     ghc-options: -Wall
     build-depends:
         base >=4.3 && <5,
         shake >=0.14,
         cdeps -any,
         composition-prelude -any
-    
+
     if flag(development)
         ghc-options: -Werror
-    
+
     if impl(ghc >=8.0)
         ghc-options: -Wincomplete-uni-patterns -Wincomplete-record-updates
                      -Wredundant-constraints -Wnoncanonical-monad-instances
-    
+
     if impl(ghc >=8.4)
         ghc-options: -Wmissing-export-lists
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,5 +1,7 @@
-{-# LANGUAGE DeriveAnyClass #-}
-{-# LANGUAGE DeriveGeneric  #-}
+{-# LANGUAGE DeriveAnyClass     #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE TypeFamilies       #-}
 
 -- | This module provides functions for easy C builds of binaries, static
 -- libraries, and dynamic libraries.
@@ -13,6 +15,8 @@
                            , dynLibR
                            , cBin
                            , cToLib
+                           -- * Oracles
+                           , idOracle
                            -- * Actions
                            , pkgConfig
                            , binaryA
@@ -99,7 +103,7 @@
 ccFromString _ = Other "cc"
 
 -- ALSO consider using Haskell -> C -> ICC ??
--- TODO ICC??
+-- TODO TCC
 -- | A data type representing the C compiler to be used.
 data CCompiler = GCC { _prefix  :: Maybe String -- ^ Usually the target triple
                      , _postfix :: Maybe String -- ^ The compiler version
@@ -111,7 +115,7 @@
                | CompCert
                | ICC
                | Other String
-               deriving (Generic, Binary) -- Show, Eq, Generic, Typeable, Hashable, Binary, NFData)
+               deriving (Generic, Binary, Show, Typeable, Eq, Hashable, NFData)
 
 mapFlags :: String -> ([String] -> [String])
 mapFlags s = fmap (s ++)
@@ -122,8 +126,17 @@
                        , extras     :: [String] -- ^ Extra flags to be passed to the compiler
                        , staticLink :: Bool -- ^ Whether to link against static versions of libraries
                        }
-             deriving (Generic, Binary) -- Show, Eq, Generic, Typeable, Hashable, Binary, NFData)
+             deriving (Generic, Binary, Show, Typeable, Eq, Hashable, NFData)
 
+type instance RuleResult CCompiler = CCompiler
+type instance RuleResult CConfig = CConfig
+
+-- | Use this for tracking e.g. 'CCompiler' or 'CConfig'
+--
+-- @since 0.4.1.0
+idOracle :: (RuleResult q ~ a, q ~ a, ShakeValue q) => Rules (q -> Action a)
+idOracle = addOracle pure
+
 -- | Rules for making a static library from C source files. Unlike 'staticLibR',
 -- this also creates rules for creating object files.
 cToLib :: CCompiler
@@ -132,9 +145,7 @@
        -> CConfig
        -> Rules ()
 cToLib cc sources lib cfg =
-    mconcat [ mconcat objRules
-            , staticLibR cc (g sources) lib cfg
-            ]
+    sequence_ ( staticLibR cc (g sources) lib cfg : objRules)
     where objRules = objectFileR cc cfg <$> g sources <*> pure lib
           g = fmap (-<.> "o")
 
@@ -147,6 +158,7 @@
      -> Rules ()
 cBin cc sources bin cfg = bin %> \out -> binaryA cc sources out cfg
 -- TODO depend on config!!
+-- TODO depend on the source files transitively (optionally)
 
 stripA :: CmdResult r
        => FilePath -- ^ Build product to be stripped
@@ -178,10 +190,14 @@
         -> FilePattern -- ^ Shared object file to be generated.
         -> CConfig
         -> Rules ()
-dynLibR cc objFiles shLib cfg =
-    shLib %> \out ->
-        need objFiles *>
-        command [EchoStderr False] (ccToString cc) ("-shared" : "-o" : out : objFiles ++ cconfigToArgs cfg)
+dynLibR cc objFiles shLib cfg = do
+    ccOracle <- idOracle
+    cconfOracle <- idOracle
+    shLib %> \out -> do
+        need objFiles
+        cc' <- ccOracle cc
+        cfg' <- cconfOracle 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
@@ -189,10 +205,14 @@
             -> FilePath -- ^ C source file
             -> FilePattern -- ^ Object file output
             -> Rules ()
-objectFileR cc cfg srcFile objFile =
-    objFile %> \out ->
-        need [srcFile] *>
-        command [EchoStderr False] (ccToString cc) (srcFile : "-c" : "-fPIC" : "-o" : out : cconfigToArgs cfg)
+objectFileR cc cfg srcFile objFile = do
+    ccOracle <- idOracle
+    cconfOracle <- idOracle
+    objFile %> \out -> do
+        need [srcFile]
+        cc' <- ccOracle cc
+        cfg' <- cconfOracle cfg
+        command [EchoStderr False] (ccToString cc') (srcFile : "-c" : "-fPIC" : "-o" : out : cconfigToArgs cfg')
 
 sharedLibA :: CmdResult r
            => CCompiler
@@ -219,13 +239,23 @@
            -> FilePattern -- ^ File pattern for shared library outputs
            -> CConfig
            -> Rules ()
-sharedLibR cc objFiles shrLib cfg =
-    shrLib %> \out -> sharedLibA cc objFiles out cfg
+sharedLibR cc objFiles shrLib cfg = do
+    ccOracle <- idOracle
+    cconfOracle <- idOracle
+    shrLib %> \out -> do
+        cc' <- ccOracle cc
+        cfg' <- cconfOracle cfg
+        sharedLibA cc' objFiles out cfg'
 
 staticLibR :: CCompiler
            -> [FilePath] -- ^ Object files to be linked
            -> FilePattern -- ^ File pattern for static library outputs
            -> CConfig
            -> Rules ()
-staticLibR ar objFiles stalib cfg =
-    stalib %> \out -> staticLibA ar objFiles out cfg
+staticLibR ar objFiles stalib cfg = do
+    ccOracle <- idOracle
+    cconfOracle <- idOracle
+    stalib %> \out -> do
+        ar' <- ccOracle ar
+        cfg' <- cconfOracle cfg
+        staticLibA ar' objFiles out cfg'
