diff --git a/build/check_gn_headers.py b/build/check_gn_headers.py
index fe884db..c5095e61 100755
--- a/build/check_gn_headers.py
+++ b/build/check_gn_headers.py
@@ -38,13 +38,13 @@
 
   ans, err = set(), None
   try:
-    ans = ParseNinjaDepsOutput(NinjaSource())
+    ans = ParseNinjaDepsOutput(NinjaSource(), out_dir)
   except Exception as e:
     err = str(e)
   q.put((ans, err))
 
 
-def ParseNinjaDepsOutput(ninja_out):
+def ParseNinjaDepsOutput(ninja_out, out_dir):
   """Parse ninja output and get the header files"""
   all_headers = set()
 
@@ -62,6 +62,8 @@
           # build/ only contains build-specific files like build_config.h
           # and buildflag.h, and system header files, so they should be
           # skipped.
+          if f.startswith(out_dir) or f.startswith('out'):
+            continue
           if not f.startswith('build'):
             all_headers.add(f)
     else:
@@ -128,6 +130,12 @@
   q.put((prefixes, err))
 
 
+def IsBuildClean(out_dir):
+  cmd = ['ninja', '-C', out_dir, '-n']
+  out = subprocess.check_output(cmd)
+  return 'no work to do.' in out
+
+
 def ParseWhiteList(whitelist):
   out = set()
   for line in whitelist.split('\n'):
@@ -150,6 +158,16 @@
 
 
 def main():
+
+  def DumpJson(data):
+    if args.json:
+      with open(args.json, 'w') as f:
+        json.dump(data, f)
+
+  def PrintError(msg):
+    DumpJson([])
+    parser.error(msg)
+
   parser = argparse.ArgumentParser(description='''
       NOTE: Use ninja to build all targets in OUT_DIR before running
       this script.''')
@@ -158,12 +176,27 @@
   parser.add_argument('--json',
                       help='JSON output filename for missing headers')
   parser.add_argument('--whitelist', help='file containing whitelist')
+  parser.add_argument('--skip-dirty-check', action='store_true',
+                      help='skip checking whether the build is dirty')
 
   args, _extras = parser.parse_known_args()
 
   if not os.path.isdir(args.out_dir):
     parser.error('OUT_DIR "%s" does not exist.' % args.out_dir)
 
+  if not args.skip_dirty_check and not IsBuildClean(args.out_dir):
+    dirty_msg = 'OUT_DIR looks dirty. You need to build all there.'
+    if args.json:
+      # Assume running on the bots. Silently skip this step.
+      # This is possible because "analyze" step can be wrong due to
+      # underspecified header files. See crbug.com/725877
+      print dirty_msg
+      DumpJson([])
+      return 0
+    else:
+      # Assume running interactively.
+      parser.error(dirty_msg)
+
   d_q = Queue()
   d_p = Process(target=GetHeadersFromNinja, args=(args.out_dir, d_q,))
   d_p.start()
@@ -190,29 +223,29 @@
   deps_p.join()
 
   if d_err:
-    parser.error(d_err)
+    PrintError(d_err)
   if gn_err:
-    parser.error(gn_err)
+    PrintError(gn_err)
   if deps_err:
-    parser.error(deps_err)
+    PrintError(deps_err)
   if len(GetNonExistingFiles(d)) > 0:
-    parser.error('''Found non-existing files in ninja deps. You should
-        build all in OUT_DIR.''')
+    print 'Non-existing files in ninja deps:', GetNonExistingFiles(d)
+    PrintError('Found non-existing files in ninja deps. You should ' +
+               'build all in OUT_DIR.')
   if len(d) == 0:
-    parser.error('OUT_DIR looks empty. You should build all there.')
+    PrintError('OUT_DIR looks empty. You should build all there.')
   if any((('/gen/' in i) for i in nonexisting)):
-    parser.error('OUT_DIR looks wrong. You should build all there.')
+    PrintError('OUT_DIR looks wrong. You should build all there.')
 
   if args.whitelist:
     whitelist = ParseWhiteList(open(args.whitelist).read())
     missing -= whitelist
+    nonexisting -= whitelist
 
   missing = sorted(missing)
   nonexisting = sorted(nonexisting)
 
-  if args.json:
-    with open(args.json, 'w') as f:
-      json.dump(missing, f)
+  DumpJson(sorted(missing + nonexisting))
 
   if len(missing) == 0 and len(nonexisting) == 0:
     return 0
diff --git a/build/check_gn_headers_unittest.py b/build/check_gn_headers_unittest.py
index 78c7877..e0853fd 100755
--- a/build/check_gn_headers_unittest.py
+++ b/build/check_gn_headers_unittest.py
@@ -25,6 +25,7 @@
     ../../c.cc
     ../../build/a.h
     gen/b.h
+    ../../out/Release/gen/no.h
     ../../dir3/path/b.h
     ../../c3.hh
 '''
@@ -64,7 +65,8 @@
 
 class CheckGnHeadersTest(unittest.TestCase):
   def testNinja(self):
-    headers = check_gn_headers.ParseNinjaDepsOutput(ninja_input.split('\n'))
+    headers = check_gn_headers.ParseNinjaDepsOutput(
+        ninja_input.split('\n'), 'out/Release')
     expected = set([
         'dir/path/b.h',
         'c.hh',
@@ -78,7 +80,7 @@
     os.sep = '\\'
 
     headers = check_gn_headers.ParseNinjaDepsOutput(
-        ninja_input_win.split('\n'))
+        ninja_input_win.split('\n'), 'out\\Release')
     expected = set([
         'dir\\path\\b.h',
         'c.hh',
diff --git a/build/toolchain/win/setup_toolchain.py b/build/toolchain/win/setup_toolchain.py
index e8b0849..d91bf9b2 100644
--- a/build/toolchain/win/setup_toolchain.py
+++ b/build/toolchain/win/setup_toolchain.py
@@ -50,7 +50,7 @@
           # path. Add the path to this python here so that if it's not in the
           # path when ninja is run later, python will still be found.
           setting = os.path.dirname(sys.executable) + os.pathsep + setting
-        env[var.upper()] = setting
+        env[var.upper()] = setting.lower()
         break
   if sys.platform in ('win32', 'cygwin'):
     for required in ('SYSTEMROOT', 'TEMP', 'TMP'):