Merge from Chromium at DEPS revision 614f7b807940

This commit was generated by merge_to_master.py.

Change-Id: Ia5907b240acf3d9443c73353e6ada203505b9dea
diff --git a/pylib/gyp/MSVSUtil.py b/pylib/gyp/MSVSUtil.py
index fbf3ed2..0b32e91 100644
--- a/pylib/gyp/MSVSUtil.py
+++ b/pylib/gyp/MSVSUtil.py
@@ -8,10 +8,12 @@
 import os
 
 
-_TARGET_TYPE_EXT = {
-  'executable': '.exe',
-  'loadable_module': '.dll',
-  'shared_library': '.dll',
+# A dictionary mapping supported target types to extensions.
+TARGET_TYPE_EXT = {
+  'executable': 'exe',
+  'loadable_module': 'dll',
+  'shared_library': 'dll',
+  'static_library': 'lib',
 }
 
 
@@ -157,7 +159,7 @@
 
 
   pdb_base = target_dict.get('product_name', target_dict['target_name'])
-  pdb_base = '%s%s.pdb' % (pdb_base, _TARGET_TYPE_EXT[target_dict['type']])
+  pdb_base = '%s.%s.pdb' % (pdb_base, TARGET_TYPE_EXT[target_dict['type']])
   pdb_path = vars['PRODUCT_DIR'] + '/' + pdb_base
 
   return pdb_path
diff --git a/pylib/gyp/generator/android.py b/pylib/gyp/generator/android.py
index 5afeb53..4129b8e 100644
--- a/pylib/gyp/generator/android.py
+++ b/pylib/gyp/generator/android.py
@@ -108,7 +108,7 @@
     self.android_top_dir = android_top_dir
 
   def Write(self, qualified_target, relative_target, base_path, output_filename,
-            spec, configs, part_of_all, write_alias_target):
+            spec, configs, part_of_all, write_alias_target, sdk_version):
     """The main entry point: writes a .mk file for a single target.
 
     Arguments:
@@ -121,6 +121,7 @@
       part_of_all: flag indicating this target is part of 'all'
       write_alias_target: flag indicating whether to create short aliases for
                           this target
+      sdk_version: what to emit for LOCAL_SDK_VERSION in output
     """
     gyp.common.EnsureDirExists(output_filename)
 
@@ -166,6 +167,7 @@
     else:
       self.WriteLn('LOCAL_MODULE_TARGET_ARCH := '
                    '$(TARGET_$(GYP_VAR_PREFIX)ARCH)')
+      self.WriteLn('LOCAL_SDK_VERSION := %s' % sdk_version)
 
     # Grab output directories; needed for Actions and Rules.
     if self.toolset == 'host':
@@ -719,16 +721,20 @@
 
     return (clean_cflags, include_paths)
 
-  def ComputeAndroidLibraryModuleNames(self, libraries):
-    """Compute the Android module names from libraries, ie spec.get('libraries')
+  def FilterLibraries(self, libraries):
+    """Filter the 'libraries' key to separate things that shouldn't be ldflags.
+
+    Library entries that look like filenames should be converted to android
+    module names instead of being passed to the linker as flags.
 
     Args:
       libraries: the value of spec.get('libraries')
     Returns:
-      A tuple (static_lib_modules, dynamic_lib_modules)
+      A tuple (static_lib_modules, dynamic_lib_modules, ldflags)
     """
     static_lib_modules = []
     dynamic_lib_modules = []
+    ldflags = []
     for libs in libraries:
       # Libs can have multiple words.
       for lib in libs.split():
@@ -745,13 +751,9 @@
         if match:
           dynamic_lib_modules.append(match.group(1))
           continue
-        # "-lstlport" -> libstlport
         if lib.startswith('-l'):
-          if lib.endswith('_static'):
-            static_lib_modules.append('lib' + lib[2:])
-          else:
-            dynamic_lib_modules.append('lib' + lib[2:])
-    return (static_lib_modules, dynamic_lib_modules)
+          ldflags.append(lib)
+    return (static_lib_modules, dynamic_lib_modules, ldflags)
 
 
   def ComputeDeps(self, spec):
@@ -779,19 +781,20 @@
     spec, configs: input from gyp.
     link_deps: link dependency list; see ComputeDeps()
     """
+    # Libraries (i.e. -lfoo)
+    # These must be included even for static libraries as some of them provide
+    # implicit include paths through the build system.
+    libraries = gyp.common.uniquer(spec.get('libraries', []))
+    static_libs, dynamic_libs, ldflags_libs = self.FilterLibraries(libraries)
+
     if self.type != 'static_library':
       for configname, config in sorted(configs.iteritems()):
         ldflags = list(config.get('ldflags', []))
         self.WriteLn('')
         self.WriteList(ldflags, 'LOCAL_LDFLAGS_%s' % configname)
-      self.WriteLn('\nLOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))')
-
-    # Libraries (i.e. -lfoo)
-    # These must be included even for static libraries as some of them provide
-    # implicit include paths through the build system.
-    libraries = gyp.common.uniquer(spec.get('libraries', []))
-    static_libs, dynamic_libs = self.ComputeAndroidLibraryModuleNames(
-        libraries)
+      self.WriteList(ldflags_libs, 'LOCAL_GYP_LIBS')
+      self.WriteLn('LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION)) '
+                   '$(LOCAL_GYP_LIBS)')
 
     # Link dependencies (i.e. other gyp targets this target depends on)
     # These need not be included for static libraries as within the gyp build
@@ -962,6 +965,7 @@
   builddir_name = generator_flags.get('output_dir', 'out')
   limit_to_target_all = generator_flags.get('limit_to_target_all', False)
   write_alias_targets = generator_flags.get('write_alias_targets', True)
+  sdk_version = generator_flags.get('aosp_sdk_version', 19)
   android_top_dir = os.environ.get('ANDROID_BUILD_TOP')
   assert android_top_dir, '$ANDROID_BUILD_TOP not set; you need to run lunch.'
 
@@ -1058,7 +1062,8 @@
     android_module = writer.Write(qualified_target, relative_target, base_path,
                                   output_file, spec, configs,
                                   part_of_all=part_of_all,
-                                  write_alias_target=write_alias_targets)
+                                  write_alias_target=write_alias_targets,
+                                  sdk_version=sdk_version)
     if android_module in android_modules:
       print ('ERROR: Android module names must be unique. The following '
              'targets both generate Android module name %s.\n  %s\n  %s' %
diff --git a/pylib/gyp/generator/gypd.py b/pylib/gyp/generator/gypd.py
index 22ef57f..874b21a 100644
--- a/pylib/gyp/generator/gypd.py
+++ b/pylib/gyp/generator/gypd.py
@@ -39,9 +39,11 @@
 
 # These variables should just be spit back out as variable references.
 _generator_identity_variables = [
+  'CONFIGURATION_NAME',
   'EXECUTABLE_PREFIX',
   'EXECUTABLE_SUFFIX',
   'INTERMEDIATE_DIR',
+  'LIB_DIR',
   'PRODUCT_DIR',
   'RULE_INPUT_ROOT',
   'RULE_INPUT_DIRNAME',
@@ -49,6 +51,7 @@
   'RULE_INPUT_NAME',
   'RULE_INPUT_PATH',
   'SHARED_INTERMEDIATE_DIR',
+  'SHARED_LIB_DIR',
 ]
 
 # gypd doesn't define a default value for OS like many other generator
diff --git a/pylib/gyp/generator/make.py b/pylib/gyp/generator/make.py
index 8c31d10..e726646 100644
--- a/pylib/gyp/generator/make.py
+++ b/pylib/gyp/generator/make.py
@@ -1138,9 +1138,12 @@
     for output, res in gyp.xcode_emulation.GetMacBundleResources(
         generator_default_variables['PRODUCT_DIR'], self.xcode_settings,
         map(Sourceify, map(self.Absolutify, resources))):
-      self.WriteDoCmd([output], [res], 'mac_tool,,,copy-bundle-resource',
-                      part_of_all=True)
-      bundle_deps.append(output)
+      _, ext = os.path.splitext(output)
+      if ext != '.xcassets':
+        # Make does not supports '.xcassets' emulation.
+        self.WriteDoCmd([output], [res], 'mac_tool,,,copy-bundle-resource',
+                        part_of_all=True)
+        bundle_deps.append(output)
 
 
   def WriteMacInfoPlist(self, bundle_deps):
diff --git a/pylib/gyp/generator/msvs.py b/pylib/gyp/generator/msvs.py
index 80e3104..f529d39 100644
--- a/pylib/gyp/generator/msvs.py
+++ b/pylib/gyp/generator/msvs.py
@@ -83,6 +83,9 @@
     'msvs_external_builder_build_cmd',
     'msvs_external_builder_clean_cmd',
     'msvs_external_builder_clcompile_cmd',
+    'msvs_enable_winrt',
+    'msvs_requires_importlibrary',
+    'msvs_enable_winphone',
 ]
 
 
@@ -1106,7 +1109,8 @@
             for this configuration.
   """
   # Get the information for this configuration
-  include_dirs, resource_include_dirs = _GetIncludeDirs(config)
+  include_dirs, midl_include_dirs, resource_include_dirs = \
+      _GetIncludeDirs(config)
   libraries = _GetLibraries(spec)
   library_dirs = _GetLibraryDirs(config)
   out_file, vc_tool, _ = _GetOutputFilePathAndTool(spec, msbuild=False)
@@ -1134,6 +1138,8 @@
   # Add the information to the appropriate tool
   _ToolAppend(tools, 'VCCLCompilerTool',
               'AdditionalIncludeDirectories', include_dirs)
+  _ToolAppend(tools, 'VCMIDLTool',
+              'AdditionalIncludeDirectories', midl_include_dirs)
   _ToolAppend(tools, 'VCResourceCompilerTool',
               'AdditionalIncludeDirectories', resource_include_dirs)
   # Add in libraries.
@@ -1189,10 +1195,14 @@
   include_dirs = (
       config.get('include_dirs', []) +
       config.get('msvs_system_include_dirs', []))
+  midl_include_dirs = (
+      config.get('midl_include_dirs', []) +
+      config.get('msvs_system_include_dirs', []))
   resource_include_dirs = config.get('resource_include_dirs', include_dirs)
   include_dirs = _FixPaths(include_dirs)
+  midl_include_dirs = _FixPaths(midl_include_dirs)
   resource_include_dirs = _FixPaths(resource_include_dirs)
-  return include_dirs, resource_include_dirs
+  return include_dirs, midl_include_dirs, resource_include_dirs
 
 
 def _GetLibraryDirs(config):
@@ -2595,15 +2605,26 @@
 
 def _GetMSBuildGlobalProperties(spec, guid, gyp_file_name):
   namespace = os.path.splitext(gyp_file_name)[0]
-  return [
+  properties = [
       ['PropertyGroup', {'Label': 'Globals'},
-       ['ProjectGuid', guid],
-       ['Keyword', 'Win32Proj'],
-       ['RootNamespace', namespace],
-       ['IgnoreWarnCompileDuplicatedFilename', 'true'],
+        ['ProjectGuid', guid],
+        ['Keyword', 'Win32Proj'],
+        ['RootNamespace', namespace],
+        ['IgnoreWarnCompileDuplicatedFilename', 'true'],
       ]
-  ]
+    ]
 
+  if spec.get('msvs_enable_winrt'):
+    properties[0].append(['DefaultLanguage', 'en-US'])
+    properties[0].append(['AppContainerApplication', 'true'])
+    properties[0].append(['ApplicationTypeRevision', '8.1'])
+
+    if spec.get('msvs_enable_winphone'):
+      properties[0].append(['ApplicationType', 'Windows Phone'])
+    else:
+      properties[0].append(['ApplicationType', 'Windows Store'])
+
+  return properties
 
 def _GetMSBuildConfigurationDetails(spec, build_file):
   properties = {}
@@ -2614,8 +2635,9 @@
     _AddConditionalProperty(properties, condition, 'ConfigurationType',
                             msbuild_attributes['ConfigurationType'])
     if character_set:
-      _AddConditionalProperty(properties, condition, 'CharacterSet',
-                              character_set)
+      if 'msvs_enable_winrt' not in spec :
+        _AddConditionalProperty(properties, condition, 'CharacterSet',
+                                character_set)
   return _GetMSBuildPropertyGroup(spec, 'Configuration', properties)
 
 
@@ -2914,7 +2936,8 @@
     converted = True
     msvs_settings = configuration.get('msvs_settings', {})
     msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(msvs_settings)
-  include_dirs, resource_include_dirs = _GetIncludeDirs(configuration)
+  include_dirs, midl_include_dirs, resource_include_dirs = \
+      _GetIncludeDirs(configuration)
   libraries = _GetLibraries(spec)
   library_dirs = _GetLibraryDirs(configuration)
   out_file, _, msbuild_tool = _GetOutputFilePathAndTool(spec, msbuild=True)
@@ -2944,6 +2967,8 @@
   # if you don't have any resources.
   _ToolAppend(msbuild_settings, 'ClCompile',
               'AdditionalIncludeDirectories', include_dirs)
+  _ToolAppend(msbuild_settings, 'Midl',
+              'AdditionalIncludeDirectories', midl_include_dirs)
   _ToolAppend(msbuild_settings, 'ResourceCompile',
               'AdditionalIncludeDirectories', resource_include_dirs)
   # Add in libraries, note that even for empty libraries, we want this
@@ -2974,6 +2999,13 @@
                 'PrecompiledHeaderFile', precompiled_header)
     _ToolAppend(msbuild_settings, 'ClCompile',
                 'ForcedIncludeFiles', [precompiled_header])
+  else:
+    _ToolAppend(msbuild_settings, 'ClCompile', 'PrecompiledHeader', 'NotUsing')
+  # Turn off WinRT compilation
+  _ToolAppend(msbuild_settings, 'ClCompile', 'CompileAsWinRT', 'false')
+  # Turn on import libraries if appropriate
+  if spec.get('msvs_requires_importlibrary'):
+   _ToolAppend(msbuild_settings, '', 'IgnoreImportLibrary', 'false')
   # Loadable modules don't generate import libraries;
   # tell dependent projects to not expect one.
   if spec['type'] == 'loadable_module':
@@ -3214,7 +3246,10 @@
   content += _GetMSBuildGlobalProperties(spec, project.guid, project_file_name)
   content += import_default_section
   content += _GetMSBuildConfigurationDetails(spec, project.build_file)
-  content += _GetMSBuildLocalProperties(project.msbuild_toolset)
+  if spec.get('msvs_enable_winphone'):
+   content += _GetMSBuildLocalProperties('v120_wp81')
+  else:
+   content += _GetMSBuildLocalProperties(project.msbuild_toolset)
   content += import_cpp_props_section
   content += _GetMSBuildExtensions(props_files_of_rules)
   content += _GetMSBuildPropertySheets(configurations)
diff --git a/pylib/gyp/generator/ninja.py b/pylib/gyp/generator/ninja.py
index 4484f93..cfb13fc 100644
--- a/pylib/gyp/generator/ninja.py
+++ b/pylib/gyp/generator/ninja.py
@@ -213,7 +213,7 @@
 #   to the input file name as well as the output target name.
 
 class NinjaWriter:
-  def __init__(self, qualified_target, target_outputs, base_dir, build_dir,
+  def __init__(self, hash_for_rules, target_outputs, base_dir, build_dir,
                output_file, toplevel_build, output_file_name, flavor,
                toplevel_dir=None):
     """
@@ -223,7 +223,7 @@
     toplevel_dir: path to the toplevel directory
     """
 
-    self.qualified_target = qualified_target
+    self.hash_for_rules = hash_for_rules
     self.target_outputs = target_outputs
     self.base_dir = base_dir
     self.build_dir = build_dir
@@ -564,9 +564,10 @@
     stamp = self.WriteCollapsedDependencies('actions_rules_copies', outputs)
 
     if self.is_mac_bundle:
-      self.WriteMacBundleResources(
+      xcassets = self.WriteMacBundleResources(
           extra_mac_bundle_resources + mac_bundle_resources, mac_bundle_depends)
-      self.WriteMacInfoPlist(mac_bundle_depends)
+      partial_info_plist = self.WriteMacXCassets(xcassets, mac_bundle_depends)
+      self.WriteMacInfoPlist(partial_info_plist, mac_bundle_depends)
 
     return stamp
 
@@ -591,8 +592,7 @@
     all_outputs = []
     for action in actions:
       # First write out a rule for the action.
-      name = '%s_%s' % (action['action_name'],
-                        hashlib.md5(self.qualified_target).hexdigest())
+      name = '%s_%s' % (action['action_name'], self.hash_for_rules)
       description = self.GenerateDescription('ACTION',
                                              action.get('message', None),
                                              name)
@@ -629,8 +629,7 @@
         continue
 
       # First write out a rule for the rule action.
-      name = '%s_%s' % (rule['rule_name'],
-                        hashlib.md5(self.qualified_target).hexdigest())
+      name = '%s_%s' % (rule['rule_name'], self.hash_for_rules)
 
       args = rule['action']
       description = self.GenerateDescription(
@@ -762,15 +761,66 @@
 
   def WriteMacBundleResources(self, resources, bundle_depends):
     """Writes ninja edges for 'mac_bundle_resources'."""
+    xcassets = []
     for output, res in gyp.xcode_emulation.GetMacBundleResources(
         generator_default_variables['PRODUCT_DIR'],
         self.xcode_settings, map(self.GypPathToNinja, resources)):
       output = self.ExpandSpecial(output)
-      self.ninja.build(output, 'mac_tool', res,
-                       variables=[('mactool_cmd', 'copy-bundle-resource')])
-      bundle_depends.append(output)
+      if os.path.splitext(output)[-1] != '.xcassets':
+        self.ninja.build(output, 'mac_tool', res,
+                         variables=[('mactool_cmd', 'copy-bundle-resource')])
+        bundle_depends.append(output)
+      else:
+        xcassets.append(res)
+    return xcassets
 
-  def WriteMacInfoPlist(self, bundle_depends):
+  def WriteMacXCassets(self, xcassets, bundle_depends):
+    """Writes ninja edges for 'mac_bundle_resources' .xcassets files.
+
+    This add an invocation of 'actool' via the 'mac_tool.py' helper script.
+    It assumes that the assets catalogs define at least one imageset and
+    thus an Assets.car file will be generated in the application resources
+    directory. If this is not the case, then the build will probably be done
+    at each invocation of ninja."""
+    if not xcassets:
+      return
+
+    extra_arguments = {}
+    settings_to_arg = {
+        'XCASSETS_APP_ICON': 'app-icon',
+        'XCASSETS_LAUNCH_IMAGE': 'launch-image',
+    }
+    settings = self.xcode_settings.xcode_settings[self.config_name]
+    for settings_key, arg_name in settings_to_arg.iteritems():
+      value = settings.get(settings_key)
+      if value:
+        extra_arguments[arg_name] = value
+
+    partial_info_plist = None
+    if extra_arguments:
+      partial_info_plist = self.GypPathToUniqueOutput(
+          'assetcatalog_generated_info.plist')
+      extra_arguments['output-partial-info-plist'] = partial_info_plist
+
+    outputs = []
+    outputs.append(
+        os.path.join(
+            self.xcode_settings.GetBundleResourceFolder(),
+            'Assets.car'))
+    if partial_info_plist:
+      outputs.append(partial_info_plist)
+
+    keys = QuoteShellArgument(json.dumps(extra_arguments), self.flavor)
+    extra_env = self.xcode_settings.GetPerTargetSettings()
+    env = self.GetSortedXcodeEnv(additional_settings=extra_env)
+    env = self.ComputeExportEnvString(env)
+
+    bundle_depends.extend(self.ninja.build(
+        outputs, 'compile_xcassets', xcassets,
+        variables=[('env', env), ('keys', keys)]))
+    return partial_info_plist
+
+  def WriteMacInfoPlist(self, partial_info_plist, bundle_depends):
     """Write build rules for bundle Info.plist files."""
     info_plist, out, defines, extra_env = gyp.xcode_emulation.GetMacInfoPlist(
         generator_default_variables['PRODUCT_DIR'],
@@ -790,6 +840,12 @@
     env = self.GetSortedXcodeEnv(additional_settings=extra_env)
     env = self.ComputeExportEnvString(env)
 
+    if partial_info_plist:
+      intermediate_plist = self.GypPathToUniqueOutput('merged_info.plist')
+      info_plist = self.ninja.build(
+          intermediate_plist, 'merge_infoplist',
+          [partial_info_plist, info_plist])
+
     keys = self.xcode_settings.GetExtraPlistItems(self.config_name)
     keys = QuoteShellArgument(json.dumps(keys), self.flavor)
     self.ninja.build(out, 'copy_infoplist', info_plist,
@@ -884,6 +940,14 @@
         [QuoteShellArgument('-I' + self.GypPathToNinja(i, env), self.flavor)
          for i in include_dirs])
 
+    if self.flavor == 'win':
+      midl_include_dirs = config.get('midl_include_dirs', [])
+      midl_include_dirs = self.msvs_settings.AdjustMidlIncludeDirs(
+          midl_include_dirs, config_name)
+      self.WriteVariableList(ninja_file, 'midl_includes',
+          [QuoteShellArgument('-I' + self.GypPathToNinja(i, env), self.flavor)
+           for i in midl_include_dirs])
+
     pch_commands = precompiled_header.GetPchBuildCommands(arch)
     if self.flavor == 'mac':
       # Most targets use no precompiled headers, so only write these if needed.
@@ -1520,12 +1584,13 @@
     generator_extra_sources_for_rules = getattr(xcode_generator,
         'generator_extra_sources_for_rules', [])
   elif flavor == 'win':
+    exts = gyp.MSVSUtil.TARGET_TYPE_EXT
     default_variables.setdefault('OS', 'win')
-    default_variables['EXECUTABLE_SUFFIX'] = '.exe'
+    default_variables['EXECUTABLE_SUFFIX'] = '.' + exts['executable']
     default_variables['STATIC_LIB_PREFIX'] = ''
-    default_variables['STATIC_LIB_SUFFIX'] = '.lib'
+    default_variables['STATIC_LIB_SUFFIX'] = '.' + exts['static_library']
     default_variables['SHARED_LIB_PREFIX'] = ''
-    default_variables['SHARED_LIB_SUFFIX'] = '.dll'
+    default_variables['SHARED_LIB_SUFFIX'] = '.' + exts['shared_library']
 
     # Copy additional generator configuration data from VS, which is shared
     # by the Windows Ninja generator.
@@ -1930,7 +1995,7 @@
       description='IDL $in',
       command=('%s gyp-win-tool midl-wrapper $arch $outdir '
                '$tlb $h $dlldata $iid $proxy $in '
-               '$idlflags' % sys.executable))
+               '$midl_includes $idlflags' % sys.executable))
     master_ninja.rule(
       'rc',
       description='RC $in',
@@ -2108,6 +2173,14 @@
       description='COPY INFOPLIST $in',
       command='$env ./gyp-mac-tool copy-info-plist $in $out $keys')
     master_ninja.rule(
+      'merge_infoplist',
+      description='MERGE INFOPLISTS $in',
+      command='$env ./gyp-mac-tool merge-info-plist $out $in')
+    master_ninja.rule(
+      'compile_xcassets',
+      description='COMPILE XCASSETS $in',
+      command='$env ./gyp-mac-tool compile-xcassets $keys $in')
+    master_ninja.rule(
       'mac_tool',
       description='MACTOOL $mactool_cmd $in',
       command='$env ./gyp-mac-tool $mactool_cmd $in $out')
@@ -2175,6 +2248,10 @@
 
     build_file = gyp.common.RelativePath(build_file, options.toplevel_dir)
 
+    qualified_target_for_hash = gyp.common.QualifiedTarget(build_file, name,
+                                                           toolset)
+    hash_for_rules = hashlib.md5(qualified_target_for_hash).hexdigest()
+
     base_path = os.path.dirname(build_file)
     obj = 'obj'
     if toolset != 'target':
@@ -2182,7 +2259,7 @@
     output_file = os.path.join(obj, base_path, name + '.ninja')
 
     ninja_output = StringIO()
-    writer = NinjaWriter(qualified_target, target_outputs, base_path, build_dir,
+    writer = NinjaWriter(hash_for_rules, target_outputs, base_path, build_dir,
                          ninja_output,
                          toplevel_build, output_file,
                          flavor, toplevel_dir=options.toplevel_dir)
diff --git a/pylib/gyp/generator/xcode.py b/pylib/gyp/generator/xcode.py
index b4d1e19..907e048 100644
--- a/pylib/gyp/generator/xcode.py
+++ b/pylib/gyp/generator/xcode.py
@@ -486,7 +486,7 @@
 def AddSourceToTarget(source, type, pbxp, xct):
   # TODO(mark): Perhaps source_extensions and library_extensions can be made a
   # little bit fancier.
-  source_extensions = ['c', 'cc', 'cpp', 'cxx', 'm', 'mm', 's']
+  source_extensions = ['c', 'cc', 'cpp', 'cxx', 'm', 'mm', 's', 'swift']
 
   # .o is conceptually more of a "source" than a "library," but Xcode thinks
   # of "sources" as things to compile and "libraries" (or "frameworks") as
diff --git a/pylib/gyp/mac_tool.py b/pylib/gyp/mac_tool.py
index 821e291..e5d8a2b 100755
--- a/pylib/gyp/mac_tool.py
+++ b/pylib/gyp/mac_tool.py
@@ -266,6 +266,66 @@
       os.remove(link)
     os.symlink(dest, link)
 
+  def ExecCompileXcassets(self, keys, *inputs):
+    """Compiles multiple .xcassets files into a single .car file.
+
+    This invokes 'actool' to compile all the inputs .xcassets files. The
+    |keys| arguments is a json-encoded dictionary of extra arguments to
+    pass to 'actool' when the asset catalogs contains an application icon
+    or a launch image.
+
+    Note that 'actool' does not create the Assets.car file if the asset
+    catalogs does not contains imageset.
+    """
+    command_line = [
+      'xcrun', 'actool', '--output-format', 'human-readable-text',
+      '--compress-pngs', '--notices', '--warnings', '--errors',
+    ]
+    is_iphone_target = 'IPHONEOS_DEPLOYMENT_TARGET' in os.environ
+    if is_iphone_target:
+      platform = os.environ['CONFIGURATION'].split('-')[-1]
+      if platform not in ('iphoneos', 'iphonesimulator'):
+        platform = 'iphonesimulator'
+      command_line.extend([
+          '--platform', platform, '--target-device', 'iphone',
+          '--target-device', 'ipad', '--minimum-deployment-target',
+          os.environ['IPHONEOS_DEPLOYMENT_TARGET'], '--compile',
+          os.path.abspath(os.environ['CONTENTS_FOLDER_PATH']),
+      ])
+    else:
+      command_line.extend([
+          '--platform', 'macosx', '--target-device', 'mac',
+          '--minimum-deployment-target', os.environ['MACOSX_DEPLOYMENT_TARGET'],
+          '--compile',
+          os.path.abspath(os.environ['UNLOCALIZED_RESOURCES_FOLDER_PATH']),
+      ])
+    if keys:
+      keys = json.loads(keys)
+      for key, value in keys.iteritems():
+        arg_name = '--' + key
+        if isinstance(value, bool):
+          if value:
+            command_line.append(arg_name)
+        elif isinstance(value, list):
+          for v in value:
+            command_line.append(arg_name)
+            command_line.append(str(v))
+        else:
+          command_line.append(arg_name)
+          command_line.append(str(value))
+    # Note: actool crashes if inputs path are relative, so use os.path.abspath
+    # to get absolute path name for inputs.
+    command_line.extend(map(os.path.abspath, inputs))
+    subprocess.check_call(command_line)
+
+  def ExecMergeInfoPlist(self, output, *inputs):
+    """Merge multiple .plist files into a single .plist file."""
+    merged_plist = {}
+    for path in inputs:
+      plist = self._LoadPlistMaybeBinary(path)
+      self._MergePlist(merged_plist, plist)
+    plistlib.writePlist(merged_plist, output)
+
   def ExecCodeSignBundle(self, key, resource_rules, entitlements, provisioning):
     """Code sign a bundle.
 
@@ -402,6 +462,19 @@
           'security', 'cms', '-D', '-i', profile_path, '-o', temp.name])
       return self._LoadPlistMaybeBinary(temp.name)
 
+  def _MergePlist(self, merged_plist, plist):
+    """Merge |plist| into |merged_plist|."""
+    for key, value in plist.iteritems():
+      if isinstance(value, dict):
+        merged_value = merged_plist.get(key, {})
+        if isinstance(merged_value, dict):
+          self._MergePlist(merged_value, value)
+          merged_plist[key] = merged_value
+        else:
+          merged_plist[key] = value
+      else:
+        merged_plist[key] = value
+
   def _LoadPlistMaybeBinary(self, plist_path):
     """Loads into a memory a plist possibly encoded in binary format.
 
diff --git a/pylib/gyp/msvs_emulation.py b/pylib/gyp/msvs_emulation.py
index 5384df1..35cdb34 100644
--- a/pylib/gyp/msvs_emulation.py
+++ b/pylib/gyp/msvs_emulation.py
@@ -13,10 +13,13 @@
 import sys
 
 from gyp.common import OrderedSet
+import gyp.MSVSUtil
 import gyp.MSVSVersion
 
+
 windows_quoter_regex = re.compile(r'(\\*)"')
 
+
 def QuoteForRspFile(arg):
   """Quote a command line argument so that it appears as one argument when
   processed via cmd.exe and parsed by CommandLineToArgvW (as is typical for
@@ -220,6 +223,17 @@
     if unsupported:
       raise Exception('\n'.join(unsupported))
 
+  def GetExtension(self):
+    """Returns the extension for the target, with no leading dot.
+
+    Uses 'product_extension' if specified, otherwise uses MSVS defaults based on
+    the target type.
+    """
+    ext = self.spec.get('product_extension', None)
+    if ext:
+      return ext
+    return gyp.MSVSUtil.TARGET_TYPE_EXT.get(self.spec['type'], '')
+
   def GetVSMacroEnv(self, base_to_build=None, config=None):
     """Get a dict of variables mapping internal VS macro names to their gyp
     equivalents."""
@@ -227,16 +241,22 @@
     target_name = self.spec.get('product_prefix', '') + \
         self.spec.get('product_name', self.spec['target_name'])
     target_dir = base_to_build + '\\' if base_to_build else ''
+    target_ext = '.' + self.GetExtension()
+    target_file_name = target_name + target_ext
+
     replacements = {
-        '$(OutDir)\\': target_dir,
-        '$(TargetDir)\\': target_dir,
-        '$(IntDir)': '$!INTERMEDIATE_DIR',
-        '$(InputPath)': '${source}',
         '$(InputName)': '${root}',
-        '$(ProjectName)': self.spec['target_name'],
-        '$(TargetName)': target_name,
+        '$(InputPath)': '${source}',
+        '$(IntDir)': '$!INTERMEDIATE_DIR',
+        '$(OutDir)\\': target_dir,
         '$(PlatformName)': target_platform,
         '$(ProjectDir)\\': '',
+        '$(ProjectName)': self.spec['target_name'],
+        '$(TargetDir)\\': target_dir,
+        '$(TargetExt)': target_ext,
+        '$(TargetFileName)': target_file_name,
+        '$(TargetName)': target_name,
+        '$(TargetPath)': os.path.join(target_dir, target_file_name),
     }
     replacements.update(GetGlobalVSMacroEnv(self.vs_version))
     return replacements
@@ -318,6 +338,15 @@
       ('VCCLCompilerTool', 'AdditionalIncludeDirectories'), config, default=[]))
     return [self.ConvertVSMacros(p, config=config) for p in includes]
 
+  def AdjustMidlIncludeDirs(self, midl_include_dirs, config):
+    """Updates midl_include_dirs to expand VS specific paths, and adds the
+    system include dirs used for platform SDK and similar."""
+    config = self._TargetConfig(config)
+    includes = midl_include_dirs + self.msvs_system_include_dirs[config]
+    includes.extend(self._Setting(
+      ('VCMIDLTool', 'AdditionalIncludeDirectories'), config, default=[]))
+    return [self.ConvertVSMacros(p, config=config) for p in includes]
+
   def GetComputedDefines(self, config):
     """Returns the set of defines that are injected to the defines list based
     on other VS settings."""
@@ -406,6 +435,8 @@
     cl('WholeProgramOptimization', map={'true': '/GL'})
     cl('WarningLevel', prefix='/W')
     cl('WarnAsError', map={'true': '/WX'})
+    cl('CallingConvention',
+        map={'0': 'd', '1': 'r', '2': 'z'}, prefix='/G')
     cl('DebugInformationFormat',
         map={'1': '7', '3': 'i', '4': 'I'}, prefix='/Z')
     cl('RuntimeTypeInfo', map={'true': '/GR', 'false': '/GR-'})
@@ -476,7 +507,8 @@
     libflags.extend(self._GetAdditionalLibraryDirectories(
         'VCLibrarianTool', config, gyp_to_build_path))
     lib('LinkTimeCodeGeneration', map={'true': '/LTCG'})
-    lib('TargetMachine', map={'1': 'X86', '17': 'X64'}, prefix='/MACHINE:')
+    lib('TargetMachine', map={'1': 'X86', '17': 'X64', '3': 'ARM'},
+        prefix='/MACHINE:')
     lib('AdditionalOptions')
     return libflags
 
@@ -519,7 +551,8 @@
                           'VCLinkerTool', append=ldflags)
     self._GetDefFileAsLdflags(ldflags, gyp_to_build_path)
     ld('GenerateDebugInformation', map={'true': '/DEBUG'})
-    ld('TargetMachine', map={'1': 'X86', '17': 'X64'}, prefix='/MACHINE:')
+    ld('TargetMachine', map={'1': 'X86', '17': 'X64', '3': 'ARM'},
+       prefix='/MACHINE:')
     ldflags.extend(self._GetAdditionalLibraryDirectories(
         'VCLinkerTool', config, gyp_to_build_path))
     ld('DelayLoadDLLs', prefix='/DELAYLOAD:')
diff --git a/pylib/gyp/xcodeproj_file.py b/pylib/gyp/xcodeproj_file.py
index 7c7f1fb..759fdd9 100644
--- a/pylib/gyp/xcodeproj_file.py
+++ b/pylib/gyp/xcodeproj_file.py
@@ -1508,6 +1508,7 @@
         's':           'sourcecode.asm',
         'storyboard':  'file.storyboard',
         'strings':     'text.plist.strings',
+        'swift':       'sourcecode.swift',
         'ttf':         'file',
         'xcassets':    'folder.assetcatalog',
         'xcconfig':    'text.xcconfig',
diff --git a/test/ios/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json b/test/ios/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..2db2b1c
--- /dev/null
+++ b/test/ios/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,58 @@
+{
+  "images" : [
+    {
+      "idiom" : "mac",
+      "size" : "16x16",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "16x16",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "32x32",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "32x32",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "128x128",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "128x128",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "256x256",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "256x256",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "512x512",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "512x512",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json b/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json
new file mode 100644
index 0000000..0a87b6e
--- /dev/null
+++ b/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x",
+      "filename" : "super_sylvain.png"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x",
+      "filename" : "super_sylvain@2x.png"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x",
+      "filename" : "super_sylvain@3x.png"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain.png b/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain.png
new file mode 100644
index 0000000..0ba7691
--- /dev/null
+++ b/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain.png
Binary files differ
diff --git a/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@2x.png b/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@2x.png
new file mode 100644
index 0000000..edfa6a5
--- /dev/null
+++ b/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@2x.png
Binary files differ
diff --git a/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@3x.png b/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@3x.png
new file mode 100644
index 0000000..e0652ef
--- /dev/null
+++ b/test/ios/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@3x.png
Binary files differ
diff --git a/test/ios/app-bundle/test-assets-catalog.gyp b/test/ios/app-bundle/test-assets-catalog.gyp
new file mode 100644
index 0000000..9a12d07
--- /dev/null
+++ b/test/ios/app-bundle/test-assets-catalog.gyp
@@ -0,0 +1,45 @@
+# Copyright (c) 2011 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.
+{
+  'conditions': [
+    ['"<(GENERATOR)"=="ninja"', {
+      'make_global_settings': [
+        ['CC', '/usr/bin/clang'],
+        ['CXX', '/usr/bin/clang++'],
+      ],
+    }],
+  ],
+  'targets': [
+    {
+      'target_name': 'test_app',
+      'product_name': 'Test App Assets Catalog Gyp',
+      'type': 'executable',
+      'mac_bundle': 1,
+      'sources': [
+        'TestApp/main.m',
+      ],
+      'mac_bundle_resources': [
+        'TestApp/English.lproj/InfoPlist.strings',
+        'TestApp/English.lproj/MainMenu.xib',
+        'TestApp/English.lproj/Main_iPhone.storyboard',
+        'TestApp/Images.xcassets',
+      ],
+      'link_settings': {
+        'libraries': [
+          '$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
+          '$(SDKROOT)/System/Library/Frameworks/UIKit.framework',
+        ],
+      },
+      'xcode_settings': {
+        'OTHER_CFLAGS': [
+          '-fobjc-abi-version=2',
+        ],
+        'INFOPLIST_FILE': 'TestApp/TestApp-Info.plist',
+        'SDKROOT': 'iphonesimulator',  # -isysroot
+        'IPHONEOS_DEPLOYMENT_TARGET': '7.0',
+        'CONFIGURATION_BUILD_DIR':'build/Default',
+      },
+    },
+  ],
+}
diff --git a/test/ios/gyptest-app-ios-assets-catalog.py b/test/ios/gyptest-app-ios-assets-catalog.py
new file mode 100755
index 0000000..efd96ac
--- /dev/null
+++ b/test/ios/gyptest-app-ios-assets-catalog.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 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.
+
+"""
+Verifies that ios app bundles are built correctly.
+"""
+
+import TestGyp
+import TestMac
+
+import os.path
+import sys
+
+# Xcode supports for assets catalog was introduced in Xcode 6.0
+if sys.platform == 'darwin' and TestMac.Xcode.Version() >= '0600':
+  test_gyp_path = 'test-assets-catalog.gyp'
+  test_app_path = 'Test App Assets Catalog Gyp.app'
+
+  test = TestGyp.TestGyp(formats=['xcode', 'ninja'])
+  test.run_gyp(test_gyp_path, chdir='app-bundle')
+  test.build(test_gyp_path, test.ALL, chdir='app-bundle')
+
+  # Test that the extension is .bundle
+  test.built_file_must_exist(
+      os.path.join(test_app_path, 'Test App Assets Catalog Gyp'),
+      chdir='app-bundle')
+
+  # Info.plist
+  info_plist = test.built_file_path(
+      os.path.join(test_app_path, 'Info.plist'),
+      chdir='app-bundle')
+  # Resources
+  test.built_file_must_exist(
+      os.path.join(test_app_path, 'English.lproj/InfoPlist.strings'),
+      chdir='app-bundle')
+  test.built_file_must_exist(
+      os.path.join(test_app_path, 'English.lproj/MainMenu.nib'),
+      chdir='app-bundle')
+  test.built_file_must_exist(
+      os.path.join(test_app_path, 'English.lproj/Main_iPhone.storyboardc'),
+      chdir='app-bundle')
+  test.built_file_must_exist(
+      os.path.join(test_app_path, 'Assets.car'),
+      chdir='app-bundle')
+
+  # Packaging
+  test.built_file_must_exist(
+      os.path.join(test_app_path, 'PkgInfo'),
+      chdir='app-bundle')
+  test.built_file_must_match(
+      os.path.join(test_app_path, 'PkgInfo'), 'APPLause',
+      chdir='app-bundle')
+
+  test.pass_test()
diff --git a/test/mac/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json b/test/mac/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..2db2b1c
--- /dev/null
+++ b/test/mac/app-bundle/TestApp/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,58 @@
+{
+  "images" : [
+    {
+      "idiom" : "mac",
+      "size" : "16x16",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "16x16",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "32x32",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "32x32",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "128x128",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "128x128",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "256x256",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "256x256",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "512x512",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "mac",
+      "size" : "512x512",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json b/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json
new file mode 100644
index 0000000..0a87b6e
--- /dev/null
+++ b/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x",
+      "filename" : "super_sylvain.png"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x",
+      "filename" : "super_sylvain@2x.png"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x",
+      "filename" : "super_sylvain@3x.png"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain.png b/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain.png
new file mode 100644
index 0000000..0ba7691
--- /dev/null
+++ b/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain.png
Binary files differ
diff --git a/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@2x.png b/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@2x.png
new file mode 100644
index 0000000..edfa6a5
--- /dev/null
+++ b/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@2x.png
Binary files differ
diff --git a/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@3x.png b/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@3x.png
new file mode 100644
index 0000000..e0652ef
--- /dev/null
+++ b/test/mac/app-bundle/TestApp/Images.xcassets/image.imageset/super_sylvain@3x.png
Binary files differ
diff --git a/test/mac/app-bundle/test-assets-catalog.gyp b/test/mac/app-bundle/test-assets-catalog.gyp
new file mode 100644
index 0000000..25f94a1
--- /dev/null
+++ b/test/mac/app-bundle/test-assets-catalog.gyp
@@ -0,0 +1,43 @@
+# Copyright (c) 2011 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.
+{
+  'targets': [
+    {
+      'target_name': 'dep_framework',
+      'product_name': 'Dependency Framework',
+      'type': 'shared_library',
+      'mac_bundle': 1,
+      'sources': [ 'empty.c', ],
+    },
+    {
+      'target_name': 'test_app',
+      'product_name': 'Test App Assets Catalog Gyp',
+      'type': 'executable',
+      'mac_bundle': 1,
+      'dependencies': [ 'dep_framework', ],
+      'sources': [
+        'TestApp/main.m',
+        'TestApp/TestApp_Prefix.pch',
+        'TestApp/TestAppAppDelegate.h',
+        'TestApp/TestAppAppDelegate.m',
+      ],
+      'mac_bundle_resources': [
+        'TestApp/English.lproj/InfoPlist.strings',  # UTF-8
+        'TestApp/English.lproj/utf-16be.strings',
+        'TestApp/English.lproj/utf-16le.strings',
+        'TestApp/English.lproj/MainMenu.xib',
+        'TestApp/Images.xcassets',
+      ],
+      'link_settings': {
+        'libraries': [
+          '$(SDKROOT)/System/Library/Frameworks/Cocoa.framework',
+        ],
+      },
+      'xcode_settings': {
+        'INFOPLIST_FILE': 'TestApp/TestApp-Info.plist',
+        'MACOSX_DEPLOYMENT_TARGET': '10.9',
+      },
+    },
+  ],
+}
diff --git a/test/mac/gyptest-app-assets-catalog.py b/test/mac/gyptest-app-assets-catalog.py
new file mode 100755
index 0000000..ecb5a78
--- /dev/null
+++ b/test/mac/gyptest-app-assets-catalog.py
@@ -0,0 +1,120 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 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.
+
+"""
+Verifies that app bundles are built correctly.
+"""
+
+import TestGyp
+import TestMac
+
+import os
+import plistlib
+import subprocess
+import sys
+
+
+def ExpectEq(expected, actual):
+  if expected != actual:
+    print >>sys.stderr, 'Expected "%s", got "%s"' % (expected, actual)
+    test.fail_test()
+
+def ls(path):
+  '''Returns a list of all files in a directory, relative to the directory.'''
+  result = []
+  for dirpath, _, files in os.walk(path):
+    for f in files:
+      result.append(os.path.join(dirpath, f)[len(path) + 1:])
+  return result
+
+# Xcode supports for assets catalog was introduced in Xcode 6.0
+if sys.platform == 'darwin' and TestMac.Xcode.Version() >= '0600':
+  test_gyp_path = 'test-assets-catalog.gyp'
+  test_app_path = 'Test App Assets Catalog Gyp.app'
+
+  test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'])
+  test.run_gyp(test_gyp_path, chdir='app-bundle')
+  test.build(test_gyp_path, test.ALL, chdir='app-bundle')
+
+  # Binary
+  test.built_file_must_exist(
+      os.path.join(test_app_path, 'Contents/MacOS/Test App Assets Catalog Gyp'),
+      chdir='app-bundle')
+
+  # Info.plist
+  info_plist = test.built_file_path(
+      os.path.join(test_app_path, 'Contents/Info.plist'),
+      chdir='app-bundle')
+  test.must_exist(info_plist)
+  test.must_contain(
+      info_plist,
+      'com.google.Test-App-Assets-Catalog-Gyp')  # Variable expansion
+  test.must_not_contain(info_plist, '${MACOSX_DEPLOYMENT_TARGET}');
+
+  if test.format != 'make':
+    # TODO: Synthesized plist entries aren't hooked up in the make generator.
+    machine = subprocess.check_output(['sw_vers', '-buildVersion']).rstrip('\n')
+    plist = plistlib.readPlist(info_plist)
+    ExpectEq(machine, plist['BuildMachineOSBuild'])
+
+    expected = ''
+    version = TestMac.Xcode.SDKVersion()
+    expected = 'macosx' + version
+    ExpectEq(expected, plist['DTSDKName'])
+    sdkbuild = TestMac.Xcode.SDKBuild()
+    if not sdkbuild:
+      # Above command doesn't work in Xcode 4.2.
+      sdkbuild = plist['BuildMachineOSBuild']
+    ExpectEq(sdkbuild, plist['DTSDKBuild'])
+    ExpectEq(TestMac.Xcode.Version(), plist['DTXcode'])
+    ExpectEq(TestMac.Xcode.Build(), plist['DTXcodeBuild'])
+
+  # Resources
+  strings_files = ['InfoPlist.strings', 'utf-16be.strings', 'utf-16le.strings']
+  for f in strings_files:
+    strings = test.built_file_path(
+        os.path.join(test_app_path, 'Contents/Resources/English.lproj', f),
+        chdir='app-bundle')
+    test.must_exist(strings)
+    # Xcodes writes UTF-16LE with BOM.
+    contents = open(strings, 'rb').read()
+    if not contents.startswith('\xff\xfe' + '/* Localized'.encode('utf-16le')):
+      test.fail_test()
+
+  test.built_file_must_exist(
+      os.path.join(
+          test_app_path, 'Contents/Resources/English.lproj/MainMenu.nib'),
+      chdir='app-bundle')
+
+  # make does not supports .xcassets files
+  extra_content_files = []
+  if test.format != 'make':
+    extra_content_files = ['Contents/Resources/Assets.car']
+    for f in extra_content_files:
+      test.built_file_must_exist(
+          os.path.join(test_app_path, f),
+          chdir='app-bundle')
+
+  # Packaging
+  test.built_file_must_exist(
+      os.path.join(test_app_path, 'Contents/PkgInfo'),
+      chdir='app-bundle')
+  test.built_file_must_match(
+      os.path.join(test_app_path, 'Contents/PkgInfo'), 'APPLause',
+      chdir='app-bundle')
+
+  # Check that no other files get added to the bundle.
+  if set(ls(test.built_file_path(test_app_path, chdir='app-bundle'))) != \
+     set(['Contents/MacOS/Test App Assets Catalog Gyp',
+          'Contents/Info.plist',
+          'Contents/Resources/English.lproj/MainMenu.nib',
+          'Contents/PkgInfo',
+          ] + extra_content_files +
+         [os.path.join('Contents/Resources/English.lproj', f)
+             for f in strings_files]):
+    test.fail_test()
+
+  test.pass_test()
diff --git a/test/mac/gyptest-swift-library.py b/test/mac/gyptest-swift-library.py
new file mode 100644
index 0000000..7db24c3
--- /dev/null
+++ b/test/mac/gyptest-swift-library.py
@@ -0,0 +1,62 @@
+#!/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.
+
+"""
+Verifies that a swift framework builds correctly.
+"""
+
+import TestGyp
+import TestMac
+
+import collections
+import sys
+import subprocess
+
+if sys.platform == 'darwin':
+  test = TestGyp.TestGyp(formats=['xcode'])
+
+  # Ensures that the given symbol is present in the given file, by running nm.
+  def CheckHasSymbolName(path, symbol):
+    output = subprocess.check_output(['nm', '-j', path])
+    idx = output.find(symbol)
+    if idx == -1:
+      print 'Swift: Could not find symobl: %s' % symbol
+      test.fail_test()
+
+  test_cases = []
+
+  # Run this for iOS on XCode 6.0 or greater
+  if TestMac.Xcode.Version() >= '0600':
+    test_cases.append(('Default', 'iphoneos'))
+    test_cases.append(('Default', 'iphonesimulator'))
+
+  # Run it for Mac on XCode 6.1 or greater
+  if TestMac.Xcode.Version() >= '0610':
+    test_cases.append(('Default', None))
+
+  # Generate the project.
+  test.run_gyp('test.gyp', chdir='swift-library')
+
+  # Build and verify for each configuration.
+  for configuration, sdk in test_cases:
+    kwds = collections.defaultdict(list)
+    if test.format == 'xcode':
+      if sdk is not None:
+        kwds['arguments'].extend(['-sdk', sdk])
+
+    test.set_configuration(configuration)
+    test.build('test.gyp', 'SwiftFramework', chdir='swift-library', **kwds)
+
+    filename = 'SwiftFramework.framework/SwiftFramework'
+    result_file = test.built_file_path(filename, chdir='swift-library')
+
+    test.must_exist(result_file)
+
+    # Check to make sure that our swift class (GypSwiftTest) is present in the
+    # built binary
+    CheckHasSymbolName(result_file, "C14SwiftFramework12GypSwiftTest")
+
+  test.pass_test()
diff --git a/test/mac/swift-library/Info.plist b/test/mac/swift-library/Info.plist
new file mode 100644
index 0000000..804990c
--- /dev/null
+++ b/test/mac/swift-library/Info.plist
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>English</string>
+  <key>CFBundleExecutable</key>
+  <string>${EXECUTABLE_NAME}</string>
+  <key>CFBundleIconFile</key>
+  <string></string>
+  <key>CFBundleIdentifier</key>
+  <string>com.yourcompany.${PRODUCT_NAME:identifier}</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>${PRODUCT_NAME}</string>
+  <key>CFBundlePackageType</key>
+  <string>FMWK</string>
+  <key>CFBundleShortVersionString</key>
+  <string>1.0</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>1</string>
+  <key>NSPrincipalClass</key>
+  <string></string>
+</dict>
+</plist>
diff --git a/test/mac/swift-library/file.swift b/test/mac/swift-library/file.swift
new file mode 100644
index 0000000..88db7da
--- /dev/null
+++ b/test/mac/swift-library/file.swift
@@ -0,0 +1,9 @@
+import Foundation
+
+public class GypSwiftTest {
+  let myProperty = false
+
+  init() {
+    self.myProperty = true
+  }
+}
\ No newline at end of file
diff --git a/test/mac/swift-library/test.gyp b/test/mac/swift-library/test.gyp
new file mode 100644
index 0000000..373a677
--- /dev/null
+++ b/test/mac/swift-library/test.gyp
@@ -0,0 +1,21 @@
+# Copyright (c) 2011 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.
+{
+  'targets': [
+    {
+      'target_name': 'SwiftFramework',
+      'product_name': 'SwiftFramework',
+      'type': 'shared_library',
+      'mac_bundle': 1,
+      'xcode_settings': {
+        'INFOPLIST_FILE': 'Info.plist',
+        'CODE_SIGNING_REQUIRED': 'NO',
+        'CONFIGURATION_BUILD_DIR':'build/Default',
+      },
+      'sources': [
+        'file.swift',
+      ],
+    },
+  ],
+}
diff --git a/test/ninja/action-rule-hash/gyptest-action-rule-hash.py b/test/ninja/action-rule-hash/gyptest-action-rule-hash.py
new file mode 100644
index 0000000..631e176
--- /dev/null
+++ b/test/ninja/action-rule-hash/gyptest-action-rule-hash.py
@@ -0,0 +1,27 @@
+#!/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.
+
+"""
+Verify that running gyp in a different directory does not cause actions and
+rules to rerun.
+"""
+
+import os
+import sys
+import TestGyp
+
+test = TestGyp.TestGyp(formats=['ninja'])
+
+test.run_gyp('subdir/action-rule-hash.gyp')
+test.build('subdir/action-rule-hash.gyp', test.ALL)
+test.up_to_date('subdir/action-rule-hash.gyp')
+
+# Verify that everything is still up-to-date when we re-invoke gyp from a
+# different directory.
+test.run_gyp('action-rule-hash.gyp', '--depth=../', chdir='subdir')
+test.up_to_date('subdir/action-rule-hash.gyp')
+
+test.pass_test()
diff --git a/test/ninja/action-rule-hash/subdir/action-rule-hash.gyp b/test/ninja/action-rule-hash/subdir/action-rule-hash.gyp
new file mode 100644
index 0000000..0e88a30
--- /dev/null
+++ b/test/ninja/action-rule-hash/subdir/action-rule-hash.gyp
@@ -0,0 +1,29 @@
+# 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.
+
+{
+  'targets': [
+    {
+      'target_name': 'program',
+      'type': 'executable',
+      'sources': [
+        '<(INTERMEDIATE_DIR)/main.cc',
+      ],
+      'actions': [
+        {
+          'action_name': 'emit_main_cc',
+          'inputs': ['emit.py'],
+          'outputs': ['<(INTERMEDIATE_DIR)/main.cc'],
+          'action': [
+            'python',
+            'emit.py',
+            '<(INTERMEDIATE_DIR)/main.cc',
+          ],
+          # Allows the test to run without hermetic cygwin on windows.
+          'msvs_cygwin_shell': 0,
+        },
+      ],
+    },
+  ],
+}
diff --git a/test/ninja/action-rule-hash/subdir/emit.py b/test/ninja/action-rule-hash/subdir/emit.py
new file mode 100644
index 0000000..fcb715a
--- /dev/null
+++ b/test/ninja/action-rule-hash/subdir/emit.py
@@ -0,0 +1,13 @@
+#!/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.
+
+import sys
+
+f = open(sys.argv[1], 'wb')
+f.write('int main() {\n')
+f.write('  return 0;\n')
+f.write('}\n')
+f.close()
diff --git a/test/win/compiler-flags/calling-convention-cdecl.def b/test/win/compiler-flags/calling-convention-cdecl.def
new file mode 100644
index 0000000..dc1dba0
--- /dev/null
+++ b/test/win/compiler-flags/calling-convention-cdecl.def
@@ -0,0 +1,6 @@
+; 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.
+
+EXPORTS
+  foo
diff --git a/test/win/compiler-flags/calling-convention-fastcall.def b/test/win/compiler-flags/calling-convention-fastcall.def
new file mode 100644
index 0000000..2c61afe
--- /dev/null
+++ b/test/win/compiler-flags/calling-convention-fastcall.def
@@ -0,0 +1,6 @@
+; 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.
+
+EXPORTS
+  @foo@0
diff --git a/test/win/compiler-flags/calling-convention-stdcall.def b/test/win/compiler-flags/calling-convention-stdcall.def
new file mode 100644
index 0000000..6c7e05e
--- /dev/null
+++ b/test/win/compiler-flags/calling-convention-stdcall.def
@@ -0,0 +1,6 @@
+; 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.
+
+EXPORTS
+  _foo@0
diff --git a/test/win/compiler-flags/calling-convention.cc b/test/win/compiler-flags/calling-convention.cc
new file mode 100644
index 0000000..0d78a0c
--- /dev/null
+++ b/test/win/compiler-flags/calling-convention.cc
@@ -0,0 +1,6 @@
+// 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.
+
+extern "C" void foo() {
+}
diff --git a/test/win/compiler-flags/calling-convention.gyp b/test/win/compiler-flags/calling-convention.gyp
new file mode 100644
index 0000000..e2cdd77
--- /dev/null
+++ b/test/win/compiler-flags/calling-convention.gyp
@@ -0,0 +1,47 @@
+# 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.
+
+{
+ 'targets': [
+    {
+      'target_name': 'test_cdecl',
+      'type': 'loadable_module',
+      'msvs_settings': {
+        'VCCLCompilerTool': {
+          'CallingConvention': 0,
+        },
+      },
+      'sources': [
+        'calling-convention.cc',
+        'calling-convention-cdecl.def',
+      ],
+    },
+    {
+      'target_name': 'test_fastcall',
+      'type': 'loadable_module',
+      'msvs_settings': {
+        'VCCLCompilerTool': {
+          'CallingConvention': 1,
+        },
+      },
+      'sources': [
+        'calling-convention.cc',
+        'calling-convention-fastcall.def',
+      ],
+    },
+    {
+      'target_name': 'test_stdcall',
+      'type': 'loadable_module',
+      'msvs_settings': {
+        'VCCLCompilerTool': {
+          'CallingConvention': 2,
+        },
+      },
+      'sources': [
+        'calling-convention.cc',
+        'calling-convention-stdcall.def',
+      ],
+    },
+  ]
+}
diff --git a/test/win/enable-winrt/dllmain.cc b/test/win/enable-winrt/dllmain.cc
new file mode 100644
index 0000000..dedd83c
--- /dev/null
+++ b/test/win/enable-winrt/dllmain.cc
@@ -0,0 +1,30 @@
+// Copyright (c) 2013 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.
+
+#include <windows.h>
+#include <wrl.h>
+#include <wrl/wrappers/corewrappers.h>
+#include <windows.graphics.display.h>
+
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Graphics::Display;
+
+bool TryToUseSomeWinRT() {
+  ComPtr<IDisplayPropertiesStatics> dp;
+  HStringReference s(RuntimeClass_Windows_Graphics_Display_DisplayProperties);
+  HRESULT hr = GetActivationFactory(s.Get(), dp.GetAddressOf());
+  if (SUCCEEDED(hr)) {
+    float dpi = 96.0f;
+    if (SUCCEEDED(dp->get_LogicalDpi(&dpi))) {
+      return true;
+    }
+  }
+  return false;
+}
+
+BOOL WINAPI DllMain(HINSTANCE hinstance, DWORD reason, LPVOID reserved) {
+  return TRUE;
+}
diff --git a/test/win/enable-winrt/enable-winrt.gyp b/test/win/enable-winrt/enable-winrt.gyp
new file mode 100644
index 0000000..69f7018
--- /dev/null
+++ b/test/win/enable-winrt/enable-winrt.gyp
@@ -0,0 +1,39 @@
+# Copyright (c) 2013 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.
+
+{
+ 'targets': [
+    {
+      'target_name': 'enable_winrt_dll',
+      'type': 'shared_library',
+      'msvs_enable_winrt': 1,
+      'sources': [
+        'dllmain.cc',
+      ],
+    },
+    {
+      'target_name': 'enable_winrt_missing_dll',
+      'type': 'shared_library',
+      'sources': [
+        'dllmain.cc',
+      ],
+    },
+    {
+      'target_name': 'enable_winrt_winphone_dll',
+      'type': 'shared_library',
+      'msvs_enable_winrt': 1,
+      'msvs_enable_winphone': 1,
+      'sources': [
+        'dllmain.cc',
+      ],
+      'msvs_settings': {
+        'VCLinkerTool': {
+          'AdditionalDependencies': [
+            '%(AdditionalDependencies)',
+          ],
+        },
+      },
+    },
+  ]
+}
diff --git a/test/win/gyptest-cl-calling-convention.py b/test/win/gyptest-cl-calling-convention.py
new file mode 100644
index 0000000..b5fdc47
--- /dev/null
+++ b/test/win/gyptest-cl-calling-convention.py
@@ -0,0 +1,22 @@
+#!/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.
+
+"""
+Make sure calling convention setting is extracted properly.
+"""
+
+import TestGyp
+
+import sys
+
+if sys.platform == 'win32':
+  test = TestGyp.TestGyp(formats=['msvs', 'ninja'])
+
+  CHDIR = 'compiler-flags'
+  test.run_gyp('calling-convention.gyp', chdir=CHDIR)
+  test.build('calling-convention.gyp', test.ALL, chdir=CHDIR)
+
+  test.pass_test()
diff --git a/test/win/gyptest-link-enable-winrt.py b/test/win/gyptest-link-enable-winrt.py
new file mode 100644
index 0000000..0c99ca1
--- /dev/null
+++ b/test/win/gyptest-link-enable-winrt.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2013 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.
+
+"""
+Make sure msvs_enable_winrt works correctly.
+"""
+
+import TestGyp
+
+import os
+import sys
+import struct
+
+CHDIR = 'enable-winrt'
+
+if (sys.platform == 'win32' and
+    int(os.environ.get('GYP_MSVS_VERSION', 0)) >= 2013):
+  test = TestGyp.TestGyp(formats=['msvs'])
+
+  test.run_gyp('enable-winrt.gyp', chdir=CHDIR)
+
+  test.build('enable-winrt.gyp', 'enable_winrt_dll', chdir=CHDIR)
+
+  test.build('enable-winrt.gyp', 'enable_winrt_missing_dll', chdir=CHDIR,
+             status=1)
+
+  test.build('enable-winrt.gyp', 'enable_winrt_winphone_dll', chdir=CHDIR)
+
+  test.pass_test()
diff --git a/test/win/gyptest-macro-targetext.py b/test/win/gyptest-macro-targetext.py
new file mode 100644
index 0000000..450710d
--- /dev/null
+++ b/test/win/gyptest-macro-targetext.py
@@ -0,0 +1,26 @@
+#!/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.
+
+"""
+Make sure macro expansion of $(TargetExt) is handled.
+"""
+
+import TestGyp
+
+import sys
+
+if sys.platform == 'win32':
+  test = TestGyp.TestGyp(formats=['msvs', 'ninja'])
+
+  CHDIR = 'vs-macros'
+  test.run_gyp('targetext.gyp', chdir=CHDIR)
+  test.build('targetext.gyp', test.ALL, chdir=CHDIR)
+  test.built_file_must_exist('executable.exe', chdir=CHDIR)
+  test.built_file_must_exist('loadable_module.dll', chdir=CHDIR)
+  test.built_file_must_exist('shared_library.dll', chdir=CHDIR)
+  test.built_file_must_exist('static_library.lib', chdir=CHDIR)
+  test.built_file_must_exist('product_extension.library', chdir=CHDIR)
+  test.pass_test()
diff --git a/test/win/gyptest-macro-targetfilename.py b/test/win/gyptest-macro-targetfilename.py
new file mode 100644
index 0000000..9b8a5c7
--- /dev/null
+++ b/test/win/gyptest-macro-targetfilename.py
@@ -0,0 +1,30 @@
+#!/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.
+
+"""
+Make sure macro expansion of $(TargetFileName) is handled.
+"""
+
+import TestGyp
+
+import sys
+
+if sys.platform == 'win32':
+  test = TestGyp.TestGyp(formats=['msvs', 'ninja'])
+
+  CHDIR = 'vs-macros'
+  test.run_gyp('targetfilename.gyp', chdir=CHDIR)
+  test.build('targetfilename.gyp', test.ALL, chdir=CHDIR)
+  test.built_file_must_exist('test_targetfilename_executable.exe', chdir=CHDIR)
+  test.built_file_must_exist('test_targetfilename_loadable_module.dll',
+                             chdir=CHDIR)
+  test.built_file_must_exist('test_targetfilename_shared_library.dll',
+                             chdir=CHDIR)
+  test.built_file_must_exist('test_targetfilename_static_library.lib',
+                             chdir=CHDIR)
+  test.built_file_must_exist('test_targetfilename_product_extension.foo',
+                             chdir=CHDIR)
+  test.pass_test()
diff --git a/test/win/gyptest-macro-targetpath.py b/test/win/gyptest-macro-targetpath.py
new file mode 100644
index 0000000..fe7eac1
--- /dev/null
+++ b/test/win/gyptest-macro-targetpath.py
@@ -0,0 +1,30 @@
+#!/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.
+
+"""
+Make sure macro expansion of $(TargetPath) is handled.
+"""
+
+import TestGyp
+
+import sys
+
+if sys.platform == 'win32':
+  test = TestGyp.TestGyp(formats=['msvs', 'ninja'])
+
+  CHDIR = 'vs-macros'
+  test.run_gyp('targetpath.gyp', chdir=CHDIR)
+  test.build('targetpath.gyp', test.ALL, chdir=CHDIR)
+  test.built_file_must_exist('test_targetpath_executable.exe', chdir=CHDIR)
+  test.built_file_must_exist('test_targetpath_loadable_module.dll',
+                             chdir=CHDIR)
+  test.built_file_must_exist('test_targetpath_shared_library.dll',
+                             chdir=CHDIR)
+  test.built_file_must_exist('test_targetpath_static_library.lib',
+                             chdir=CHDIR)
+  test.built_file_must_exist('test_targetpath_product_extension.foo',
+                             chdir=CHDIR)
+  test.pass_test()
diff --git a/test/win/gyptest-midl-includedirs.py b/test/win/gyptest-midl-includedirs.py
new file mode 100644
index 0000000..05f6370
--- /dev/null
+++ b/test/win/gyptest-midl-includedirs.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.
+
+"""
+Verify that 'midl_include_dirs' is handled.
+"""
+
+import TestGyp
+
+import sys
+
+if sys.platform == 'win32':
+  test = TestGyp.TestGyp(formats=['msvs', 'ninja'])
+
+  CHDIR = 'idl-includedirs'
+  test.run_gyp('idl-includedirs.gyp', chdir=CHDIR)
+  test.build('idl-includedirs.gyp', test.ALL, chdir=CHDIR)
+  test.pass_test()
diff --git a/test/win/idl-includedirs/hello.cc b/test/win/idl-includedirs/hello.cc
new file mode 100644
index 0000000..9dc3c94
--- /dev/null
+++ b/test/win/idl-includedirs/hello.cc
@@ -0,0 +1,7 @@
+// 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.
+
+int main() {
+  return 0;
+}
diff --git a/test/win/idl-includedirs/idl-includedirs.gyp b/test/win/idl-includedirs/idl-includedirs.gyp
new file mode 100644
index 0000000..fcec063
--- /dev/null
+++ b/test/win/idl-includedirs/idl-includedirs.gyp
@@ -0,0 +1,26 @@
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+  'targets': [
+    {
+      'target_name': 'test_midl_include_dirs',
+      'type': 'executable',
+      'sources': [
+        'hello.cc',
+        'subdir/foo.idl',
+        'subdir/bar.idl',
+      ],
+      'midl_include_dirs': [
+        'subdir',
+      ],
+      'msvs_settings': {
+        'VCMIDLTool': {
+          'OutputDirectory': '<(INTERMEDIATE_DIR)',
+          'DLLDataFileName': '$(InputName)_dlldata.h',
+         },
+      },
+    },
+  ],
+}
diff --git a/test/win/idl-includedirs/subdir/bar.idl b/test/win/idl-includedirs/subdir/bar.idl
new file mode 100644
index 0000000..d4e6cbb
--- /dev/null
+++ b/test/win/idl-includedirs/subdir/bar.idl
@@ -0,0 +1,13 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import "oaidl.idl";
+
+[
+  object,
+  uuid(A03D1421-B1EC-11D0-8C3A-00C04FC31D3F),
+]
+interface Bar : IUnknown {
+  HRESULT BarFunction();
+};
diff --git a/test/win/idl-includedirs/subdir/foo.idl b/test/win/idl-includedirs/subdir/foo.idl
new file mode 100644
index 0000000..c8c65b9
--- /dev/null
+++ b/test/win/idl-includedirs/subdir/foo.idl
@@ -0,0 +1,14 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import "oaidl.idl";
+import "bar.idl";
+
+[
+  object,
+  uuid(9C1100DD-51D4-4827-AE9F-3B8FAC4AED72),
+]
+interface Foo : IUnknown {
+  HRESULT FooFunction(Bar* bar);
+};
diff --git a/test/win/vs-macros/targetext.gyp b/test/win/vs-macros/targetext.gyp
new file mode 100644
index 0000000..11f580e
--- /dev/null
+++ b/test/win/vs-macros/targetext.gyp
@@ -0,0 +1,59 @@
+# 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.
+
+{
+ 'targets': [
+    {
+      'target_name': 'test_targetext_executable',
+      'type': 'executable',
+      'sources': ['hello.cc'],
+      'msvs_settings': {
+        'VCLinkerTool': {
+          'OutputFile': '$(TargetDir)\\executable$(TargetExt)',
+        },
+      },
+    },
+    {
+      'target_name': 'test_targetext_loadable_module',
+      'type': 'loadable_module',
+      'sources': ['hello.cc'],
+      'msvs_settings': {
+        'VCLinkerTool': {
+          'OutputFile': '$(TargetDir)\\loadable_module$(TargetExt)',
+        },
+      },
+    },
+    {
+      'target_name': 'test_targetext_shared_library',
+      'type': 'shared_library',
+      'sources': ['hello.cc'],
+      'msvs_settings': {
+        'VCLinkerTool': {
+          'OutputFile': '$(TargetDir)\\shared_library$(TargetExt)',
+        },
+      },
+    },
+    {
+      'target_name': 'test_targetext_static_library',
+      'type': 'static_library',
+      'sources': ['hello.cc'],
+      'msvs_settings': {
+        'VCLibrarianTool': {
+          'OutputFile': '$(TargetDir)\\static_library$(TargetExt)',
+        },
+      },
+    },
+    {
+      'target_name': 'test_targetext_product_extension',
+      'type': 'executable',
+      'sources': ['hello.cc'],
+      'product_extension': 'library',
+      'msvs_settings': {
+        'VCLinkerTool': {
+          'OutputFile': '$(TargetDir)\\product_extension$(TargetExt)',
+        },
+      },
+    },
+  ]
+}
diff --git a/test/win/vs-macros/targetfilename.gyp b/test/win/vs-macros/targetfilename.gyp
new file mode 100644
index 0000000..8287320
--- /dev/null
+++ b/test/win/vs-macros/targetfilename.gyp
@@ -0,0 +1,59 @@
+# 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.
+
+{
+ 'targets': [
+    {
+      'target_name': 'test_targetfilename_executable',
+      'type': 'executable',
+      'sources': ['hello.cc'],
+      'msvs_settings': {
+        'VCLinkerTool': {
+          'OutputFile': '$(TargetDir)\\$(TargetFileName)',
+        },
+      },
+    },
+    {
+      'target_name': 'test_targetfilename_loadable_module',
+      'type': 'loadable_module',
+      'sources': ['hello.cc'],
+      'msvs_settings': {
+        'VCLinkerTool': {
+          'OutputFile': '$(TargetDir)\\$(TargetFileName)',
+        },
+      },
+    },
+    {
+      'target_name': 'test_targetfilename_shared_library',
+      'type': 'loadable_module',
+      'sources': ['hello.cc'],
+      'msvs_settings': {
+        'VCLinkerTool': {
+          'OutputFile': '$(TargetDir)\\$(TargetFileName)',
+        },
+      },
+    },
+    {
+      'target_name': 'test_targetfilename_static_library',
+      'type': 'static_library',
+      'sources': ['hello.cc'],
+      'msvs_settings': {
+        'VCLibrarianTool': {
+          'OutputFile': '$(TargetDir)\\$(TargetFileName)',
+        },
+      },
+    },
+    {
+      'target_name': 'test_targetfilename_product_extension',
+      'type': 'executable',
+      'sources': ['hello.cc'],
+      'product_extension': 'foo',
+      'msvs_settings': {
+        'VCLinkerTool': {
+          'OutputFile': '$(TargetDir)\\$(TargetFileName)',
+        },
+      },
+    },
+  ]
+}
diff --git a/test/win/vs-macros/targetpath.gyp b/test/win/vs-macros/targetpath.gyp
new file mode 100644
index 0000000..a8699ff
--- /dev/null
+++ b/test/win/vs-macros/targetpath.gyp
@@ -0,0 +1,59 @@
+# 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.
+
+{
+ 'targets': [
+    {
+      'target_name': 'test_targetpath_executable',
+      'type': 'executable',
+      'sources': ['hello.cc'],
+      'msvs_settings': {
+        'VCLinkerTool': {
+          'OutputFile': '$(TargetPath)',
+        },
+      },
+    },
+    {
+      'target_name': 'test_targetpath_loadable_module',
+      'type': 'loadable_module',
+      'sources': ['hello.cc'],
+      'msvs_settings': {
+        'VCLinkerTool': {
+          'OutputFile': '$(TargetPath)',
+        },
+      },
+    },
+    {
+      'target_name': 'test_targetpath_shared_library',
+      'type': 'loadable_module',
+      'sources': ['hello.cc'],
+      'msvs_settings': {
+        'VCLinkerTool': {
+          'OutputFile': '$(TargetPath)',
+        },
+      },
+    },
+    {
+      'target_name': 'test_targetpath_static_library',
+      'type': 'static_library',
+      'sources': ['hello.cc'],
+      'msvs_settings': {
+        'VCLibrarianTool': {
+          'OutputFile': '$(TargetPath)',
+        },
+      },
+    },
+    {
+      'target_name': 'test_targetpath_product_extension',
+      'type': 'executable',
+      'sources': ['hello.cc'],
+      'product_extension': 'foo',
+      'msvs_settings': {
+        'VCLinkerTool': {
+          'OutputFile': '$(TargetPath)',
+        },
+      },
+    },
+  ]
+}