Merge tools/gyp from https://chromium.googlesource.com/external/gyp.git at 39fd3e8ea1c88c144a756f8fe23c1a361ae13495

This commit was generated by merge_from_chromium.py.

Change-Id: I2803e03a972897e3a400528e1a6b85d65331ae57
diff --git a/pylib/gyp/generator/ninja.py b/pylib/gyp/generator/ninja.py
index f31068a..7cdb0e8 100644
--- a/pylib/gyp/generator/ninja.py
+++ b/pylib/gyp/generator/ninja.py
@@ -14,6 +14,7 @@
 import sys
 import gyp
 import gyp.common
+from gyp.common import OrderedSet
 import gyp.msvs_emulation
 import gyp.MSVSUtil as MSVSUtil
 import gyp.xcode_emulation
@@ -1777,8 +1778,15 @@
       wrappers[key_prefix] = os.path.join(build_to_root, value)
 
   if flavor == 'win':
+    configs = [target_dicts[qualified_target]['configurations'][config_name]
+               for qualified_target in target_list]
+    shared_system_includes = None
+    if not generator_flags.get('ninja_use_custom_environment_files', 0):
+      shared_system_includes = \
+          gyp.msvs_emulation.ExtractSharedMSVSSystemIncludes(
+              configs, generator_flags)
     cl_paths = gyp.msvs_emulation.GenerateEnvironmentFiles(
-        toplevel_build, generator_flags, OpenOutput)
+        toplevel_build, generator_flags, shared_system_includes, OpenOutput)
     for arch, path in cl_paths.iteritems():
       if clang_cl:
         # If we have selected clang-cl, use that instead.
diff --git a/pylib/gyp/msvs_emulation.py b/pylib/gyp/msvs_emulation.py
index 63593a4..1b82adb 100644
--- a/pylib/gyp/msvs_emulation.py
+++ b/pylib/gyp/msvs_emulation.py
@@ -12,6 +12,7 @@
 import subprocess
 import sys
 
+from gyp.common import OrderedSet
 import gyp.MSVSVersion
 
 windows_quoter_regex = re.compile(r'(\\*)"')
@@ -131,6 +132,54 @@
   return dxsdk_dir
 
 
+def GetGlobalVSMacroEnv(vs_version):
+  """Get a dict of variables mapping internal VS macro names to their gyp
+  equivalents. Returns all variables that are independent of the target."""
+  env = {}
+  # '$(VSInstallDir)' and '$(VCInstallDir)' are available when and only when
+  # Visual Studio is actually installed.
+  if vs_version.Path():
+    env['$(VSInstallDir)'] = vs_version.Path()
+    env['$(VCInstallDir)'] = os.path.join(vs_version.Path(), 'VC') + '\\'
+  # Chromium uses DXSDK_DIR in include/lib paths, but it may or may not be
+  # set. This happens when the SDK is sync'd via src-internal, rather than
+  # by typical end-user installation of the SDK. If it's not set, we don't
+  # want to leave the unexpanded variable in the path, so simply strip it.
+  dxsdk_dir = _FindDirectXInstallation()
+  env['$(DXSDK_DIR)'] = dxsdk_dir if dxsdk_dir else ''
+  # Try to find an installation location for the Windows DDK by checking
+  # the WDK_DIR environment variable, may be None.
+  env['$(WDK_DIR)'] = os.environ.get('WDK_DIR', '')
+  return env
+
+def ExtractSharedMSVSSystemIncludes(configs, generator_flags):
+  """Finds msvs_system_include_dirs that are common to all targets, removes
+  them from all targets, and returns an OrderedSet containing them."""
+  all_system_includes = OrderedSet(
+      configs[0].get('msvs_system_include_dirs', []))
+  for config in configs[1:]:
+    system_includes = config.get('msvs_system_include_dirs', [])
+    all_system_includes = all_system_includes & OrderedSet(system_includes)
+  if not all_system_includes:
+    return None
+  # Expand macros in all_system_includes.
+  env = GetGlobalVSMacroEnv(GetVSVersion(generator_flags))
+  expanded_system_includes = OrderedSet([ExpandMacros(include, env)
+                                         for include in all_system_includes])
+  if any(['$' in include for include in expanded_system_includes]):
+    # Some path relies on target-specific variables, bail.
+    return None
+
+  # Remove system includes shared by all targets from the targets.
+  for config in configs:
+    includes = config.get('msvs_system_include_dirs', [])
+    if includes:  # Don't insert a msvs_system_include_dirs key if not needed.
+      # This must check the unexpanded includes list:
+      new_includes = [i for i in includes if i not in all_system_includes]
+      config['msvs_system_include_dirs'] = new_includes
+  return expanded_system_includes
+
+
 class MsvsSettings(object):
   """A class that understands the gyp 'msvs_...' values (especially the
   msvs_settings field). They largely correpond to the VS2008 IDE DOM. This
@@ -139,11 +188,6 @@
   def __init__(self, spec, generator_flags):
     self.spec = spec
     self.vs_version = GetVSVersion(generator_flags)
-    self.dxsdk_dir = _FindDirectXInstallation()
-
-    # Try to find an installation location for the Windows DDK by checking
-    # the WDK_DIR environment variable, may be None.
-    self.wdk_dir = os.environ.get('WDK_DIR')
 
     supported_fields = [
         ('msvs_configuration_attributes', dict),
@@ -194,18 +238,7 @@
         '$(PlatformName)': target_platform,
         '$(ProjectDir)\\': '',
     }
-    # '$(VSInstallDir)' and '$(VCInstallDir)' are available when and only when
-    # Visual Studio is actually installed.
-    if self.vs_version.Path():
-      replacements['$(VSInstallDir)'] = self.vs_version.Path()
-      replacements['$(VCInstallDir)'] = os.path.join(self.vs_version.Path(),
-                                                     'VC') + '\\'
-    # Chromium uses DXSDK_DIR in include/lib paths, but it may or may not be
-    # set. This happens when the SDK is sync'd via src-internal, rather than
-    # by typical end-user installation of the SDK. If it's not set, we don't
-    # want to leave the unexpanded variable in the path, so simply strip it.
-    replacements['$(DXSDK_DIR)'] = self.dxsdk_dir if self.dxsdk_dir else ''
-    replacements['$(WDK_DIR)'] = self.wdk_dir if self.wdk_dir else ''
+    replacements.update(GetGlobalVSMacroEnv(self.vs_version))
     return replacements
 
   def ConvertVSMacros(self, s, base_to_build=None, config=None):
@@ -897,7 +930,8 @@
     if line.startswith('LOC:'):
       return line[len('LOC:'):].strip()
 
-def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags, open_out):
+def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags,
+                             system_includes, open_out):
   """It's not sufficient to have the absolute path to the compiler, linker,
   etc. on Windows, as those tools rely on .dlls being in the PATH. We also
   need to support both x86 and x64 compilers within the same build (to support
@@ -928,6 +962,13 @@
         args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
     variables, _ = popen.communicate()
     env = _ExtractImportantEnvironment(variables)
+
+    # Inject system includes from gyp files into INCLUDE.
+    if system_includes:
+      system_includes = system_includes | OrderedSet(
+                                              env.get('INCLUDE', '').split(';'))
+      env['INCLUDE'] = ';'.join(system_includes)
+
     env_block = _FormatAsEnvironmentBlock(env)
     f = open_out(os.path.join(toplevel_build_dir, 'environment.' + arch), 'wb')
     f.write(env_block)
diff --git a/test/win/gyptest-system-include.py b/test/win/gyptest-system-include.py
new file mode 100644
index 0000000..9a47d98
--- /dev/null
+++ b/test/win/gyptest-system-include.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2014 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Checks that msvs_system_include_dirs works.
+"""
+
+import TestGyp
+
+import sys
+
+if sys.platform == 'win32':
+  test = TestGyp.TestGyp(formats=['msvs', 'ninja'])
+
+  CHDIR = 'system-include'
+  test.run_gyp('test.gyp', chdir=CHDIR)
+  test.build('test.gyp', test.ALL, chdir=CHDIR)
+  test.pass_test()
diff --git a/test/win/system-include/bar/header.h b/test/win/system-include/bar/header.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/win/system-include/bar/header.h
diff --git a/test/win/system-include/common/commonheader.h b/test/win/system-include/common/commonheader.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/win/system-include/common/commonheader.h
diff --git a/test/win/system-include/foo/header.h b/test/win/system-include/foo/header.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/win/system-include/foo/header.h
diff --git a/test/win/system-include/main.cc b/test/win/system-include/main.cc
new file mode 100644
index 0000000..b04ea8a
--- /dev/null
+++ b/test/win/system-include/main.cc
@@ -0,0 +1,4 @@
+#include <commonheader.h>
+#include <header.h>
+
+int main() {}
diff --git a/test/win/system-include/test.gyp b/test/win/system-include/test.gyp
new file mode 100644
index 0000000..07f2636
--- /dev/null
+++ b/test/win/system-include/test.gyp
@@ -0,0 +1,26 @@
+{
+  'target_defaults': {
+    'msvs_settings': {
+      'VCCLCompilerTool': {
+        'WarningLevel': '4',
+        'WarnAsError': 'true',
+      },
+    },
+    'msvs_system_include_dirs': [
+      '$(ProjectName)',  # Different for each target
+      'common',  # Same for all targets
+    ],
+  },
+  'targets': [
+    {
+      'target_name': 'foo',
+      'type': 'executable',
+      'sources': [ 'main.cc', ],
+    },
+    {
+      'target_name': 'bar',
+      'type': 'executable',
+      'sources': [ 'main.cc', ],
+    },
+  ],
+}