Merge tools/gyp from https://chromium.googlesource.com/external/gyp.git at 487c0b6ae8b44932e45347211bca0e8387718436

This commit was generated by merge_from_chromium.py.

Change-Id: I52ec8f577a9b64496a39bdf9a197e7c527f9356a
diff --git a/buildbot/buildbot_run.py b/buildbot/buildbot_run.py
index 6382707..10460b3 100755
--- a/buildbot/buildbot_run.py
+++ b/buildbot/buildbot_run.py
@@ -229,14 +229,13 @@
   elif sys.platform == 'win32':
     retcode += GypTestFormat('ninja')
     if os.environ['BUILDBOT_BUILDERNAME'] == 'gyp-win64':
-      retcode += GypTestFormat('msvs-ninja-2012', format='msvs-ninja',
-                               msvs_version='2012',
+      retcode += GypTestFormat('msvs-ninja-2013', format='msvs-ninja',
+                               msvs_version='2013',
                                tests=[
                                    'test\generator-output\gyptest-actions.py',
                                    'test\generator-output\gyptest-relocate.py',
                                    'test\generator-output\gyptest-rules.py'])
-      retcode += GypTestFormat('msvs-2010', format='msvs', msvs_version='2010')
-      retcode += GypTestFormat('msvs-2012', format='msvs', msvs_version='2012')
+      retcode += GypTestFormat('msvs-2013', format='msvs', msvs_version='2013')
   else:
     raise Exception('Unknown platform')
   if retcode:
diff --git a/pylib/gyp/generator/msvs.py b/pylib/gyp/generator/msvs.py
index f529d39..28957e5 100644
--- a/pylib/gyp/generator/msvs.py
+++ b/pylib/gyp/generator/msvs.py
@@ -817,10 +817,10 @@
   if rules_external:
     _GenerateExternalRules(rules_external, output_dir, spec,
                            sources, options, actions_to_add)
-  _AdjustSourcesForRules(spec, rules, sources, excluded_sources)
+  _AdjustSourcesForRules(rules, sources, excluded_sources, False)
 
 
-def _AdjustSourcesForRules(spec, rules, sources, excluded_sources):
+def _AdjustSourcesForRules(rules, sources, excluded_sources, is_msbuild):
   # Add outputs generated by each rule (if applicable).
   for rule in rules:
     # Add in the outputs from this rule.
@@ -837,7 +837,7 @@
         outputs = OrderedSet(_FixPaths(outputs))
         inputs.remove(_FixPath(trigger_file))
         sources.update(inputs)
-        if not spec.get('msvs_external_builder'):
+        if not is_msbuild:
           excluded_sources.update(inputs)
         sources.update(outputs)
 
@@ -2013,7 +2013,7 @@
 
 
 def _GenerateMSBuildFiltersFile(filters_path, source_files,
-                                extension_to_rule_name):
+                                rule_dependencies, extension_to_rule_name):
   """Generate the filters file.
 
   This file is used by Visual Studio to organize the presentation of source
@@ -2026,8 +2026,8 @@
   """
   filter_group = []
   source_group = []
-  _AppendFiltersForMSBuild('', source_files, extension_to_rule_name,
-                           filter_group, source_group)
+  _AppendFiltersForMSBuild('', source_files, rule_dependencies,
+                           extension_to_rule_name, filter_group, source_group)
   if filter_group:
     content = ['Project',
                {'ToolsVersion': '4.0',
@@ -2042,7 +2042,7 @@
     os.unlink(filters_path)
 
 
-def _AppendFiltersForMSBuild(parent_filter_name, sources,
+def _AppendFiltersForMSBuild(parent_filter_name, sources, rule_dependencies,
                              extension_to_rule_name,
                              filter_group, source_group):
   """Creates the list of filters and sources to be added in the filter file.
@@ -2068,11 +2068,12 @@
            ['UniqueIdentifier', MSVSNew.MakeGuid(source.name)]])
       # Recurse and add its dependents.
       _AppendFiltersForMSBuild(filter_name, source.contents,
-                               extension_to_rule_name,
+                               rule_dependencies, extension_to_rule_name,
                                filter_group, source_group)
     else:
       # It's a source.  Create a source entry.
-      _, element = _MapFileToMsBuildSourceType(source, extension_to_rule_name)
+      _, element = _MapFileToMsBuildSourceType(source, rule_dependencies,
+                                               extension_to_rule_name)
       source_entry = [element, {'Include': source}]
       # Specify the filter it is part of, if any.
       if parent_filter_name:
@@ -2080,7 +2081,8 @@
       source_group.append(source_entry)
 
 
-def _MapFileToMsBuildSourceType(source, extension_to_rule_name):
+def _MapFileToMsBuildSourceType(source, rule_dependencies,
+                                extension_to_rule_name):
   """Returns the group and element type of the source file.
 
   Arguments:
@@ -2106,6 +2108,9 @@
   elif ext == '.idl':
     group = 'midl'
     element = 'Midl'
+  elif source in rule_dependencies:
+    group = 'rule_dependency'
+    element = 'CustomBuild'
   else:
     group = 'none'
     element = 'None'
@@ -2115,7 +2120,8 @@
 def _GenerateRulesForMSBuild(output_dir, options, spec,
                              sources, excluded_sources,
                              props_files_of_rules, targets_files_of_rules,
-                             actions_to_add, extension_to_rule_name):
+                             actions_to_add, rule_dependencies,
+                             extension_to_rule_name):
   # MSBuild rules are implemented using three files: an XML file, a .targets
   # file and a .props file.
   # See http://blogs.msdn.com/b/vcblog/archive/2010/04/21/quick-help-on-vs2010-custom-build-rule.aspx
@@ -2131,6 +2137,7 @@
       continue
     msbuild_rule = MSBuildRule(rule, spec)
     msbuild_rules.append(msbuild_rule)
+    rule_dependencies.update(msbuild_rule.additional_dependencies.split(';'))
     extension_to_rule_name[msbuild_rule.extension] = msbuild_rule.rule_name
   if msbuild_rules:
     base = spec['target_name'] + options.suffix
@@ -2152,7 +2159,7 @@
   if rules_external:
     _GenerateExternalRules(rules_external, output_dir, spec,
                            sources, options, actions_to_add)
-  _AdjustSourcesForRules(spec, rules, sources, excluded_sources)
+  _AdjustSourcesForRules(rules, sources, excluded_sources, True)
 
 
 class MSBuildRule(object):
@@ -3073,15 +3080,18 @@
   return missing_sources
 
 
-def _GetMSBuildSources(spec, sources, exclusions, extension_to_rule_name,
-                       actions_spec, sources_handled_by_action, list_excluded):
-  groups = ['none', 'midl', 'include', 'compile', 'resource', 'rule']
+def _GetMSBuildSources(spec, sources, exclusions, rule_dependencies,
+                       extension_to_rule_name, actions_spec,
+                       sources_handled_by_action, list_excluded):
+  groups = ['none', 'midl', 'include', 'compile', 'resource', 'rule',
+            'rule_dependency']
   grouped_sources = {}
   for g in groups:
     grouped_sources[g] = []
 
   _AddSources2(spec, sources, exclusions, grouped_sources,
-               extension_to_rule_name, sources_handled_by_action, list_excluded)
+               rule_dependencies, extension_to_rule_name,
+               sources_handled_by_action, list_excluded)
   sources = []
   for g in groups:
     if grouped_sources[g]:
@@ -3092,13 +3102,15 @@
 
 
 def _AddSources2(spec, sources, exclusions, grouped_sources,
-                 extension_to_rule_name, sources_handled_by_action,
+                 rule_dependencies, extension_to_rule_name,
+                 sources_handled_by_action,
                  list_excluded):
   extensions_excluded_from_precompile = []
   for source in sources:
     if isinstance(source, MSVSProject.Filter):
       _AddSources2(spec, source.contents, exclusions, grouped_sources,
-                   extension_to_rule_name, sources_handled_by_action,
+                   rule_dependencies, extension_to_rule_name,
+                   sources_handled_by_action,
                    list_excluded)
     else:
       if not source in sources_handled_by_action:
@@ -3141,7 +3153,7 @@
                 detail.append(['PrecompiledHeader', ''])
                 detail.append(['ForcedIncludeFiles', ''])
 
-        group, element = _MapFileToMsBuildSourceType(source,
+        group, element = _MapFileToMsBuildSourceType(source, rule_dependencies,
                                                      extension_to_rule_name)
         grouped_sources[group].append([element, {'Include': source}] + detail)
 
@@ -3185,6 +3197,7 @@
   actions_to_add = {}
   props_files_of_rules = set()
   targets_files_of_rules = set()
+  rule_dependencies = set()
   extension_to_rule_name = {}
   list_excluded = generator_flags.get('msvs_list_excluded_files', True)
 
@@ -3193,10 +3206,11 @@
     _GenerateRulesForMSBuild(project_dir, options, spec,
                              sources, excluded_sources,
                              props_files_of_rules, targets_files_of_rules,
-                             actions_to_add, extension_to_rule_name)
+                             actions_to_add, rule_dependencies,
+                             extension_to_rule_name)
   else:
     rules = spec.get('rules', [])
-    _AdjustSourcesForRules(spec, rules, sources, excluded_sources)
+    _AdjustSourcesForRules(rules, sources, excluded_sources, True)
 
   sources, excluded_sources, excluded_idl = (
       _AdjustSourcesAndConvertToFilterHierarchy(spec, options,
@@ -3219,6 +3233,7 @@
       spec, actions_to_add)
 
   _GenerateMSBuildFiltersFile(project.path + '.filters', sources,
+                              rule_dependencies,
                               extension_to_rule_name)
   missing_sources = _VerifySourcesExist(sources, project_dir)
 
@@ -3258,8 +3273,8 @@
                                                       project.build_file)
   content += _GetMSBuildToolSettingsSections(spec, configurations)
   content += _GetMSBuildSources(
-      spec, sources, exclusions, extension_to_rule_name, actions_spec,
-      sources_handled_by_action, list_excluded)
+      spec, sources, exclusions, rule_dependencies, extension_to_rule_name,
+      actions_spec, sources_handled_by_action, list_excluded)
   content += _GetMSBuildProjectReferences(project)
   content += import_cpp_targets_section
   content += _GetMSBuildExtensionTargets(targets_files_of_rules)
diff --git a/pylib/gyp/mac_tool.py b/pylib/gyp/mac_tool.py
index e5d8a2b..a25754c 100755
--- a/pylib/gyp/mac_tool.py
+++ b/pylib/gyp/mac_tool.py
@@ -223,11 +223,25 @@
         r'^.*libtool: warning for library: ' +
         r'.* the table of contents is empty ' +
         r'\(no object file members in the library define global symbols\)$')
-    libtoolout = subprocess.Popen(cmd_list, stderr=subprocess.PIPE)
+    env = os.environ.copy()
+    # Ref:
+    # http://www.opensource.apple.com/source/cctools/cctools-809/misc/libtool.c
+    # The problem with this flag is that it resets the file mtime on the file to
+    # epoch=0, e.g. 1970-1-1 or 1969-12-31 depending on daylight saving.
+    env['ZERO_AR_DATE'] = '1'
+    libtoolout = subprocess.Popen(cmd_list, stderr=subprocess.PIPE, env=env)
     _, err = libtoolout.communicate()
     for line in err.splitlines():
       if not libtool_re.match(line) and not libtool_re5.match(line):
         print >>sys.stderr, line
+    # Unconditionally touch any file .a file on the command line if present if
+    # succeeded. A bit hacky.
+    if not libtoolout.returncode:
+      archives = [
+        cmd for cmd in cmd_list if cmd.endswith('.a') and os.path.isfile(cmd)
+      ]
+      if len(archives) == 1:
+        os.utime(archives[0], None)
     return libtoolout.returncode
 
   def ExecPackageFramework(self, framework, version):
diff --git a/test/mac/gyptest-libtool-zero.py b/test/mac/gyptest-libtool-zero.py
new file mode 100644
index 0000000..ae5b7e6
--- /dev/null
+++ b/test/mac/gyptest-libtool-zero.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.
+
+"""
+Verifies libraries have proper mtime.
+"""
+
+import TestGyp
+
+import sys
+
+if sys.platform == 'darwin':
+  test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'])
+
+  CHDIR = 'libtool-zero'
+
+  test.run_gyp('test.gyp', chdir=CHDIR)
+
+  test.build('test.gyp', 'mylib', chdir=CHDIR)
+
+  test.up_to_date('test.gyp', 'mylib', chdir=CHDIR)
+
+  test.pass_test()
diff --git a/test/mac/libtool-zero/mylib.c b/test/mac/libtool-zero/mylib.c
new file mode 100644
index 0000000..b26d61b
--- /dev/null
+++ b/test/mac/libtool-zero/mylib.c
@@ -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 my_foo(int x) {
+  return x + 1;
+}
diff --git a/test/mac/libtool-zero/test.gyp b/test/mac/libtool-zero/test.gyp
new file mode 100644
index 0000000..2f2c3f1
--- /dev/null
+++ b/test/mac/libtool-zero/test.gyp
@@ -0,0 +1,15 @@
+# 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': 'mylib',
+      'type': 'static_library',
+      'sources': [
+        'mylib.c',
+      ],
+    },
+  ],
+}
diff --git a/test/win/gyptest-link-enable-winrt.py b/test/win/gyptest-link-enable-winrt.py
index 0c99ca1..283863c 100644
--- a/test/win/gyptest-link-enable-winrt.py
+++ b/test/win/gyptest-link-enable-winrt.py
@@ -16,6 +16,9 @@
 
 CHDIR = 'enable-winrt'
 
+print 'This test is not currently working on the bots: https://code.google.com/p/gyp/issues/detail?id=466'
+sys.exit(0)
+
 if (sys.platform == 'win32' and
     int(os.environ.get('GYP_MSVS_VERSION', 0)) >= 2013):
   test = TestGyp.TestGyp(formats=['msvs'])
diff --git a/test/win/gyptest-macro-targetfilename.py b/test/win/gyptest-macro-targetfilename.py
index 9b8a5c7..dd5d0d2 100644
--- a/test/win/gyptest-macro-targetfilename.py
+++ b/test/win/gyptest-macro-targetfilename.py
@@ -10,21 +10,23 @@
 
 import TestGyp
 
+import os
 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()
+  if not (test.format == 'msvs' and
+          int(os.environ.get('GYP_MSVS_VERSION', 0)) == 2013):
+    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/tools/emacs/gyp.el b/tools/emacs/gyp.el
index 60619b5..b98b155 100644
--- a/tools/emacs/gyp.el
+++ b/tools/emacs/gyp.el
@@ -23,7 +23,28 @@
                            (buffer-substring-no-properties
                             (line-beginning-position) (line-end-position))))
     (setf (first python-indent-levels)
-          (- (first python-indent-levels) python-indent-offset))))
+          (- (first python-indent-levels) python-continuation-offset))))
+
+(defadvice python-indent-guess-indent-offset (around
+                                              gyp-indent-guess-indent-offset
+                                              activate)
+  "Guess correct indent offset in gyp-mode."
+  (or (and (not (eq major-mode 'gyp-mode))
+           ad-do-it)
+      (save-excursion
+        (save-restriction
+          (widen)
+          (goto-char (point-min))
+          ;; Find first line ending with an opening brace that is not a comment.
+          (or (and (re-search-forward "\\(^[[{]$\\|^.*[^#].*[[{]$\\)")
+                   (forward-line)
+                   (/= (current-indentation) 0)
+                   (set (make-local-variable 'python-indent-offset)
+                        (current-indentation))
+                   (set (make-local-variable 'python-continuation-offset)
+                        (current-indentation)))
+              (message "Can't guess gyp indent offset, using default: %s"
+                       python-continuation-offset))))))
 
 (define-derived-mode gyp-mode python-mode "Gyp"
   "Major mode for editing .gyp files. See http://code.google.com/p/gyp/"
@@ -36,9 +57,10 @@
 
 (defun gyp-set-indentation ()
   "Hook function to configure python indentation to suit gyp mode."
-  (setq python-continuation-offset 2
-        python-indent-offset 2
-        python-indent-guess-indent-offset nil))
+  (set (make-local-variable 'python-indent-offset) 2)
+  (set (make-local-variable 'python-continuation-offset) 2)
+  (set (make-local-variable 'python-indent-guess-indent-offset) t)
+  (python-indent-guess-indent-offset))
 
 (add-hook 'gyp-mode-hook 'gyp-set-indentation)
 
@@ -223,7 +245,7 @@
                                 "copies" "defines" "dependencies" "destination"
                                 "direct_dependent_settings"
                                 "export_dependent_settings" "extension" "files"
-                                "include_dirs" "includes" "inputs" "libraries"
+                                "include_dirs" "includes" "inputs" "ldflags" "libraries"
                                 "link_settings" "mac_bundle" "message"
                                 "msvs_external_rule" "outputs" "product_name"
                                 "process_outputs_as_sources" "rules" "rule_name"