diff --git a/CHANGES.txt b/CHANGES.txt
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,9 @@
 Changelog for Shake
 
+0.11.1
+    #94, GHC 7.8 support
+    Add a Config module
+    #89, support :: as a build rule separator
 0.11
     Add alternatives to allow overlapping rules
     Make storedValue take a ShakeOptions structure
diff --git a/Development/Make/Parse.hs b/Development/Make/Parse.hs
--- a/Development/Make/Parse.hs
+++ b/Development/Make/Parse.hs
@@ -5,6 +5,7 @@
 import Development.Make.Type
 import Data.Char
 import Data.List
+import Data.Maybe
 
 
 trim = dropWhile isSpace . reverse . dropWhile isSpace . reverse
@@ -44,7 +45,7 @@
     | (a,':':b) <- break (== ':') x = case b of
         '=':b -> Assign (trim a) ColonEquals (parseExpr $ trim b)
         ':':'=':b -> Assign (trim a) ColonEquals (parseExpr $ trim b)
-        _ -> Rule (parseExpr $ trim a) (parseExpr $ trim b) []
+        _ -> Rule (parseExpr $ trim a) (parseExpr $ trim $ fromMaybe b $ stripPrefix ":" b) []
     | otherwise = error $ "Invalid statement: " ++ x
 
 
diff --git a/Development/Ninja/All.hs b/Development/Ninja/All.hs
--- a/Development/Ninja/All.hs
+++ b/Development/Ninja/All.hs
@@ -26,7 +26,7 @@
 runNinja :: FilePath -> [String] -> IO (Rules ())
 runNinja file args = do
     addTiming "Ninja parse"
-    ninja@Ninja{..} <- parse file
+    ninja@Ninja{..} <- parse file =<< newEnv
     return $ do
         needDeps <- return $ needDeps ninja -- partial application
         phonys <- return $ Map.fromList phonys
diff --git a/Development/Ninja/Env.hs b/Development/Ninja/Env.hs
--- a/Development/Ninja/Env.hs
+++ b/Development/Ninja/Env.hs
@@ -2,7 +2,7 @@
 
 -- | A Ninja style environment, basically a linked-list of mutable hash tables.
 module Development.Ninja.Env(
-    Env, newEnv, scopeEnv, addEnv, askEnv
+    Env, newEnv, scopeEnv, addEnv, askEnv, fromEnv
     ) where
 
 import qualified Data.HashMap.Strict as Map
@@ -34,3 +34,6 @@
         Just v -> return $ Just v
         Nothing | Just e <- e -> askEnv e k
         _ -> return Nothing
+
+fromEnv :: Env k v -> IO (Map.HashMap k v)
+fromEnv (Env ref _) = readIORef ref
diff --git a/Development/Ninja/Lexer.hs b/Development/Ninja/Lexer.hs
--- a/Development/Ninja/Lexer.hs
+++ b/Development/Ninja/Lexer.hs
@@ -44,7 +44,7 @@
             return $! Ptr end `minusPtr` start
 
         go s@(Ptr a) | c == '\0' || f c = a
-                     | otherwise = go $ inc s
+                     | otherwise = go (inc s)
             where c = chr s
 
 {-# INLINE break00 #-}
@@ -58,7 +58,7 @@
             return $! Ptr end `minusPtr` start
 
         go s@(Ptr a) | f c = a
-                     | otherwise = go $ inc s
+                     | otherwise = go (inc s)
             where c = chr s
 
 head0 :: Str0 -> Char
diff --git a/Development/Ninja/Parse.hs b/Development/Ninja/Parse.hs
--- a/Development/Ninja/Parse.hs
+++ b/Development/Ninja/Parse.hs
@@ -9,8 +9,8 @@
 import Control.Monad
 
 
-parse :: FilePath -> IO Ninja
-parse file = do env <- newEnv; parseFile file env newNinja
+parse :: FilePath -> Env Str Str -> IO Ninja
+parse file env = parseFile file env newNinja
 
 
 parseFile :: FilePath -> Env Str Str -> Ninja -> IO Ninja
diff --git a/Development/Shake/Config.hs b/Development/Shake/Config.hs
new file mode 100644
--- /dev/null
+++ b/Development/Shake/Config.hs
@@ -0,0 +1,80 @@
+{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving #-}
+
+-- | A module for parsing and using config files in a Shake build system. Config files
+--   consist of variable bindings, for example:
+--
+-- > # This is my Config file
+-- > HEADERS_DIR = /path/to/dir
+-- > CFLAGS = -g -I${HEADERS_DIR}
+-- > CFLAGS = $CFLAGS -O2
+-- > include extra/file.cfg
+--
+--   This defines the variable @HEADERS_DIR@ (equal to @\/path\/to\/dir@), and
+--   @CFLAGS@ (equal to @-g -I\/path\/to\/dir -O2@), and also includes the configuration
+--   statements in the file @extra/file.cfg@. The full lexical syntax for configuration
+--   files is defined here: <http://martine.github.io/ninja/manual.html#_lexical_syntax>.
+--
+--   To use the configuration file either use 'readConfigFile' to parse the configuration file
+--   and use the values directly, or 'usingConfigFile' and 'getConfig' to track the configuration
+--   values, so they become build dependencies.
+module Development.Shake.Config(
+    readConfigFile,
+    usingConfigFile, usingConfig,
+    getConfig
+    ) where
+
+import Development.Shake
+import Development.Shake.Classes
+import qualified Development.Ninja.Parse as Ninja
+import qualified Development.Ninja.Env as Ninja
+import qualified Data.HashMap.Strict as Map
+import qualified Data.ByteString.UTF8 as UTF8
+import Control.Applicative
+import Control.Arrow
+
+
+-- | Read a config file, returning a list of the variables and their bindings.
+--   Config files use the Ninja lexical syntax:
+--   <http://martine.github.io/ninja/manual.html#_lexical_syntax>
+readConfigFile :: FilePath -> IO (Map.HashMap String String)
+readConfigFile file = do
+    env <- Ninja.newEnv
+    Ninja.parse file env
+    mp <- Ninja.fromEnv env
+    return $ Map.fromList $ map (UTF8.toString *** UTF8.toString) $ Map.toList mp
+
+
+newtype Config = Config String deriving (Show,Typeable,Eq,Hashable,Binary,NFData)
+
+
+-- | Specify the file to use with 'getConfig'.
+usingConfigFile :: FilePath -> Rules ()
+usingConfigFile file = do
+    mp <- newCache $ \() -> liftIO $ readConfigFile file
+    addOracle $ \(Config x) -> Map.lookup x <$> mp ()
+    return ()
+
+
+-- | Specify the values to use with 'getConfig', generally prefer
+--   'usingConfigFile' unless you also need access to the values
+--   of variables outside 'Action'.
+usingConfig :: Map.HashMap String String -> Rules ()
+usingConfig mp = do
+    addOracle $ \(Config x) -> return $ Map.lookup x mp
+    return ()
+
+
+-- | Obtain the value of a configuration variable, returns 'Nothing' to indicate the variable
+--   has no binding. Any build system using 'getConfig' /must/ call either 'usingConfigFile'
+--   or 'usingConfig'. The 'getConfig' function will introduce a dependency on the configuration
+--   variable (but not the whole configuration file), and if the configuration variable changes, the rule will be rerun.
+--   As an example:
+--
+-- @
+-- 'usingConfigFile' \"myconfiguration.cfg\"
+-- \"*.o\" '*>' \\out -> do
+--     cflags <- 'getConfig' \"CFLAGS\"
+--     'cmd' \"gcc\" [out '-<.>' \"c\"] (fromMaybe \"\" cflags)
+-- @
+getConfig :: String -> Action (Maybe String)
+getConfig = askOracle . Config
diff --git a/Development/Shake/Core.hs b/Development/Shake/Core.hs
--- a/Development/Shake/Core.hs
+++ b/Development/Shake/Core.hs
@@ -95,7 +95,7 @@
 ruleValue = err "ruleValue"
 
 
--- | Define a set of rules. Rules can be created with calls to functions such as '*>' or 'action'. Rules are combined
+-- | Define a set of rules. Rules can be created with calls to functions such as 'Development.Shake.*>' or 'action'. Rules are combined
 --   with either the 'Monoid' instance, or (more commonly) the 'Monad' instance and @do@ notation. To define your own
 --   custom types of rule, see "Development.Shake.Rule".
 newtype Rules a = Rules (WriterT SRules IO a) -- All IO must be associative/commutative (e.g. creating IORef/MVars)
@@ -772,7 +772,7 @@
 -- digits \<- 'newCache' $ \\file -> do
 --     src \<- readFile\' file
 --     return $ length $ filter isDigit src
--- \"*.digits\" '*>' \\x -> do
+-- \"*.digits\" 'Development.Shake.*>' \\x -> do
 --     v1 \<- digits ('dropExtension' x)
 --     v2 \<- digits ('dropExtension' x)
 --     'Development.Shake.writeFile'' x $ show (v1,v2)
diff --git a/Development/Shake/Types.hs b/Development/Shake/Types.hs
--- a/Development/Shake/Types.hs
+++ b/Development/Shake/Types.hs
@@ -97,9 +97,7 @@
         -- ^ Defaults to 'Nothing'. Write an HTML profiling report to a file, showing which
         --   rules rebuilt, why, and how much time they took. Useful for improving the speed of your build systems.
     ,shakeLint :: Maybe Lint
-        -- ^ Defaults to 'False'. Perform basic sanity checks during building, checking the current directory
-        --   is not modified and that output files are not modified by multiple rules.
-        --   These sanity checks do not check for missing or redundant dependencies.
+        -- ^ Defaults to 'Nothing'. Perform sanity checks during building, see 'Lint' for details.
     ,shakeFlush :: Maybe Double
         -- ^ Defaults to @'Just' 10@. How often to flush Shake metadata files in seconds, or 'Nothing' to never flush explicitly.
         --   It is possible that on abnormal termination (not Haskell exceptions) any rules that completed in the last
diff --git a/Examples/Test/Config.hs b/Examples/Test/Config.hs
new file mode 100644
--- /dev/null
+++ b/Examples/Test/Config.hs
@@ -0,0 +1,41 @@
+
+module Examples.Test.Config(main) where
+
+import Development.Shake
+import Development.Shake.FilePath
+import Development.Shake.Config
+import Examples.Util
+import Data.Char
+import Data.Maybe
+import System.Directory
+
+
+main = shaken test $ \args obj -> do
+    want $ map obj ["hsflags.var","cflags.var","none.var"]
+    usingConfigFile $ obj "config"
+    obj "*.var" *> \out -> do
+        cfg <- getConfig $ map toUpper $ takeBaseName out
+        liftIO $ appendFile (out -<.> "times") "X"
+        writeFile' out $ fromMaybe "" cfg
+
+
+test build obj = do
+    build ["clean"]
+    createDirectoryIfMissing True $ obj ""
+    writeFile (obj "config") $ unlines
+        ["HEADERS_DIR = /path/to/dir"
+        ,"CFLAGS = -O2 -I${HEADERS_DIR} -g"
+        ,"HSFLAGS = -O2"]
+    build []
+    assertContents (obj "cflags.var") "-O2 -I/path/to/dir -g"
+    assertContents (obj "hsflags.var") "-O2"
+    assertContents (obj "none.var") ""
+
+    appendFile (obj "config") $ unlines
+        ["CFLAGS = $CFLAGS -w"]
+    build []
+    assertContents (obj "cflags.var") "-O2 -I/path/to/dir -g -w"
+    assertContents (obj "hsflags.var") "-O2"
+    assertContents (obj "cflags.times") "XX"
+    assertContents (obj "hsflags.times") "X"
+    assertContents (obj "none.times") "X"
diff --git a/Examples/Test/Docs.hs b/Examples/Test/Docs.hs
--- a/Examples/Test/Docs.hs
+++ b/Examples/Test/Docs.hs
@@ -21,7 +21,7 @@
 
     want $ map (\x -> fromMaybe (obj x) $ stripPrefix "!" x) args
 
-    let needSource = need =<< getDirectoryFiles "." ["Development/Shake.hs","Development/Shake//*.hs","General//*.hs"]
+    let needSource = need =<< getDirectoryFiles "." ["Development/Shake.hs","Development/Shake//*.hs","Development/Ninja/*.hs","General//*.hs"]
 
     index *> \_ -> do
         needSource
@@ -89,7 +89,7 @@
     obj "Files.lst" *> \out -> do
         need [index,obj "Paths_shake.hs"]
         files <- getDirectoryFiles "dist/doc/html/shake" ["Development-*.html"]
-        files <- return $ filter (not . isSuffixOf "-Classes.html") files
+        files <- return $ filter (\x -> not ("-Classes.html" `isSuffixOf` x) && not ("Config.html" `isSuffixOf` x)) files
         writeFileLines out $ map ((++) "Part_" . reps '-' '_' . takeBaseName) files
 
     let needModules = do mods <- readFileLines $ obj "Files.lst"; need [obj m <.> "hs" | m <- mods]; return mods
@@ -192,6 +192,6 @@
 
 types = words $
     "MVar IO Monad Monoid String FilePath Data [String] Eq Typeable Char ExitCode " ++
-    "Action Resource Assume FilePattern Verbosity Rules Rule CmdOption CmdResult Int Double"
+    "Action Resource Assume FilePattern Lint Verbosity Rules Rule CmdOption CmdResult Int Double"
 
 dupes = words "main progressSimple rules"
diff --git a/Test.hs b/Test.hs
--- a/Test.hs
+++ b/Test.hs
@@ -24,6 +24,7 @@
 import qualified Examples.Test.Benchmark as Benchmark
 import qualified Examples.Test.Cache as Cache
 import qualified Examples.Test.Command as Command
+import qualified Examples.Test.Config as Config
 import qualified Examples.Test.Directory as Directory
 import qualified Examples.Test.Docs as Docs
 import qualified Examples.Test.Errors as Errors
@@ -51,7 +52,8 @@
     where (*) = (,)
 
 mains = ["tar" * Tar.main, "self" * Self.main, "c" * C.main
-        ,"basic" * Basic.main, "cache" * Cache.main, "command" * Command.main, "directory" * Directory.main
+        ,"basic" * Basic.main, "cache" * Cache.main, "command" * Command.main
+        ,"config" * Config.main, "directory" * Directory.main
         ,"docs" * Docs.main, "errors" * Errors.main, "orderonly" * OrderOnly.main
         ,"filepath" * FilePath.main, "filepattern" * FilePattern.main, "files" * Files.main
         ,"journal" * Journal.main, "lint" * Lint.main, "makefile" * Makefile.main
diff --git a/shake.cabal b/shake.cabal
--- a/shake.cabal
+++ b/shake.cabal
@@ -1,7 +1,7 @@
 cabal-version:      >= 1.10
 build-type:         Simple
 name:               shake
-version:            0.11
+version:            0.11.1
 license:            BSD3
 license-file:       LICENSE
 category:           Development
@@ -90,12 +90,17 @@
         Development.Shake
         Development.Shake.Classes
         Development.Shake.Command
+        Development.Shake.Config
         Development.Shake.FilePath
         Development.Shake.Rule
         Development.Shake.Sys
         Development.Shake.Util
 
     other-modules:
+        Development.Ninja.Env
+        Development.Ninja.Lexer
+        Development.Ninja.Parse
+        Development.Ninja.Type
         Development.Shake.Args
         Development.Shake.ByteString
         Development.Shake.Core
@@ -160,10 +165,6 @@
         Development.Make.Rules
         Development.Make.Type
         Development.Ninja.All
-        Development.Ninja.Env
-        Development.Ninja.Lexer
-        Development.Ninja.Parse
-        Development.Ninja.Type
         Start
 
 
@@ -214,6 +215,7 @@
         Examples.Test.Benchmark
         Examples.Test.Cache
         Examples.Test.Command
+        Examples.Test.Config
         Examples.Test.Directory
         Examples.Test.Docs
         Examples.Test.Errors
