Browse Source

gyp: upgrade to r1103

v0.7.4-release
Ben Noordhuis 13 years ago
parent
commit
e90623edc2
  1. 10
      tools/gyp/PRESUBMIT.py
  2. 2
      tools/gyp/buildbot/buildbot_run.py
  3. 8
      tools/gyp/pylib/gyp/MSVSNew.py
  4. 6
      tools/gyp/pylib/gyp/MSVSProject.py
  5. 1
      tools/gyp/pylib/gyp/MSVSSettings.py
  6. 3
      tools/gyp/pylib/gyp/MSVSSettings_test.py
  7. 2
      tools/gyp/pylib/gyp/MSVSToolFile.py
  8. 2
      tools/gyp/pylib/gyp/MSVSUserFile.py
  9. 6
      tools/gyp/pylib/gyp/MSVSVersion.py
  10. 5
      tools/gyp/pylib/gyp/SCons.py
  11. 36
      tools/gyp/pylib/gyp/__init__.py
  12. 4
      tools/gyp/pylib/gyp/common.py
  13. 2
      tools/gyp/pylib/gyp/easy_xml.py
  14. 2
      tools/gyp/pylib/gyp/easy_xml_test.py
  15. 20
      tools/gyp/pylib/gyp/generator/dump_dependency_json.py
  16. 2
      tools/gyp/pylib/gyp/generator/gypd.py
  17. 2
      tools/gyp/pylib/gyp/generator/gypsh.py
  18. 143
      tools/gyp/pylib/gyp/generator/make.py
  19. 2
      tools/gyp/pylib/gyp/generator/msvs.py
  20. 2
      tools/gyp/pylib/gyp/generator/msvs_test.py
  21. 82
      tools/gyp/pylib/gyp/generator/ninja.py
  22. 2
      tools/gyp/pylib/gyp/generator/scons.py
  23. 4
      tools/gyp/pylib/gyp/generator/xcode.py
  24. 2
      tools/gyp/pylib/gyp/input.py
  25. 5
      tools/gyp/pylib/gyp/mac_tool.py
  26. 2
      tools/gyp/pylib/gyp/ninja_syntax.py
  27. 49
      tools/gyp/pylib/gyp/sun_tool.py
  28. 10
      tools/gyp/pylib/gyp/system_test.py
  29. 8
      tools/gyp/pylib/gyp/xcodeproj_file.py
  30. 1
      tools/gyp/pylib/gyp/xml_fix.py
  31. 307
      tools/gyp/pylintrc
  32. 23
      tools/gyp/test/actions-bare/gyptest-bare.py
  33. 25
      tools/gyp/test/actions-bare/src/bare.gyp
  34. 11
      tools/gyp/test/actions-bare/src/bare.py
  35. 42
      tools/gyp/test/actions-multiple/gyptest-all.py
  36. 165
      tools/gyp/test/actions-multiple/src/actions.gyp
  37. 9
      tools/gyp/test/actions-multiple/src/copy.py
  38. 12
      tools/gyp/test/actions-multiple/src/filter.py
  39. 11
      tools/gyp/test/actions-multiple/src/foo.c
  40. 1
      tools/gyp/test/actions-multiple/src/input.txt
  41. 22
      tools/gyp/test/actions-multiple/src/main.c
  42. 26
      tools/gyp/test/actions-subdir/gyptest-action.py
  43. 11
      tools/gyp/test/actions-subdir/src/make-file.py
  44. 31
      tools/gyp/test/actions-subdir/src/none.gyp
  45. 11
      tools/gyp/test/actions-subdir/src/subdir/make-subdir-file.py
  46. 28
      tools/gyp/test/actions-subdir/src/subdir/subdir.gyp
  47. 101
      tools/gyp/test/actions/gyptest-all.py
  48. 68
      tools/gyp/test/actions/gyptest-default.py
  49. 24
      tools/gyp/test/actions/gyptest-errors.py
  50. 24
      tools/gyp/test/actions/src/action_missing_name.gyp
  51. 114
      tools/gyp/test/actions/src/actions.gyp
  52. 21
      tools/gyp/test/actions/src/confirm-dep-files.py
  53. 46
      tools/gyp/test/actions/src/subdir1/counter.py
  54. 74
      tools/gyp/test/actions/src/subdir1/executable.gyp
  55. 20
      tools/gyp/test/actions/src/subdir1/make-prog1.py
  56. 20
      tools/gyp/test/actions/src/subdir1/make-prog2.py
  57. 12
      tools/gyp/test/actions/src/subdir1/program.c
  58. 11
      tools/gyp/test/actions/src/subdir2/make-file.py
  59. 33
      tools/gyp/test/actions/src/subdir2/none.gyp
  60. 21
      tools/gyp/test/actions/src/subdir3/generate_main.py
  61. 29
      tools/gyp/test/actions/src/subdir3/null_input.gyp
  62. 55
      tools/gyp/test/additional-targets/gyptest-additional.py
  63. 13
      tools/gyp/test/additional-targets/src/all.gyp
  64. 56
      tools/gyp/test/additional-targets/src/dir1/actions.gyp
  65. 11
      tools/gyp/test/additional-targets/src/dir1/emit.py
  66. 6
      tools/gyp/test/additional-targets/src/dir1/lib1.c
  67. 31
      tools/gyp/test/assembly/gyptest-assembly.py
  68. 4
      tools/gyp/test/assembly/src/as.bat
  69. 59
      tools/gyp/test/assembly/src/assembly.gyp
  70. 10
      tools/gyp/test/assembly/src/lib1.S
  71. 3
      tools/gyp/test/assembly/src/lib1.c
  72. 12
      tools/gyp/test/assembly/src/program.c
  73. 77
      tools/gyp/test/builddir/gyptest-all.py
  74. 77
      tools/gyp/test/builddir/gyptest-default.py
  75. 21
      tools/gyp/test/builddir/src/builddir.gypi
  76. 6
      tools/gyp/test/builddir/src/func1.c
  77. 6
      tools/gyp/test/builddir/src/func2.c
  78. 6
      tools/gyp/test/builddir/src/func3.c
  79. 6
      tools/gyp/test/builddir/src/func4.c
  80. 6
      tools/gyp/test/builddir/src/func5.c
  81. 10
      tools/gyp/test/builddir/src/prog1.c
  82. 30
      tools/gyp/test/builddir/src/prog1.gyp
  83. 10
      tools/gyp/test/builddir/src/subdir2/prog2.c
  84. 19
      tools/gyp/test/builddir/src/subdir2/prog2.gyp
  85. 10
      tools/gyp/test/builddir/src/subdir2/subdir3/prog3.c
  86. 19
      tools/gyp/test/builddir/src/subdir2/subdir3/prog3.gyp
  87. 10
      tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/prog4.c
  88. 19
      tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/prog4.gyp
  89. 10
      tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.c
  90. 19
      tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.gyp
  91. 15
      tools/gyp/test/cflags/cflags.c
  92. 16
      tools/gyp/test/cflags/cflags.gyp
  93. 65
      tools/gyp/test/cflags/gyptest-cflags.py
  94. 29
      tools/gyp/test/compilable/gyptest-headers.py
  95. 26
      tools/gyp/test/compilable/src/headers.gyp
  96. 7
      tools/gyp/test/compilable/src/lib1.cpp
  97. 6
      tools/gyp/test/compilable/src/lib1.hpp
  98. 9
      tools/gyp/test/compilable/src/program.cpp
  99. 15
      tools/gyp/test/configurations/basics/configurations.c
  100. 32
      tools/gyp/test/configurations/basics/configurations.gyp

10
tools/gyp/PRESUBMIT.py

@ -34,6 +34,16 @@ def CheckChangeOnCommit(input_api, output_api):
input_api, output_api, input_api, output_api,
'http://gyp-status.appspot.com/status', 'http://gyp-status.appspot.com/status',
'http://gyp-status.appspot.com/current')) 'http://gyp-status.appspot.com/current'))
import sys
old_sys_path = sys.path
try:
sys.path = ['pylib', 'test/lib'] + sys.path
report.extend(input_api.canned_checks.RunPylint(
input_api,
output_api))
finally:
sys.path = old_sys_path
return report return report

2
tools/gyp/buildbot/buildbot_run.py

@ -1,4 +1,4 @@
#!/usr/bin/python #!/usr/bin/env python
# Copyright (c) 2011 Google Inc. All rights reserved. # Copyright (c) 2011 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.

8
tools/gyp/pylib/gyp/MSVSNew.py

@ -1,6 +1,4 @@
#!/usr/bin/python2.4 # Copyright (c) 2011 Google Inc. All rights reserved.
# Copyright (c) 2009 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
@ -62,7 +60,7 @@ def MakeGuid(name, seed='msvs_new'):
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
class MSVSFolder: class MSVSFolder(object):
"""Folder in a Visual Studio project or solution.""" """Folder in a Visual Studio project or solution."""
def __init__(self, path, name = None, entries = None, def __init__(self, path, name = None, entries = None,
@ -103,7 +101,7 @@ class MSVSFolder:
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
class MSVSProject: class MSVSProject(object):
"""Visual Studio project.""" """Visual Studio project."""
def __init__(self, path, name = None, dependencies = None, guid = None, def __init__(self, path, name = None, dependencies = None, guid = None,

6
tools/gyp/pylib/gyp/MSVSProject.py

@ -1,6 +1,4 @@
#!/usr/bin/python2.4 # Copyright (c) 2011 Google Inc. All rights reserved.
# Copyright (c) 2009 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
@ -208,5 +206,3 @@ class Writer(object):
] ]
easy_xml.WriteXmlIfChanged(content, self.project_path, easy_xml.WriteXmlIfChanged(content, self.project_path,
encoding="Windows-1252") encoding="Windows-1252")
#------------------------------------------------------------------------------

1
tools/gyp/pylib/gyp/MSVSSettings.py

@ -1,4 +1,3 @@
#!/usr/bin/python
# Copyright (c) 2011 The Chromium Authors. All rights reserved. # Copyright (c) 2011 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.

3
tools/gyp/pylib/gyp/MSVSSettings_test.py

@ -1,4 +1,4 @@
#!/usr/bin/python #!/usr/bin/env python
# Copyright (c) 2011 Google Inc. All rights reserved. # Copyright (c) 2011 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
@ -1476,5 +1476,6 @@ class TestSequenceFunctions(unittest.TestCase):
self.assertEqual(expected_msbuild_settings, actual_msbuild_settings) self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
self._ExpectedWarnings([]) self._ExpectedWarnings([])
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

2
tools/gyp/pylib/gyp/MSVSToolFile.py

@ -1,5 +1,3 @@
#!/usr/bin/python2.4
# Copyright (c) 2009 Google Inc. All rights reserved. # Copyright (c) 2009 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.

2
tools/gyp/pylib/gyp/MSVSUserFile.py

@ -1,5 +1,3 @@
#!/usr/bin/python2.4
# Copyright (c) 2009 Google Inc. All rights reserved. # Copyright (c) 2009 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.

6
tools/gyp/pylib/gyp/MSVSVersion.py

@ -1,4 +1,3 @@
#!/usr/bin/python
# Copyright (c) 2011 The Chromium Authors. All rights reserved. # Copyright (c) 2011 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
@ -12,7 +11,7 @@ import subprocess
import sys import sys
class VisualStudioVersion: class VisualStudioVersion(object):
"""Information regarding a version of Visual Studio.""" """Information regarding a version of Visual Studio."""
def __init__(self, short_name, description, def __init__(self, short_name, description,
@ -80,6 +79,7 @@ def _RegistryQueryBase(sysdir, key, value):
return None return None
return text return text
def _RegistryQuery(key, value=None): def _RegistryQuery(key, value=None):
"""Use reg.exe to read a particular key through _RegistryQueryBase. """Use reg.exe to read a particular key through _RegistryQueryBase.
@ -107,6 +107,7 @@ def _RegistryQuery(key, value=None):
raise raise
return text return text
def _RegistryGetValue(key, value): def _RegistryGetValue(key, value):
"""Use reg.exe to obtain the value of a registry key. """Use reg.exe to obtain the value of a registry key.
@ -125,6 +126,7 @@ def _RegistryGetValue(key, value):
return None return None
return match.group(1) return match.group(1)
def _RegistryKeyExists(key): def _RegistryKeyExists(key):
"""Use reg.exe to see if a key exists. """Use reg.exe to see if a key exists.

5
tools/gyp/pylib/gyp/SCons.py

@ -1,6 +1,4 @@
#!/usr/bin/env python # Copyright (c) 2011 Google Inc. All rights reserved.
# Copyright (c) 2009 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
@ -196,5 +194,6 @@ TargetMap = {
'loadable_module' : LoadableModuleTarget, 'loadable_module' : LoadableModuleTarget,
} }
def Target(spec): def Target(spec):
return TargetMap[spec.get('type')](spec) return TargetMap[spec.get('type')](spec)

36
tools/gyp/pylib/gyp/__init__.py

@ -1,4 +1,4 @@
#!/usr/bin/python #!/usr/bin/env python
# Copyright (c) 2011 Google Inc. All rights reserved. # Copyright (c) 2011 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
@ -11,6 +11,7 @@ import os.path
import re import re
import shlex import shlex
import sys import sys
import traceback
# Default debug modes for GYP # Default debug modes for GYP
debug = {} debug = {}
@ -20,9 +21,18 @@ DEBUG_GENERAL = 'general'
DEBUG_VARIABLES = 'variables' DEBUG_VARIABLES = 'variables'
DEBUG_INCLUDES = 'includes' DEBUG_INCLUDES = 'includes'
def DebugOutput(mode, message): def DebugOutput(mode, message):
if mode in gyp.debug.keys(): if 'all' in gyp.debug.keys() or mode in gyp.debug.keys():
print "%s: %s" % (mode.upper(), message) ctx = ('unknown', 0, 'unknown')
try:
f = traceback.extract_stack(limit=2)
if f:
ctx = f[0][:3]
except:
pass
print '%s:%s:%d:%s %s' % (mode.upper(), os.path.basename(ctx[0]),
ctx[1], ctx[2], message)
def FindBuildFiles(): def FindBuildFiles():
extension = '.gyp' extension = '.gyp'
@ -266,8 +276,8 @@ def main(args):
help='set DEPTH gyp variable to a relative path to PATH') help='set DEPTH gyp variable to a relative path to PATH')
parser.add_option('-d', '--debug', dest='debug', metavar='DEBUGMODE', parser.add_option('-d', '--debug', dest='debug', metavar='DEBUGMODE',
action='append', default=[], help='turn on a debugging ' action='append', default=[], help='turn on a debugging '
'mode for debugging GYP. Supported modes are "variables" ' 'mode for debugging GYP. Supported modes are "variables", '
'and "general"') '"includes" and "general" or "all" for all of them.')
parser.add_option('-S', '--suffix', dest='suffix', default='', parser.add_option('-S', '--suffix', dest='suffix', default='',
help='suffix to add to generated files') help='suffix to add to generated files')
parser.add_option('-G', dest='generator_flags', action='append', default=[], parser.add_option('-G', dest='generator_flags', action='append', default=[],
@ -327,16 +337,12 @@ def main(args):
options.formats = generate_formats options.formats = generate_formats
else: else:
# Nothing in the variable, default based on platform. # Nothing in the variable, default based on platform.
options.formats = [ {'darwin': 'xcode', if sys.platform == 'darwin':
'win32': 'msvs', options.formats = ['xcode']
'cygwin': 'msvs', elif sys.platform in ('win32', 'cygwin'):
'freebsd7': 'make', options.formats = ['msvs']
'freebsd8': 'make', else:
'linux2': 'make', options.formats = ['make']
'linux3': 'make',
'openbsd4': 'make',
'openbsd5': 'make',
'sunos5': 'make',}[sys.platform] ]
if not options.generator_output and options.use_environment: if not options.generator_output and options.use_environment:
g_o = os.environ.get('GYP_GENERATOR_OUTPUT') g_o = os.environ.get('GYP_GENERATOR_OUTPUT')

4
tools/gyp/pylib/gyp/common.py

@ -1,6 +1,4 @@
#!/usr/bin/python # Copyright (c) 2011 Google Inc. All rights reserved.
# Copyright (c) 2009 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.

2
tools/gyp/pylib/gyp/easy_xml.py

@ -1,5 +1,3 @@
#!/usr/bin/python
# Copyright (c) 2011 Google Inc. All rights reserved. # Copyright (c) 2011 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.

2
tools/gyp/pylib/gyp/easy_xml_test.py

@ -1,4 +1,4 @@
#!/usr/bin/python #!/usr/bin/env python
# Copyright (c) 2011 Google Inc. All rights reserved. # Copyright (c) 2011 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be

20
tools/gyp/pylib/gyp/generator/dump_dependency_json.py

@ -1,5 +1,3 @@
#!/usr/bin/python
# Copyright (c) 2011 Google Inc. All rights reserved. # Copyright (c) 2011 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
@ -8,18 +6,18 @@ import collections
import gyp import gyp
import gyp.common import gyp.common
import json import json
import sys
generator_wants_static_library_dependencies_adjusted = False generator_wants_static_library_dependencies_adjusted = False
generator_default_variables = { generator_default_variables = {
'OS': 'linux',
} }
for dirname in ['INTERMEDIATE_DIR', 'SHARED_INTERMEDIATE_DIR', 'PRODUCT_DIR', for dirname in ['INTERMEDIATE_DIR', 'SHARED_INTERMEDIATE_DIR', 'PRODUCT_DIR',
'LIB_DIR', 'SHARED_LIB_DIR']: 'LIB_DIR', 'SHARED_LIB_DIR']:
# Some gyp steps fail if these are empty(!). # Some gyp steps fail if these are empty(!).
generator_default_variables[dirname] = 'dir' generator_default_variables[dirname] = 'dir'
for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME', for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME',
'RULE_INPUT_EXT', 'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT',
'EXECUTABLE_PREFIX', 'EXECUTABLE_SUFFIX', 'EXECUTABLE_PREFIX', 'EXECUTABLE_SUFFIX',
'STATIC_LIB_PREFIX', 'STATIC_LIB_SUFFIX', 'STATIC_LIB_PREFIX', 'STATIC_LIB_SUFFIX',
'SHARED_LIB_PREFIX', 'SHARED_LIB_SUFFIX', 'SHARED_LIB_PREFIX', 'SHARED_LIB_SUFFIX',
@ -27,9 +25,21 @@ for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME',
generator_default_variables[unused] = '' generator_default_variables[unused] = ''
def GetFlavor(params):
"""Returns |params.flavor| if it's set, the system's default flavor else."""
flavors = {
'darwin': 'mac',
'sunos5': 'solaris',
'freebsd7': 'freebsd',
'freebsd8': 'freebsd',
}
flavor = flavors.get(sys.platform, 'linux')
return params.get('flavor', flavor)
def CalculateVariables(default_variables, params): def CalculateVariables(default_variables, params):
generator_flags = params.get('generator_flags', {}) generator_flags = params.get('generator_flags', {})
default_variables['OS'] = generator_flags.get('os', 'linux') default_variables['OS'] = generator_flags.get('os', GetFlavor(params))
def CalculateGeneratorInputInfo(params): def CalculateGeneratorInputInfo(params):

2
tools/gyp/pylib/gyp/generator/gypd.py

@ -1,5 +1,3 @@
#!/usr/bin/python
# Copyright (c) 2011 Google Inc. All rights reserved. # Copyright (c) 2011 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.

2
tools/gyp/pylib/gyp/generator/gypsh.py

@ -1,5 +1,3 @@
#!/usr/bin/python
# Copyright (c) 2011 Google Inc. All rights reserved. # Copyright (c) 2011 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.

143
tools/gyp/pylib/gyp/generator/make.py

@ -1,5 +1,3 @@
#!/usr/bin/python
# Copyright (c) 2011 Google Inc. All rights reserved. # Copyright (c) 2011 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
@ -26,21 +24,18 @@
import gyp import gyp
import gyp.common import gyp.common
import gyp.system_test import gyp.system_test
import os.path
import os import os
import re
import shlex
import sys import sys
# Debugging-related imports -- remove me once we're solid.
import code
import pprint
generator_default_variables = { generator_default_variables = {
'EXECUTABLE_PREFIX': '', 'EXECUTABLE_PREFIX': '',
'EXECUTABLE_SUFFIX': '', 'EXECUTABLE_SUFFIX': '',
'STATIC_LIB_PREFIX': 'lib', 'STATIC_LIB_PREFIX': 'lib',
'SHARED_LIB_PREFIX': 'lib', 'SHARED_LIB_PREFIX': 'lib',
'STATIC_LIB_SUFFIX': '.a', 'STATIC_LIB_SUFFIX': '.a',
'INTERMEDIATE_DIR': '$(obj).$(TOOLSET)/geni', 'INTERMEDIATE_DIR': '$(obj).$(TOOLSET)/$(TARGET)/geni',
'SHARED_INTERMEDIATE_DIR': '$(obj)/gen', 'SHARED_INTERMEDIATE_DIR': '$(obj)/gen',
'PRODUCT_DIR': '$(builddir)', 'PRODUCT_DIR': '$(builddir)',
'RULE_INPUT_ROOT': '%(INPUT_ROOT)s', # This gets expanded by Python. 'RULE_INPUT_ROOT': '%(INPUT_ROOT)s', # This gets expanded by Python.
@ -452,10 +447,10 @@ $(if $(or $(command_changed),$(prereq_changed)),
) )
endef endef
# Declare "all" target first so it is the default, even though we don't have the # Declare the "%(default_target)s" target first so it is the default,
# deps yet. # even though we don't have the deps yet.
.PHONY: all .PHONY: %(default_target)s
all: %(default_target)s:
# Use FORCE_DO_CMD to force a target to run. Should be coupled with # Use FORCE_DO_CMD to force a target to run. Should be coupled with
# do_cmd. # do_cmd.
@ -489,6 +484,9 @@ cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@"
quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@ quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@
cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4) cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4)
quiet_cmd_infoplist = INFOPLIST $@
cmd_infoplist = $(CC.$(TOOLSET)) -E -P -Wno-trigraphs -x c $(INFOPLIST_DEFINES) "$<" -o "$@"
""" """
SHARED_HEADER_SUN_COMMANDS = """ SHARED_HEADER_SUN_COMMANDS = """
@ -901,8 +899,6 @@ class XcodeSettings(object):
self._WarnUnimplemented('GCC_DEBUGGING_SYMBOLS') self._WarnUnimplemented('GCC_DEBUGGING_SYMBOLS')
self._WarnUnimplemented('GCC_ENABLE_OBJC_EXCEPTIONS') self._WarnUnimplemented('GCC_ENABLE_OBJC_EXCEPTIONS')
self._WarnUnimplemented('GCC_ENABLE_OBJC_GC') self._WarnUnimplemented('GCC_ENABLE_OBJC_GC')
self._WarnUnimplemented('INFOPLIST_PREPROCESS')
self._WarnUnimplemented('INFOPLIST_PREPROCESSOR_DEFINITIONS')
# TODO: This is exported correctly, but assigning to it is not supported. # TODO: This is exported correctly, but assigning to it is not supported.
self._WarnUnimplemented('MACH_O_TYPE') self._WarnUnimplemented('MACH_O_TYPE')
@ -917,7 +913,7 @@ class XcodeSettings(object):
config = self.spec['configurations'][self.configname] config = self.spec['configurations'][self.configname]
framework_dirs = config.get('mac_framework_dirs', []) framework_dirs = config.get('mac_framework_dirs', [])
for directory in framework_dirs: for directory in framework_dirs:
cflags.append('-F ' + os.path.join(sdk_root, directory)) cflags.append('-F ' + directory.replace('$(SDKROOT)', sdk_root))
self.configname = None self.configname = None
return cflags return cflags
@ -1499,6 +1495,12 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
cd_action = 'cd %s; ' % Sourceify(self.path or '.') cd_action = 'cd %s; ' % Sourceify(self.path or '.')
# command and cd_action get written to a toplevel variable called
# cmd_foo. Toplevel variables can't handle things that change per
# makefile like $(TARGET), so hardcode the target.
command = command.replace('$(TARGET)', self.target)
cd_action = cd_action.replace('$(TARGET)', self.target)
# Set LD_LIBRARY_PATH in case the action runs an executable from this # Set LD_LIBRARY_PATH in case the action runs an executable from this
# build which links to shared libs from this build. # build which links to shared libs from this build.
# actions run on the host, so they should in theory only use host # actions run on the host, so they should in theory only use host
@ -1618,6 +1620,15 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
if len(dirs) > 0: if len(dirs) > 0:
mkdirs = 'mkdir -p %s; ' % ' '.join(dirs) mkdirs = 'mkdir -p %s; ' % ' '.join(dirs)
cd_action = 'cd %s; ' % Sourceify(self.path or '.') cd_action = 'cd %s; ' % Sourceify(self.path or '.')
# action, cd_action, and mkdirs get written to a toplevel variable
# called cmd_foo. Toplevel variables can't handle things that change
# per makefile like $(TARGET), so hardcode the target.
action = gyp.common.EncodePOSIXShellList(action)
action = action.replace('$(TARGET)', self.target)
cd_action = cd_action.replace('$(TARGET)', self.target)
mkdirs = mkdirs.replace('$(TARGET)', self.target)
# Set LD_LIBRARY_PATH in case the rule runs an executable from this # Set LD_LIBRARY_PATH in case the rule runs an executable from this
# build which links to shared libs from this build. # build which links to shared libs from this build.
# rules run on the host, so they should in theory only use host # rules run on the host, so they should in theory only use host
@ -1629,7 +1640,7 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
"$(builddir)/lib.host:$(builddir)/lib.target:$$LD_LIBRARY_PATH; " "$(builddir)/lib.host:$(builddir)/lib.target:$$LD_LIBRARY_PATH; "
"export LD_LIBRARY_PATH; " "export LD_LIBRARY_PATH; "
"%(cd_action)s%(mkdirs)s%(action)s" % { "%(cd_action)s%(mkdirs)s%(action)s" % {
'action': gyp.common.EncodePOSIXShellList(action), 'action': action,
'cd_action': cd_action, 'cd_action': cd_action,
'count': count, 'count': count,
'mkdirs': mkdirs, 'mkdirs': mkdirs,
@ -1666,6 +1677,7 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
outputs = [] outputs = []
for copy in copies: for copy in copies:
for path in copy['files']: for path in copy['files']:
# Absolutify() calls normpath, stripping trailing slashes.
path = Sourceify(self.Absolutify(path)) path = Sourceify(self.Absolutify(path))
filename = os.path.split(path)[1] filename = os.path.split(path)[1]
output = Sourceify(self.Absolutify(os.path.join(copy['destination'], output = Sourceify(self.Absolutify(os.path.join(copy['destination'],
@ -1731,10 +1743,29 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
assert ' ' not in info_plist, ( assert ' ' not in info_plist, (
"Spaces in resource filenames not supported (%s)" % info_plist) "Spaces in resource filenames not supported (%s)" % info_plist)
info_plist = self.Absolutify(info_plist) info_plist = self.Absolutify(info_plist)
settings = self.xcode_settings
# If explicilty set to preprocess the plist, invoke the C preprocessor and
# specify any defines as -D flags.
if settings.GetPerTargetSetting('INFOPLIST_PREPROCESS', 'NO') == 'YES':
# Create an intermediate file based on the path.
intermediate_plist = ('$(obj).$(TOOLSET)/$(TARGET)/' +
os.path.basename(info_plist))
defines = shlex.split(settings.GetPerTargetSetting(
'INFOPLIST_PREPROCESSOR_DEFINITIONS', ''))
self.WriteList(defines, intermediate_plist + ': INFOPLIST_DEFINES', '-D',
quoter=EscapeCppDefine)
self.WriteMakeRule([intermediate_plist], [info_plist],
['$(call do_cmd,infoplist)',
# "Convert" the plist so that any weird whitespace changes from the
# preprocessor do not affect the XML parser in mac_tool.
'@plutil -convert xml1 $@ $@'])
info_plist = intermediate_plist
path = generator_default_variables['PRODUCT_DIR'] path = generator_default_variables['PRODUCT_DIR']
dest_plist = os.path.join(path, self.xcode_settings.GetBundlePlistPath()) dest_plist = os.path.join(path, settings.GetBundlePlistPath())
dest_plist = QuoteSpaces(dest_plist) dest_plist = QuoteSpaces(dest_plist)
extra_settings = self.xcode_settings.GetPerTargetSettings() extra_settings = settings.GetPerTargetSettings()
# plists can contain envvars and substitute them into the file.. # plists can contain envvars and substitute them into the file..
self.WriteXcodeEnv(dest_plist, spec, additional_settings=extra_settings) self.WriteXcodeEnv(dest_plist, spec, additional_settings=extra_settings)
self.WriteDoCmd([dest_plist], [info_plist], 'mac_tool,,,copy-info-plist', self.WriteDoCmd([dest_plist], [info_plist], 'mac_tool,,,copy-info-plist',
@ -2007,6 +2038,8 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
# We want to get the literal string "$ORIGIN" into the link command, # We want to get the literal string "$ORIGIN" into the link command,
# so we need lots of escaping. # so we need lots of escaping.
ldflags.append(r'-Wl,-rpath=\$$ORIGIN/lib.%s/' % self.toolset) ldflags.append(r'-Wl,-rpath=\$$ORIGIN/lib.%s/' % self.toolset)
ldflags.append(r'-Wl,-rpath-link=\$(builddir)/lib.%s/' %
self.toolset)
self.WriteList(ldflags, 'LDFLAGS_%s' % configname) self.WriteList(ldflags, 'LDFLAGS_%s' % configname)
libraries = spec.get('libraries') libraries = spec.get('libraries')
if libraries: if libraries:
@ -2409,6 +2442,7 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
# See /Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Specifications/MacOSX\ Product\ Types.xcspec for FULL_PRODUCT_NAME # See /Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Specifications/MacOSX\ Product\ Types.xcspec for FULL_PRODUCT_NAME
'FULL_PRODUCT_NAME' : product_name, 'FULL_PRODUCT_NAME' : product_name,
'SRCROOT' : srcroot, 'SRCROOT' : srcroot,
'SOURCE_ROOT': '$(SRCROOT)',
# This is not true for static libraries, but currently the env is only # This is not true for static libraries, but currently the env is only
# written for bundles: # written for bundles:
'TARGET_BUILD_DIR' : built_products_dir, 'TARGET_BUILD_DIR' : built_products_dir,
@ -2453,14 +2487,66 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
# GetXcodeEnv() for the full rationale. # GetXcodeEnv() for the full rationale.
keys_to_not_absolutify = ('PRODUCT_NAME', 'FULL_PRODUCT_NAME') keys_to_not_absolutify = ('PRODUCT_NAME', 'FULL_PRODUCT_NAME')
# Perform some transformations that are required to mimic Xcode behavior. # First sort the list of keys, removing any non-string values.
for k in env: # Values that are not strings but are, for example, lists or tuples such
# Values that are not strings but are, for example, lists or tuples such # as LDFLAGS or CFLAGS, should not be written out because they are
# as LDFLAGS or CFLAGS, should not be written out because they are # not needed and it's undefined how multi-valued keys should be written.
# not needed and it's undefined how multi-valued keys should be written. key_list = env.keys()
if not isinstance(env[k], str): key_list.sort()
key_list = [k for k in key_list if isinstance(env[k], str)]
# Since environment variables can refer to other variables, the evaluation
# order is important. Below is the logic to compute the dependency graph
# and sort it.
regex = re.compile(r'\$\(([a-zA-Z0-9\-_]+)\)')
# Phase 1: Create a set of edges of (DEPENDEE, DEPENDER) where in the graph,
# DEPENDEE -> DEPENDER. Also create sets of dependers and dependees.
edges = set()
dependees = set()
dependers = set()
for k in key_list:
matches = regex.findall(env[k])
if not len(matches):
continue continue
dependers.add(k)
for dependee in matches:
if dependee in env:
edges.add((dependee, k))
dependees.add(dependee)
# Phase 2: Create a list of graph nodes with no incoming edges.
sorted_nodes = []
edgeless_nodes = dependees - dependers
# Phase 3: Perform Kahn topological sort.
while len(edgeless_nodes):
# Find a node with no incoming edges, add it to the sorted list, and
# remove it from the list of nodes that aren't part of the graph.
node = edgeless_nodes.pop()
sorted_nodes.append(node)
key_list.remove(node)
# Find all the edges between |node| and other nodes.
edges_to_node = [e for e in edges if e[0] == node]
for edge in edges_to_node:
edges.remove(edge)
# If the node connected to |node| by |edge| has no other incoming edges,
# add it to |edgeless_nodes|.
if not len([e for e in edges if e[1] == edge[1]]):
edgeless_nodes.add(edge[1])
# Any remaining edges indicate a cycle.
if len(edges):
raise Exception('Xcode environment variables are cyclically dependent: ' +
str(edges))
# Append the "nodes" not in the graph to those that were just sorted.
sorted_nodes.extend(key_list)
# Perform some transformations that are required to mimic Xcode behavior.
for k in sorted_nodes:
# For # For
# foo := a\ b # foo := a\ b
# the escaped space does the right thing. For # the escaped space does the right thing. For
@ -2498,7 +2584,9 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
"""Convert a subdirectory-relative path into a base-relative path. """Convert a subdirectory-relative path into a base-relative path.
Skips over paths that contain variables.""" Skips over paths that contain variables."""
if '$(' in path: if '$(' in path:
return path # path is no existing file in this case, but calling normpath is still
# important for trimming trailing slashes.
return os.path.normpath(path)
return os.path.normpath(os.path.join(self.path, path)) return os.path.normpath(os.path.join(self.path, path))
@ -2634,6 +2722,7 @@ def GenerateOutput(target_list, target_dicts, data, params):
generator_flags = params.get('generator_flags', {}) generator_flags = params.get('generator_flags', {})
builddir_name = generator_flags.get('output_dir', 'out') builddir_name = generator_flags.get('output_dir', 'out')
android_ndk_version = generator_flags.get('android_ndk_version', None) android_ndk_version = generator_flags.get('android_ndk_version', None)
default_target = generator_flags.get('default_target', 'all')
def CalculateMakefilePath(build_file, base_name): def CalculateMakefilePath(build_file, base_name):
"""Determine where to write a Makefile for a given gyp file.""" """Determine where to write a Makefile for a given gyp file."""
@ -2675,6 +2764,7 @@ def GenerateOutput(target_list, target_dicts, data, params):
flock_command= 'flock' flock_command= 'flock'
header_params = { header_params = {
'default_target': default_target,
'builddir': builddir_name, 'builddir': builddir_name,
'default_configuration': default_configuration, 'default_configuration': default_configuration,
'flock': flock_command, 'flock': flock_command,
@ -2714,7 +2804,8 @@ def GenerateOutput(target_list, target_dicts, data, params):
if value[0] != '$': if value[0] != '$':
value = '$(abspath %s)' % value value = '$(abspath %s)' % value
if key == 'LINK': if key == 'LINK':
make_global_settings += '%s ?= %s %s\n' % (flock_command, key, value) make_global_settings += ('%s ?= %s $(builddir)/linker.lock %s\n' %
(key, flock_command, value))
elif key in ['CC', 'CXX']: elif key in ['CC', 'CXX']:
make_global_settings += ( make_global_settings += (
'ifneq (,$(filter $(origin %s), undefined default))\n' % key) 'ifneq (,$(filter $(origin %s), undefined default))\n' % key)

2
tools/gyp/pylib/gyp/generator/msvs.py

@ -1,5 +1,3 @@
#!/usr/bin/python
# Copyright (c) 2011 Google Inc. All rights reserved. # Copyright (c) 2011 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.

2
tools/gyp/pylib/gyp/generator/msvs_test.py

@ -1,4 +1,4 @@
#!/usr/bin/python #!/usr/bin/env python
# Copyright (c) 2011 Google Inc. All rights reserved. # Copyright (c) 2011 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be

82
tools/gyp/pylib/gyp/generator/ninja.py

@ -1,5 +1,3 @@
#!/usr/bin/python
# Copyright (c) 2011 Google Inc. All rights reserved. # Copyright (c) 2011 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
@ -65,12 +63,6 @@ def QuoteShellArgument(arg):
return "'" + arg.replace("'", "'" + '"\'"' + "'") + "'" return "'" + arg.replace("'", "'" + '"\'"' + "'") + "'"
def MaybeQuoteShellArgument(arg):
if '"' in arg or ' ' in arg:
return QuoteShellArgument(arg)
return arg
def InvertRelativePath(path): def InvertRelativePath(path):
"""Given a relative path like foo/bar, return the inverse relative path: """Given a relative path like foo/bar, return the inverse relative path:
the path from the relative path back to the origin dir. the path from the relative path back to the origin dir.
@ -154,6 +146,15 @@ class NinjaWriter:
return path return path
def ExpandRuleVariables(self, path, root, dirname, source, ext, name):
path = path.replace(generator_default_variables['RULE_INPUT_ROOT'], root)
path = path.replace(generator_default_variables['RULE_INPUT_DIRNAME'],
dirname)
path = path.replace(generator_default_variables['RULE_INPUT_PATH'], source)
path = path.replace(generator_default_variables['RULE_INPUT_EXT'], ext)
path = path.replace(generator_default_variables['RULE_INPUT_NAME'], name)
return path
def GypPathToNinja(self, path): def GypPathToNinja(self, path):
"""Translate a gyp path to a ninja path. """Translate a gyp path to a ninja path.
@ -211,7 +212,8 @@ class NinjaWriter:
def WriteSpec(self, spec, config): def WriteSpec(self, spec, config):
"""The main entry point for NinjaWriter: write the build rules for a spec. """The main entry point for NinjaWriter: write the build rules for a spec.
Returns the path to the build output, or None.""" Returns the path to the build output, or None, and a list of targets for
dependencies of its compile steps."""
self.name = spec['target_name'] self.name = spec['target_name']
self.toolset = spec['toolset'] self.toolset = spec['toolset']
@ -226,43 +228,56 @@ class NinjaWriter:
spec['type'] = 'none' spec['type'] = 'none'
# Compute predepends for all rules. # Compute predepends for all rules.
# prebuild is the dependencies this target depends on before # actions_depends is the dependencies this target depends on before running
# running any of its internal steps. # any of its action/rule/copy steps.
prebuild = [] # compile_depends is the dependencies this target depends on before running
# any of its compile steps.
actions_depends = []
compile_depends = []
if 'dependencies' in spec: if 'dependencies' in spec:
for dep in spec['dependencies']: for dep in spec['dependencies']:
if dep in self.target_outputs: if dep in self.target_outputs:
prebuild.append(self.target_outputs[dep][0]) input, precompile_input, linkable = self.target_outputs[dep]
prebuild = self.WriteCollapsedDependencies('predepends', prebuild) actions_depends.append(input)
compile_depends.extend(precompile_input)
actions_depends = self.WriteCollapsedDependencies('actions_depends',
actions_depends)
# Write out actions, rules, and copies. These must happen before we # Write out actions, rules, and copies. These must happen before we
# compile any sources, so compute a list of predependencies for sources # compile any sources, so compute a list of predependencies for sources
# while we do it. # while we do it.
extra_sources = [] extra_sources = []
sources_predepends = self.WriteActionsRulesCopies(spec, extra_sources, sources_depends = self.WriteActionsRulesCopies(spec, extra_sources,
prebuild) actions_depends)
# If we have actions/rules/copies, we depend directly on those, but
# otherwise we depend on dependent target's actions/rules/copies etc.
# We never need to explicitly depend on previous target's link steps,
# because no compile ever depends on them.
compile_depends = self.WriteCollapsedDependencies('compile_depends',
sources_depends or compile_depends)
# Write out the compilation steps, if any. # Write out the compilation steps, if any.
link_deps = [] link_deps = []
sources = spec.get('sources', []) + extra_sources sources = spec.get('sources', []) + extra_sources
if sources: if sources:
link_deps = self.WriteSources(config, sources, link_deps = self.WriteSources(config, sources, compile_depends)
sources_predepends or prebuild)
# Some actions/rules output 'sources' that are already object files. # Some actions/rules output 'sources' that are already object files.
link_deps += [self.GypPathToNinja(f) for f in sources if f.endswith('.o')] link_deps += [self.GypPathToNinja(f) for f in sources if f.endswith('.o')]
# The final output of our target depends on the last output of the # The final output of our target depends on the last output of the
# above steps. # above steps.
output = None output = None
final_deps = link_deps or sources_predepends or prebuild final_deps = link_deps or sources_depends or actions_depends
if final_deps: if final_deps:
output = self.WriteTarget(spec, config, final_deps) output = self.WriteTarget(spec, config, final_deps,
order_only=actions_depends)
if self.name != output and self.toolset == 'target': if self.name != output and self.toolset == 'target':
# Write a short name to build this target. This benefits both the # Write a short name to build this target. This benefits both the
# "build chrome" case as well as the gyp tests, which expect to be # "build chrome" case as well as the gyp tests, which expect to be
# able to run actions and build libraries by their short name. # able to run actions and build libraries by their short name.
self.ninja.build(self.name, 'phony', output) self.ninja.build(self.name, 'phony', output)
return output return output, compile_depends
def WriteActionsRulesCopies(self, spec, extra_sources, prebuild): def WriteActionsRulesCopies(self, spec, extra_sources, prebuild):
"""Write out the Actions, Rules, and Copies steps. Return any outputs """Write out the Actions, Rules, and Copies steps. Return any outputs
@ -351,9 +366,8 @@ class NinjaWriter:
# Gather the list of outputs, expanding $vars if possible. # Gather the list of outputs, expanding $vars if possible.
outputs = [] outputs = []
for output in rule['outputs']: for output in rule['outputs']:
outputs.append(output.replace( outputs.append(self.ExpandRuleVariables(output, root, dirname,
generator_default_variables['RULE_INPUT_ROOT'], root).replace( source, ext, basename))
generator_default_variables['RULE_INPUT_DIRNAME'], dirname))
if int(rule.get('process_outputs_as_sources', False)): if int(rule.get('process_outputs_as_sources', False)):
extra_sources += outputs extra_sources += outputs
@ -409,14 +423,17 @@ class NinjaWriter:
self.ninja.variable('cxx', '$cxx_host') self.ninja.variable('cxx', '$cxx_host')
self.WriteVariableList('defines', self.WriteVariableList('defines',
['-D' + MaybeQuoteShellArgument(ninja_syntax.escape(d)) [QuoteShellArgument(ninja_syntax.escape('-D' + d))
for d in config.get('defines', [])]) for d in config.get('defines', [])])
self.WriteVariableList('includes', self.WriteVariableList('includes',
['-I' + self.GypPathToNinja(i) ['-I' + self.GypPathToNinja(i)
for i in config.get('include_dirs', [])]) for i in config.get('include_dirs', [])])
self.WriteVariableList('cflags', config.get('cflags')) self.WriteVariableList('cflags', map(self.ExpandSpecial,
self.WriteVariableList('cflags_c', config.get('cflags_c')) config.get('cflags', [])))
self.WriteVariableList('cflags_cc', config.get('cflags_cc')) self.WriteVariableList('cflags_c', map(self.ExpandSpecial,
config.get('cflags_c', [])))
self.WriteVariableList('cflags_cc', map(self.ExpandSpecial,
config.get('cflags_cc', [])))
self.ninja.newline() self.ninja.newline()
outputs = [] outputs = []
for source in sources: for source in sources:
@ -437,7 +454,7 @@ class NinjaWriter:
self.ninja.newline() self.ninja.newline()
return outputs return outputs
def WriteTarget(self, spec, config, final_deps): def WriteTarget(self, spec, config, final_deps, order_only):
if spec['type'] == 'none': if spec['type'] == 'none':
# This target doesn't have any explicit final output, but is instead # This target doesn't have any explicit final output, but is instead
# used for its effects before the final output (e.g. copies steps). # used for its effects before the final output (e.g. copies steps).
@ -460,7 +477,7 @@ class NinjaWriter:
if output_uses_linker: if output_uses_linker:
extra_deps = set() extra_deps = set()
for dep in spec['dependencies']: for dep in spec['dependencies']:
input, linkable = self.target_outputs.get(dep, (None, False)) input, _, linkable = self.target_outputs.get(dep, (None, [], False))
if not input: if not input:
continue continue
if linkable: if linkable:
@ -494,6 +511,7 @@ class NinjaWriter:
self.ninja.build(output, command, final_deps, self.ninja.build(output, command, final_deps,
implicit=list(implicit_deps), implicit=list(implicit_deps),
order_only=order_only,
variables=extra_bindings) variables=extra_bindings)
return output return output
@ -711,10 +729,10 @@ def GenerateOutput(target_list, target_dicts, data, params):
output_file))) output_file)))
master_ninja.subninja(output_file) master_ninja.subninja(output_file)
output = writer.WriteSpec(spec, config) output, compile_depends = writer.WriteSpec(spec, config)
if output: if output:
linkable = spec['type'] in ('static_library', 'shared_library') linkable = spec['type'] in ('static_library', 'shared_library')
target_outputs[qualified_target] = (output, linkable) target_outputs[qualified_target] = (output, compile_depends, linkable)
if qualified_target in all_targets: if qualified_target in all_targets:
all_outputs.add(output) all_outputs.add(output)

2
tools/gyp/pylib/gyp/generator/scons.py

@ -1,5 +1,3 @@
#!/usr/bin/python
# Copyright (c) 2011 Google Inc. All rights reserved. # Copyright (c) 2011 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.

4
tools/gyp/pylib/gyp/generator/xcode.py

@ -1,5 +1,3 @@
#!/usr/bin/python
# Copyright (c) 2011 Google Inc. All rights reserved. # Copyright (c) 2011 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
@ -1161,7 +1159,7 @@ exit 1
if support_xct: if support_xct:
support_xct.AddDependency(xcode_targets[dependency]) support_xct.AddDependency(xcode_targets[dependency])
if spec['type'] != 'none' and 'libraries' in spec: if 'libraries' in spec:
for library in spec['libraries']: for library in spec['libraries']:
xct.FrameworksPhase().AddFile(library) xct.FrameworksPhase().AddFile(library)
# Add the library's directory to LIBRARY_SEARCH_PATHS if necessary. # Add the library's directory to LIBRARY_SEARCH_PATHS if necessary.

2
tools/gyp/pylib/gyp/input.py

@ -1,5 +1,3 @@
#!/usr/bin/python
# Copyright (c) 2011 The Chromium Authors. All rights reserved. # Copyright (c) 2011 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.

5
tools/gyp/pylib/gyp/mac_tool.py

@ -1,4 +1,4 @@
#!/usr/bin/python #!/usr/bin/env python
# Copyright (c) 2011 Google Inc. All rights reserved. # Copyright (c) 2011 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
@ -16,10 +16,12 @@ import string
import subprocess import subprocess
import sys import sys
def main(args): def main(args):
executor = MacTool() executor = MacTool()
executor.Dispatch(args) executor.Dispatch(args)
class MacTool(object): class MacTool(object):
"""This class performs all the Mac tooling steps. The methods can either be """This class performs all the Mac tooling steps. The methods can either be
executed directly, or dispatched from an argument list.""" executed directly, or dispatched from an argument list."""
@ -185,5 +187,6 @@ class MacTool(object):
else: else:
return None return None
if __name__ == '__main__': if __name__ == '__main__':
sys.exit(main(sys.argv[1:])) sys.exit(main(sys.argv[1:]))

2
tools/gyp/pylib/gyp/ninja_syntax.py

@ -1,5 +1,3 @@
#!/usr/bin/python
# This file comes from # This file comes from
# https://github.com/martine/ninja/blob/master/misc/ninja_syntax.py # https://github.com/martine/ninja/blob/master/misc/ninja_syntax.py
# Do not edit! Edit the upstream one instead. # Do not edit! Edit the upstream one instead.

49
tools/gyp/pylib/gyp/sun_tool.py

@ -12,58 +12,12 @@ import struct
import subprocess import subprocess
import sys import sys
def main(args):
executor = SunTool()
executor.Dispatch(args)
class SunTool(object):
"""This class performs all the SunOS tooling steps. The methods can either be
executed directly, or dispatched from an argument list."""
def Dispatch(self, args):
"""Dispatches a string command to a method."""
if len(args) < 1:
raise Exception("Not enough arguments")
method = "Exec%s" % self._CommandifyName(args[0])
getattr(self, method)(*args[1:])
def _CommandifyName(self, name_string):
"""Transforms a tool name like copy-info-plist to CopyInfoPlist"""
return name_string.title().replace('-', '')
def ExecFlock(self, lockfile, *cmd_list):
"""Emulates the most basic behavior of Linux's flock(1)."""
# Rely on exception handling to report errors.
# Note that the stock python on SunOS has a bug
# where fcntl.flock(fd, LOCK_EX) always fails
# with EBADF, that's why we use this F_SETLK
# hack instead.
fd = os.open(lockfile, os.O_WRONLY|os.O_NOCTTY|os.O_CREAT, 0666)
op = struct.pack('hhllhhl', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0)
fcntl.fcntl(fd, fcntl.F_SETLK, op)
return subprocess.call(cmd_list)
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))
#!/usr/bin/env python
# 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.
"""These functions are executed via gyp-sun-tool when using the Makefile
generator."""
import fcntl
import os
import struct
import subprocess
import sys
def main(args): def main(args):
executor = SunTool() executor = SunTool()
executor.Dispatch(args) executor.Dispatch(args)
class SunTool(object): class SunTool(object):
"""This class performs all the SunOS tooling steps. The methods can either be """This class performs all the SunOS tooling steps. The methods can either be
executed directly, or dispatched from an argument list.""" executed directly, or dispatched from an argument list."""
@ -92,5 +46,6 @@ class SunTool(object):
fcntl.fcntl(fd, fcntl.F_SETLK, op) fcntl.fcntl(fd, fcntl.F_SETLK, op)
return subprocess.call(cmd_list) return subprocess.call(cmd_list)
if __name__ == '__main__': if __name__ == '__main__':
sys.exit(main(sys.argv[1:])) sys.exit(main(sys.argv[1:]))

10
tools/gyp/pylib/gyp/system_test.py

@ -1,4 +1,4 @@
#!/usr/bin/python #!/usr/bin/env python
# Copyright (c) 2011 Google Inc. All rights reserved. # Copyright (c) 2011 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
@ -9,6 +9,7 @@ import tempfile
import shutil import shutil
import subprocess import subprocess
def TestCommands(commands, files={}, env={}): def TestCommands(commands, files={}, env={}):
"""Run commands in a temporary directory, returning true if they all succeed. """Run commands in a temporary directory, returning true if they all succeed.
Return false on failures or if any commands produce output. Return false on failures or if any commands produce output.
@ -64,7 +65,7 @@ def TestLinkerSupportsICF(cc_command='cc'):
env={'cc': cc_command}) env={'cc': cc_command})
if __name__ == '__main__': def main():
# Run the various test functions and print the results. # Run the various test functions and print the results.
def RunTest(description, function, **kwargs): def RunTest(description, function, **kwargs):
print "Testing " + description + ':', print "Testing " + description + ':',
@ -75,3 +76,8 @@ if __name__ == '__main__':
RunTest("ar 'T' flag", TestArSupportsT) RunTest("ar 'T' flag", TestArSupportsT)
RunTest("ar 'T' flag with ccache", TestArSupportsT, cc_command='ccache cc') RunTest("ar 'T' flag with ccache", TestArSupportsT, cc_command='ccache cc')
RunTest("ld --threads", TestLinkerSupportsThreads) RunTest("ld --threads", TestLinkerSupportsThreads)
return 0
if __name__ == '__main__':
sys.exit(main())

8
tools/gyp/pylib/gyp/xcodeproj_file.py

@ -1,5 +1,3 @@
#!/usr/bin/python
# Copyright (c) 2009 Google Inc. All rights reserved. # Copyright (c) 2009 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
@ -13,8 +11,8 @@ Xcode.app and observing the resultant changes in the associated project files.
XCODE PROJECT FILES XCODE PROJECT FILES
The generator targets the file format as written by Xcode 3.1 (specifically, The generator targets the file format as written by Xcode 3.2 (specifically,
3.1.2), but past experience has taught that the format has not changed 3.2.6), but past experience has taught that the format has not changed
significantly in the past several years, and future versions of Xcode are able significantly in the past several years, and future versions of Xcode are able
to read older project files. to read older project files.
@ -2444,7 +2442,7 @@ class PBXProject(XCContainerPortal):
'attributes': [0, dict, 0, 0], 'attributes': [0, dict, 0, 0],
'buildConfigurationList': [0, XCConfigurationList, 1, 1, 'buildConfigurationList': [0, XCConfigurationList, 1, 1,
XCConfigurationList()], XCConfigurationList()],
'compatibilityVersion': [0, str, 0, 1, 'Xcode 3.1'], 'compatibilityVersion': [0, str, 0, 1, 'Xcode 3.2'],
'hasScannedForEncodings': [0, int, 0, 1, 1], 'hasScannedForEncodings': [0, int, 0, 1, 1],
'mainGroup': [0, PBXGroup, 1, 1, PBXGroup()], 'mainGroup': [0, PBXGroup, 1, 1, PBXGroup()],
'projectDirPath': [0, str, 0, 1, ''], 'projectDirPath': [0, str, 0, 1, ''],

1
tools/gyp/pylib/gyp/xml_fix.py

@ -1,4 +1,3 @@
#!/usr/bin/python
# Copyright (c) 2011 Google Inc. All rights reserved. # Copyright (c) 2011 Google Inc. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.

307
tools/gyp/pylintrc

@ -0,0 +1,307 @@
[MASTER]
# Specify a configuration file.
#rcfile=
# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
#init-hook=
# Profiled execution.
profile=no
# Add files or directories to the blacklist. They should be base names, not
# paths.
ignore=CVS
# Pickle collected data for later comparisons.
persistent=yes
# List of plugins (as comma separated values of python modules names) to load,
# usually to register additional checkers.
load-plugins=
[MESSAGES CONTROL]
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time.
#enable=
# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where
# it should appear only once).
# C0103: Invalid name "NN" (should match [a-z_][a-z0-9_]{2,30}$)
# C0111: Missing docstring
# C0302: Too many lines in module (NN)
# R0902: Too many instance attributes (N/7)
# R0903: Too few public methods (N/2)
# R0904: Too many public methods (NN/20)
# R0912: Too many branches (NN/12)
# R0913: Too many arguments (N/5)
# R0914: Too many local variables (NN/15)
# R0915: Too many statements (NN/50)
# W0141: Used builtin function 'map'
# W0142: Used * or ** magic
# W0232: Class has no __init__ method
# W0511: TODO
# W0603: Using the global statement
#
# These should be enabled eventually:
# C0112: Empty docstring
# C0301: Line too long (NN/80)
# C0321: More than one statement on single line
# C0322: Operator not preceded by a space
# C0323: Operator not followed by a space
# C0324: Comma not followed by a space
# E0101: Explicit return in __init__
# E0102: function already defined line NN
# E1002: Use of super on an old style class
# E1101: Instance of 'XX' has no 'YY' member
# E1103: Instance of 'XX' has no 'XX' member (but some types could not be inferred)
# E0602: Undefined variable 'XX'
# F0401: Unable to import 'XX'
# R0201: Method could be a function
# R0801: Similar lines in N files
# W0102: Dangerous default value {} as argument
# W0104: Statement seems to have no effect
# W0105: String statement has no effect
# W0108: Lambda may not be necessary
# W0201: Attribute 'XX' defined outside __init__
# W0212: Access to a protected member XX of a client class
# W0221: Arguments number differs from overridden method
# W0223: Method 'XX' is abstract in class 'YY' but is not overridden
# W0231: __init__ method from base class 'XX' is not called
# W0301: Unnecessary semicolon
# W0311: Bad indentation. Found NN spaces, expected NN
# W0401: Wildcard import XX
# W0402: Uses of a deprecated module 'string'
# W0403: Relative import 'XX', should be 'YY.XX'
# W0404: Reimport 'XX' (imported line NN)
# W0601: Global variable 'XX' undefined at the module level
# W0602: Using global for 'XX' but no assignment is done
# W0611: Unused import pprint
# W0612: Unused variable 'XX'
# W0613: Unused argument 'XX'
# W0614: Unused import XX from wildcard import
# W0621: Redefining name 'XX' from outer scope (line NN)
# W0622: Redefining built-in 'NN'
# W0631: Using possibly undefined loop variable 'XX'
# W0701: Raising a string exception
# W0702: No exception type(s) specified
disable=C0103,C0111,C0302,R0902,R0903,R0904,R0912,R0913,R0914,R0915,W0141,W0142,W0232,W0511,W0603,C0112,C0301,C0321,C0322,C0323,C0324,E0101,E0102,E1002,E1101,E1103,E0602,F0401,R0201,R0801,W0102,W0104,W0105,W0108,W0201,W0212,W0221,W0223,W0231,W0301,W0311,W0401,W0402,W0403,W0404,W0601,W0602,W0611,W0612,W0613,W0614,W0621,W0622,W0631,W0701,W0702
[REPORTS]
# Set the output format. Available formats are text, parseable, colorized, msvs
# (visual studio) and html
output-format=text
# Include message's id in output
include-ids=yes
# Put messages in a separate file for each module / package specified on the
# command line instead of printing them on stdout. Reports (if any) will be
# written in a file name "pylint_global.[txt|html]".
files-output=no
# Tells whether to display a full report or only the messages
reports=no
# Python expression which should return a note less than 10 (10 is the highest
# note). You have access to the variables errors warning, statement which
# respectively contain the number of errors / warnings messages and the total
# number of statements analyzed. This is used by the global evaluation report
# (RP0004).
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
# Add a comment according to your evaluation note. This is used by the global
# evaluation report (RP0004).
comment=no
[VARIABLES]
# Tells whether we should check for unused import in __init__ files.
init-import=no
# A regular expression matching the beginning of the name of dummy variables
# (i.e. not used).
dummy-variables-rgx=_|dummy
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid to define new builtins when possible.
additional-builtins=
[TYPECHECK]
# Tells whether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
ignore-mixin-members=yes
# List of classes names for which member attributes should not be checked
# (useful for classes with attributes dynamically set).
ignored-classes=SQLObject
# When zope mode is activated, add a predefined set of Zope acquired attributes
# to generated-members.
zope=no
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E0201 when accessed. Python regular
# expressions are accepted.
generated-members=REQUEST,acl_users,aq_parent
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
notes=FIXME,XXX,TODO
[SIMILARITIES]
# Minimum lines number of a similarity.
min-similarity-lines=4
# Ignore comments when computing similarities.
ignore-comments=yes
# Ignore docstrings when computing similarities.
ignore-docstrings=yes
[FORMAT]
# Maximum number of characters on a single line.
max-line-length=80
# Maximum number of lines in a module
max-module-lines=1000
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
# tab).
indent-string=' '
[BASIC]
# Required attributes for module, separated by a comma
required-attributes=
# List of builtins function names that should not be used, separated by a comma
bad-functions=map,filter,apply,input
# Regular expression which should only match correct module names
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
# Regular expression which should only match correct module level names
const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
# Regular expression which should only match correct class names
class-rgx=[A-Z_][a-zA-Z0-9]+$
# Regular expression which should only match correct function names
function-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct method names
method-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct instance attribute names
attr-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct argument names
argument-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct variable names
variable-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct list comprehension /
# generator expression variable names
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
# Good variable names which should always be accepted, separated by a comma
good-names=i,j,k,ex,Run,_
# Bad variable names which should always be refused, separated by a comma
bad-names=foo,bar,baz,toto,tutu,tata
# Regular expression which should only match functions or classes name which do
# not require a docstring
no-docstring-rgx=__.*__
[DESIGN]
# Maximum number of arguments for function / method
max-args=5
# Argument names that match this expression will be ignored. Default to name
# with leading underscore
ignored-argument-names=_.*
# Maximum number of locals for function / method body
max-locals=15
# Maximum number of return / yield for function / method body
max-returns=6
# Maximum number of branch for function / method body
max-branchs=12
# Maximum number of statements in function / method body
max-statements=50
# Maximum number of parents for a class (see R0901).
max-parents=7
# Maximum number of attributes for a class (see R0902).
max-attributes=7
# Minimum number of public methods for a class (see R0903).
min-public-methods=2
# Maximum number of public methods for a class (see R0904).
max-public-methods=20
[CLASSES]
# List of interface methods to ignore, separated by a comma. This is used for
# instance to not check methods defines in Zope's Interface base class.
ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,__new__,setUp
# List of valid names for the first argument in a class method.
valid-classmethod-first-arg=cls
[IMPORTS]
# Deprecated modules which should not be used, separated by a comma
deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
# Create a graph of every (i.e. internal and external) dependencies in the
# given file (report RP0402 must not be disabled)
import-graph=
# Create a graph of external dependencies in the given file (report RP0402 must
# not be disabled)
ext-import-graph=
# Create a graph of internal dependencies in the given file (report RP0402 must
# not be disabled)
int-import-graph=
[EXCEPTIONS]
# Exceptions that will emit a warning when being caught. Defaults to
# "Exception"
overgeneral-exceptions=Exception

23
tools/gyp/test/actions-bare/gyptest-bare.py

@ -0,0 +1,23 @@
#!/usr/bin/env python
# Copyright (c) 2009 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 actions which are not depended on by other targets get executed.
"""
import TestGyp
test = TestGyp.TestGyp()
test.run_gyp('bare.gyp', chdir='src')
test.relocate('src', 'relocate/src')
test.build('bare.gyp', chdir='relocate/src')
file_content = 'Hello from bare.py\n'
test.built_file_must_match('out.txt', file_content, chdir='relocate/src')
test.pass_test()

25
tools/gyp/test/actions-bare/src/bare.gyp

@ -0,0 +1,25 @@
# Copyright (c) 2009 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': 'bare',
'type': 'none',
'actions': [
{
'action_name': 'action1',
'inputs': [
'bare.py',
],
'outputs': [
'<(PRODUCT_DIR)/out.txt',
],
'action': ['python', 'bare.py', '<(PRODUCT_DIR)/out.txt'],
'msvs_cygwin_shell': 0,
},
],
},
],
}

11
tools/gyp/test/actions-bare/src/bare.py

@ -0,0 +1,11 @@
#!/usr/bin/env python
# Copyright (c) 2009 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('Hello from bare.py\n')
f.close()

42
tools/gyp/test/actions-multiple/gyptest-all.py

@ -0,0 +1,42 @@
#!/usr/bin/env python
# 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.
"""
Verifies two actions can be attached to the same input files.
"""
import TestGyp
test = TestGyp.TestGyp()
test.run_gyp('actions.gyp', chdir='src')
test.relocate('src', 'relocate/src')
# Test that two actions can be attached to the same inputs.
test.build('actions.gyp', test.ALL, chdir='relocate/src')
test.must_contain('relocate/src/output1.txt', 'hello there')
test.must_contain('relocate/src/output2.txt', 'hello there')
test.must_contain('relocate/src/output3.txt', 'hello there')
test.must_contain('relocate/src/output4.txt', 'hello there')
# Test that process_outputs_as_sources works in conjuction with merged
# actions.
test.run_built_executable(
'multiple_action_source_filter',
chdir='relocate/src',
stdout=(
'{\n'
'bar\n'
'car\n'
'dar\n'
'ear\n'
'}\n'
),
)
test.pass_test()

165
tools/gyp/test/actions-multiple/src/actions.gyp

@ -0,0 +1,165 @@
# 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.
{
'variables': {
# Have a long string so that actions will exceed xp 512 character
# command limit on xp.
'long_string':
'abcdefghijklmnopqrstuvwxyz0123456789'
'abcdefghijklmnopqrstuvwxyz0123456789'
'abcdefghijklmnopqrstuvwxyz0123456789'
'abcdefghijklmnopqrstuvwxyz0123456789'
'abcdefghijklmnopqrstuvwxyz0123456789'
'abcdefghijklmnopqrstuvwxyz0123456789'
'abcdefghijklmnopqrstuvwxyz0123456789'
'abcdefghijklmnopqrstuvwxyz0123456789'
'abcdefghijklmnopqrstuvwxyz0123456789'
'abcdefghijklmnopqrstuvwxyz0123456789'
'abcdefghijklmnopqrstuvwxyz0123456789'
},
'targets': [
{
'target_name': 'multiple_action_target',
'type': 'none',
'actions': [
{
'action_name': 'action1',
'inputs': [
'copy.py',
'input.txt',
],
'outputs': [
'output1.txt',
],
'action': [
'python', '<@(_inputs)', '<(_outputs)', '<(long_string)',
],
# Allows the test to run without hermetic cygwin on windows.
'msvs_cygwin_shell': 0,
},
{
'action_name': 'action2',
'inputs': [
'copy.py',
'input.txt',
],
'outputs': [
'output2.txt',
],
'action': [
'python', '<@(_inputs)', '<(_outputs)', '<(long_string)',
],
# Allows the test to run without hermetic cygwin on windows.
'msvs_cygwin_shell': 0,
},
{
'action_name': 'action3',
'inputs': [
'copy.py',
'input.txt',
],
'outputs': [
'output3.txt',
],
'action': [
'python', '<@(_inputs)', '<(_outputs)', '<(long_string)',
],
# Allows the test to run without hermetic cygwin on windows.
'msvs_cygwin_shell': 0,
},
{
'action_name': 'action4',
'inputs': [
'copy.py',
'input.txt',
],
'outputs': [
'output4.txt',
],
'action': [
'python', '<@(_inputs)', '<(_outputs)', '<(long_string)',
],
# Allows the test to run without hermetic cygwin on windows.
'msvs_cygwin_shell': 0,
},
],
},
{
'target_name': 'multiple_action_source_filter',
'type': 'executable',
'sources': [
'main.c',
# TODO(bradnelson): add foo.c here once this issue is fixed:
# http://code.google.com/p/gyp/issues/detail?id=175
],
'actions': [
{
'action_name': 'action1',
'inputs': [
'foo.c',
'filter.py',
],
'outputs': [
'<(INTERMEDIATE_DIR)/output1.c',
],
'process_outputs_as_sources': 1,
'action': [
'python', 'filter.py', 'foo', 'bar', 'foo.c', '<@(_outputs)',
],
# Allows the test to run without hermetic cygwin on windows.
'msvs_cygwin_shell': 0,
},
{
'action_name': 'action2',
'inputs': [
'foo.c',
'filter.py',
],
'outputs': [
'<(INTERMEDIATE_DIR)/output2.c',
],
'process_outputs_as_sources': 1,
'action': [
'python', 'filter.py', 'foo', 'car', 'foo.c', '<@(_outputs)',
],
# Allows the test to run without hermetic cygwin on windows.
'msvs_cygwin_shell': 0,
},
{
'action_name': 'action3',
'inputs': [
'foo.c',
'filter.py',
],
'outputs': [
'<(INTERMEDIATE_DIR)/output3.c',
],
'process_outputs_as_sources': 1,
'action': [
'python', 'filter.py', 'foo', 'dar', 'foo.c', '<@(_outputs)',
],
# Allows the test to run without hermetic cygwin on windows.
'msvs_cygwin_shell': 0,
},
{
'action_name': 'action4',
'inputs': [
'foo.c',
'filter.py',
],
'outputs': [
'<(INTERMEDIATE_DIR)/output4.c',
],
'process_outputs_as_sources': 1,
'action': [
'python', 'filter.py', 'foo', 'ear', 'foo.c', '<@(_outputs)',
],
# Allows the test to run without hermetic cygwin on windows.
'msvs_cygwin_shell': 0,
},
],
},
],
}

9
tools/gyp/test/actions-multiple/src/copy.py

@ -0,0 +1,9 @@
#!/usr/bin/env python
# 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.
import shutil
import sys
shutil.copyfile(sys.argv[1], sys.argv[2])

12
tools/gyp/test/actions-multiple/src/filter.py

@ -0,0 +1,12 @@
#!/usr/bin/env python
# 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.
import sys
data = open(sys.argv[3], 'r').read()
fh = open(sys.argv[4], 'w')
fh.write(data.replace(sys.argv[1], sys.argv[2]))
fh.close()

11
tools/gyp/test/actions-multiple/src/foo.c

@ -0,0 +1,11 @@
/*
* 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.
*/
#include <stdio.h>
void foo(void) {
printf("foo\n");
}

1
tools/gyp/test/actions-multiple/src/input.txt

@ -0,0 +1 @@
hello there

22
tools/gyp/test/actions-multiple/src/main.c

@ -0,0 +1,22 @@
/*
* 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.
*/
#include <stdio.h>
void bar(void);
void car(void);
void dar(void);
void ear(void);
int main() {
printf("{\n");
bar();
car();
dar();
ear();
printf("}\n");
return 0;
}

26
tools/gyp/test/actions-subdir/gyptest-action.py

@ -0,0 +1,26 @@
#!/usr/bin/env python
# Copyright (c) 2009 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.
"""
Test actions that output to PRODUCT_DIR.
"""
import TestGyp
# TODO fix this for xcode: http://code.google.com/p/gyp/issues/detail?id=88
test = TestGyp.TestGyp(formats=['!xcode'])
test.run_gyp('none.gyp', chdir='src')
test.build('none.gyp', test.ALL, chdir='src')
file_content = 'Hello from make-file.py\n'
subdir_file_content = 'Hello from make-subdir-file.py\n'
test.built_file_must_match('file.out', file_content, chdir='src')
test.built_file_must_match('subdir_file.out', subdir_file_content, chdir='src')
test.pass_test()

11
tools/gyp/test/actions-subdir/src/make-file.py

@ -0,0 +1,11 @@
#!/usr/bin/env python
# Copyright (c) 2009 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
contents = 'Hello from make-file.py\n'
open(sys.argv[1], 'wb').write(contents)

31
tools/gyp/test/actions-subdir/src/none.gyp

@ -0,0 +1,31 @@
# Copyright (c) 2009 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': 'file',
'type': 'none',
'msvs_cygwin_shell': 0,
'actions': [
{
'action_name': 'make-file',
'inputs': [
'make-file.py',
],
'outputs': [
'<(PRODUCT_DIR)/file.out',
],
'action': [
'python', '<(_inputs)', '<@(_outputs)',
],
'process_outputs_as_sources': 1,
}
],
'dependencies': [
'subdir/subdir.gyp:subdir_file',
],
},
],
}

11
tools/gyp/test/actions-subdir/src/subdir/make-subdir-file.py

@ -0,0 +1,11 @@
#!/usr/bin/env python
# Copyright (c) 2009 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
contents = 'Hello from make-subdir-file.py\n'
open(sys.argv[1], 'wb').write(contents)

28
tools/gyp/test/actions-subdir/src/subdir/subdir.gyp

@ -0,0 +1,28 @@
# Copyright (c) 2009 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': 'subdir_file',
'type': 'none',
'msvs_cygwin_shell': 0,
'actions': [
{
'action_name': 'make-subdir-file',
'inputs': [
'make-subdir-file.py',
],
'outputs': [
'<(PRODUCT_DIR)/subdir_file.out',
],
'action': [
'python', '<(_inputs)', '<@(_outputs)',
],
'process_outputs_as_sources': 1,
}
],
},
],
}

101
tools/gyp/test/actions/gyptest-all.py

@ -0,0 +1,101 @@
#!/usr/bin/env python
# Copyright (c) 2009 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 simple actions when using an explicit build target of 'all'.
"""
import glob
import os
import TestGyp
test = TestGyp.TestGyp(workdir='workarea_all')
test.run_gyp('actions.gyp', chdir='src')
test.relocate('src', 'relocate/src')
# Some gyp files use an action that mentions an output but never
# writes it as a means to making the action run on every build. That
# doesn't mesh well with ninja's semantics. TODO(evan): figure out
# how to work always-run actions in to ninja.
if test.format == 'ninja':
test.build('actions.gyp', test.ALL, chdir='relocate/src')
else:
# Test that an "always run" action increases a counter on multiple
# invocations, and that a dependent action updates in step.
test.build('actions.gyp', test.ALL, chdir='relocate/src')
test.must_match('relocate/src/subdir1/actions-out/action-counter.txt', '1')
test.must_match('relocate/src/subdir1/actions-out/action-counter_2.txt', '1')
test.build('actions.gyp', test.ALL, chdir='relocate/src')
test.must_match('relocate/src/subdir1/actions-out/action-counter.txt', '2')
test.must_match('relocate/src/subdir1/actions-out/action-counter_2.txt', '2')
# The "always run" action only counts to 2, but the dependent target
# will count forever if it's allowed to run. This verifies that the
# dependent target only runs when the "always run" action generates
# new output, not just because the "always run" ran.
test.build('actions.gyp', test.ALL, chdir='relocate/src')
test.must_match('relocate/src/subdir1/actions-out/action-counter.txt', '2')
test.must_match('relocate/src/subdir1/actions-out/action-counter_2.txt', '2')
expect = """\
Hello from program.c
Hello from make-prog1.py
Hello from make-prog2.py
"""
if test.format == 'xcode':
chdir = 'relocate/src/subdir1'
else:
chdir = 'relocate/src'
test.run_built_executable('program', chdir=chdir, stdout=expect)
test.must_match('relocate/src/subdir2/file.out', "Hello from make-file.py\n")
expect = "Hello from generate_main.py\n"
if test.format == 'xcode':
chdir = 'relocate/src/subdir3'
else:
chdir = 'relocate/src'
test.run_built_executable('null_input', chdir=chdir, stdout=expect)
# Clean out files which may have been created if test.ALL was run.
def clean_dep_files():
for file in (glob.glob('relocate/src/dep_*.txt') +
glob.glob('relocate/src/deps_all_done_*.txt')):
if os.path.exists(file):
os.remove(file)
# Confirm our clean.
clean_dep_files()
test.must_not_exist('relocate/src/dep_1.txt')
test.must_not_exist('relocate/src/deps_all_done_first_123.txt')
# Make sure all deps finish before an action is run on a 'None' target.
# If using the Make builder, add -j to make things more difficult.
arguments = []
if test.format == 'make':
arguments = ['-j']
test.build('actions.gyp', 'action_with_dependencies_123', chdir='relocate/src',
arguments=arguments)
test.must_exist('relocate/src/deps_all_done_first_123.txt')
# Try again with a target that has deps in reverse. Output files from
# previous tests deleted. Confirm this execution did NOT run the ALL
# target which would mess up our dep tests.
clean_dep_files()
test.build('actions.gyp', 'action_with_dependencies_321', chdir='relocate/src',
arguments=arguments)
test.must_exist('relocate/src/deps_all_done_first_321.txt')
test.must_not_exist('relocate/src/deps_all_done_first_123.txt')
test.pass_test()

68
tools/gyp/test/actions/gyptest-default.py

@ -0,0 +1,68 @@
#!/usr/bin/env python
# Copyright (c) 2009 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 simple actions when using the default build target.
"""
import TestGyp
test = TestGyp.TestGyp(workdir='workarea_default')
test.run_gyp('actions.gyp', chdir='src')
test.relocate('src', 'relocate/src')
# Some gyp files use an action that mentions an output but never
# writes it as a means to making the action run on every build. That
# doesn't mesh well with ninja's semantics. TODO(evan): figure out
# how to work always-run actions in to ninja.
if test.format == 'ninja':
test.build('actions.gyp', test.ALL, chdir='relocate/src')
else:
# Test that an "always run" action increases a counter on multiple
# invocations, and that a dependent action updates in step.
test.build('actions.gyp', chdir='relocate/src')
test.must_match('relocate/src/subdir1/actions-out/action-counter.txt', '1')
test.must_match('relocate/src/subdir1/actions-out/action-counter_2.txt', '1')
test.build('actions.gyp', chdir='relocate/src')
test.must_match('relocate/src/subdir1/actions-out/action-counter.txt', '2')
test.must_match('relocate/src/subdir1/actions-out/action-counter_2.txt', '2')
# The "always run" action only counts to 2, but the dependent target
# will count forever if it's allowed to run. This verifies that the
# dependent target only runs when the "always run" action generates
# new output, not just because the "always run" ran.
test.build('actions.gyp', test.ALL, chdir='relocate/src')
test.must_match('relocate/src/subdir1/actions-out/action-counter.txt', '2')
test.must_match('relocate/src/subdir1/actions-out/action-counter_2.txt', '2')
expect = """\
Hello from program.c
Hello from make-prog1.py
Hello from make-prog2.py
"""
if test.format == 'xcode':
chdir = 'relocate/src/subdir1'
else:
chdir = 'relocate/src'
test.run_built_executable('program', chdir=chdir, stdout=expect)
test.must_match('relocate/src/subdir2/file.out', "Hello from make-file.py\n")
expect = "Hello from generate_main.py\n"
if test.format == 'xcode':
chdir = 'relocate/src/subdir3'
else:
chdir = 'relocate/src'
test.run_built_executable('null_input', chdir=chdir, stdout=expect)
test.pass_test()

24
tools/gyp/test/actions/gyptest-errors.py

@ -0,0 +1,24 @@
#!/usr/bin/env python
# Copyright (c) 2009 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 behavior for different action configuration errors:
exit status of 1, and the expected error message must be in stderr.
"""
import TestGyp
test = TestGyp.TestGyp(workdir='workarea_errors')
test.run_gyp('action_missing_name.gyp', chdir='src', status=1, stderr=None)
expect = [
"Anonymous action in target broken_actions2. An action must have an 'action_name' field.",
]
test.must_contain_all_lines(test.stderr(), expect)
test.pass_test()

24
tools/gyp/test/actions/src/action_missing_name.gyp

@ -0,0 +1,24 @@
# Copyright (c) 2009 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': 'broken_actions2',
'type': 'none',
'actions': [
{
'inputs': [
'no_name.input',
],
'action': [
'python',
'-c',
'print \'missing name\'',
],
},
],
},
],
}

114
tools/gyp/test/actions/src/actions.gyp

@ -0,0 +1,114 @@
# Copyright (c) 2009 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': 'pull_in_all_actions',
'type': 'none',
'dependencies': [
'subdir1/executable.gyp:*',
'subdir2/none.gyp:*',
'subdir3/null_input.gyp:*',
],
},
{
'target_name': 'depend_on_always_run_action',
'type': 'none',
'dependencies': [ 'subdir1/executable.gyp:counter' ],
'actions': [
{
'action_name': 'use_always_run_output',
'inputs': [
'subdir1/actions-out/action-counter.txt',
'subdir1/counter.py',
],
'outputs': [
'subdir1/actions-out/action-counter_2.txt',
],
'action': [
'python', 'subdir1/counter.py', '<(_outputs)',
],
# Allows the test to run without hermetic cygwin on windows.
'msvs_cygwin_shell': 0,
},
],
},
# Three deps which don't finish immediately.
# Each one has a small delay then creates a file.
# Delays are 1.0, 1.1, and 2.0 seconds.
{
'target_name': 'dep_1',
'type': 'none',
'actions': [{
'inputs': [ 'actions.gyp' ],
'outputs': [ 'dep_1.txt' ],
'action_name': 'dep_1',
'action': [ 'python', '-c',
'import time; time.sleep(1); open(\'dep_1.txt\', \'w\')' ],
# Allows the test to run without hermetic cygwin on windows.
'msvs_cygwin_shell': 0,
}],
},
{
'target_name': 'dep_2',
'type': 'none',
'actions': [{
'inputs': [ 'actions.gyp' ],
'outputs': [ 'dep_2.txt' ],
'action_name': 'dep_2',
'action': [ 'python', '-c',
'import time; time.sleep(1.1); open(\'dep_2.txt\', \'w\')' ],
# Allows the test to run without hermetic cygwin on windows.
'msvs_cygwin_shell': 0,
}],
},
{
'target_name': 'dep_3',
'type': 'none',
'actions': [{
'inputs': [ 'actions.gyp' ],
'outputs': [ 'dep_3.txt' ],
'action_name': 'dep_3',
'action': [ 'python', '-c',
'import time; time.sleep(2.0); open(\'dep_3.txt\', \'w\')' ],
# Allows the test to run without hermetic cygwin on windows.
'msvs_cygwin_shell': 0,
}],
},
# An action which assumes the deps have completed.
# Does NOT list the output files of it's deps as inputs.
# On success create the file deps_all_done_first.txt.
{
'target_name': 'action_with_dependencies_123',
'type': 'none',
'dependencies': [ 'dep_1', 'dep_2', 'dep_3' ],
'actions': [{
'inputs': [ 'actions.gyp' ],
'outputs': [ 'deps_all_done_first_123.txt' ],
'action_name': 'action_with_dependencies_123',
'action': [ 'python', 'confirm-dep-files.py', '<(_outputs)' ],
# Allows the test to run without hermetic cygwin on windows.
'msvs_cygwin_shell': 0,
}],
},
# Same as above but with deps in reverse.
{
'target_name': 'action_with_dependencies_321',
'type': 'none',
'dependencies': [ 'dep_3', 'dep_2', 'dep_1' ],
'actions': [{
'inputs': [ 'actions.gyp' ],
'outputs': [ 'deps_all_done_first_321.txt' ],
'action_name': 'action_with_dependencies_321',
'action': [ 'python', 'confirm-dep-files.py', '<(_outputs)' ],
# Allows the test to run without hermetic cygwin on windows.
'msvs_cygwin_shell': 0,
}],
},
],
}

21
tools/gyp/test/actions/src/confirm-dep-files.py

@ -0,0 +1,21 @@
#!/usr/bin/env python
# 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.
"""Confirms presence of files generated by our targets we depend on.
If they exist, create a new file.
Note target's input files are explicitly NOT defined in the gyp file
so they can't easily be passed to this script as args.
"""
import os
import sys
outfile = sys.argv[1] # Example value we expect: deps_all_done_first_123.txt
if (os.path.exists("dep_1.txt") and
os.path.exists("dep_2.txt") and
os.path.exists("dep_3.txt")):
open(outfile, "w")

46
tools/gyp/test/actions/src/subdir1/counter.py

@ -0,0 +1,46 @@
#!/usr/bin/env python
# Copyright (c) 2010 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
import time
output = sys.argv[1]
persistoutput = "%s.persist" % sys.argv[1]
count = 0
try:
count = open(persistoutput, 'r').read()
except:
pass
count = int(count) + 1
if len(sys.argv) > 2:
max_count = int(sys.argv[2])
if count > max_count:
count = max_count
oldcount = 0
try:
oldcount = open(output, 'r').read()
except:
pass
# Save the count in a file that is undeclared, and thus hidden, to gyp. We need
# to do this because, prior to running commands, scons deletes any declared
# outputs, so we would lose our count if we just wrote to the given output file.
# (The other option is to use Precious() in the scons generator, but that seems
# too heavy-handed just to support this somewhat unrealistic test case, and
# might lead to unintended side-effects).
open(persistoutput, 'w').write('%d' % (count))
# Only write the given output file if the count has changed.
if int(oldcount) != count:
open(output, 'w').write('%d' % (count))
# Sleep so the next run changes the file time sufficiently to make the build
# detect the file as changed.
time.sleep(1)
sys.exit(0)

74
tools/gyp/test/actions/src/subdir1/executable.gyp

@ -0,0 +1,74 @@
# Copyright (c) 2009 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',
'msvs_cygwin_shell': 0,
'sources': [
'program.c',
],
'actions': [
{
'action_name': 'make-prog1',
'inputs': [
'make-prog1.py',
],
'outputs': [
'<(INTERMEDIATE_DIR)/prog1.c',
],
'action': [
'python', '<(_inputs)', '<@(_outputs)',
],
'process_outputs_as_sources': 1,
},
{
'action_name': 'make-prog2',
'inputs': [
'make-prog2.py',
],
'outputs': [
'actions-out/prog2.c',
],
'action': [
'python', '<(_inputs)', '<@(_outputs)',
],
'process_outputs_as_sources': 1,
# Allows the test to run without hermetic cygwin on windows.
'msvs_cygwin_shell': 0,
},
],
},
{
'target_name': 'counter',
'type': 'none',
'actions': [
{
# This action should always run, regardless of whether or not it's
# inputs or the command-line change. We do this by creating a dummy
# first output, which is always missing, thus causing the build to
# always try to recreate it. Actual output files should be listed
# after the dummy one, and dependent targets should list the real
# output(s) in their inputs
# (see '../actions.gyp:depend_on_always_run_action').
'action_name': 'action_counter',
'inputs': [
'counter.py',
],
'outputs': [
'actions-out/action-counter.txt.always',
'actions-out/action-counter.txt',
],
'action': [
'python', '<(_inputs)', 'actions-out/action-counter.txt', '2',
],
# Allows the test to run without hermetic cygwin on windows.
'msvs_cygwin_shell': 0,
},
],
},
],
}

20
tools/gyp/test/actions/src/subdir1/make-prog1.py

@ -0,0 +1,20 @@
#!/usr/bin/env python
# Copyright (c) 2009 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
contents = r"""
#include <stdio.h>
void prog1(void)
{
printf("Hello from make-prog1.py\n");
}
"""
open(sys.argv[1], 'w').write(contents)
sys.exit(0)

20
tools/gyp/test/actions/src/subdir1/make-prog2.py

@ -0,0 +1,20 @@
#!/usr/bin/env python
# Copyright (c) 2009 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
contents = r"""
#include <stdio.h>
void prog2(void)
{
printf("Hello from make-prog2.py\n");
}
"""
open(sys.argv[1], 'w').write(contents)
sys.exit(0)

12
tools/gyp/test/actions/src/subdir1/program.c

@ -0,0 +1,12 @@
#include <stdio.h>
extern void prog1(void);
extern void prog2(void);
int main(int argc, char *argv[])
{
printf("Hello from program.c\n");
prog1();
prog2();
return 0;
}

11
tools/gyp/test/actions/src/subdir2/make-file.py

@ -0,0 +1,11 @@
#!/usr/bin/env python
# Copyright (c) 2009 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
contents = "Hello from make-file.py\n"
open(sys.argv[1], 'wb').write(contents)

33
tools/gyp/test/actions/src/subdir2/none.gyp

@ -0,0 +1,33 @@
# Copyright (c) 2009 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': 'file',
'type': 'none',
'msvs_cygwin_shell': 0,
'actions': [
{
'action_name': 'make-file',
'inputs': [
'make-file.py',
],
'outputs': [
'file.out',
# TODO: enhance testing infrastructure to test this
# without having to hard-code the intermediate dir paths.
#'<(INTERMEDIATE_DIR)/file.out',
],
'action': [
'python', '<(_inputs)', '<@(_outputs)',
],
'process_outputs_as_sources': 1,
# Allows the test to run without hermetic cygwin on windows.
'msvs_cygwin_shell': 0,
}
],
},
],
}

21
tools/gyp/test/actions/src/subdir3/generate_main.py

@ -0,0 +1,21 @@
#!/usr/bin/env python
# Copyright (c) 2009 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
contents = """
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("Hello from generate_main.py\\n");
return 0;
}
"""
open(sys.argv[1], 'w').write(contents)
sys.exit(0)

29
tools/gyp/test/actions/src/subdir3/null_input.gyp

@ -0,0 +1,29 @@
# Copyright (c) 2009 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': 'null_input',
'type': 'executable',
'msvs_cygwin_shell': 0,
'actions': [
{
'action_name': 'generate_main',
'process_outputs_as_sources': 1,
'inputs': [],
'outputs': [
'<(INTERMEDIATE_DIR)/main.c',
],
'action': [
# TODO: we can't just use <(_outputs) here?!
'python', 'generate_main.py', '<(INTERMEDIATE_DIR)/main.c',
],
# Allows the test to run without hermetic cygwin on windows.
'msvs_cygwin_shell': 0,
},
],
},
],
}

55
tools/gyp/test/additional-targets/gyptest-additional.py

@ -0,0 +1,55 @@
#!/usr/bin/env python
# Copyright (c) 2009 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 simple actions when using an explicit build target of 'all'.
"""
import TestGyp
test = TestGyp.TestGyp()
test.run_gyp('all.gyp', chdir='src')
test.relocate('src', 'relocate/src')
# Build all.
test.build('all.gyp', chdir='relocate/src')
if test.format=='xcode':
chdir = 'relocate/src/dir1'
else:
chdir = 'relocate/src'
# Output is as expected.
file_content = 'Hello from emit.py\n'
test.built_file_must_match('out2.txt', file_content, chdir=chdir)
test.built_file_must_not_exist('out.txt', chdir='relocate/src')
test.built_file_must_not_exist('foolib1',
type=test.SHARED_LIB,
chdir=chdir)
# TODO(mmoss) Make consistent with scons, with 'dir1' before 'out/Default'?
if test.format in ('make', 'ninja'):
chdir='relocate/src'
else:
chdir='relocate/src/dir1'
# Build the action explicitly.
test.build('actions.gyp', 'action1_target', chdir=chdir)
# Check that things got run.
file_content = 'Hello from emit.py\n'
test.built_file_must_exist('out.txt', chdir=chdir)
# Build the shared library explicitly.
test.build('actions.gyp', 'foolib1', chdir=chdir)
test.built_file_must_exist('foolib1',
type=test.SHARED_LIB,
chdir=chdir)
test.pass_test()

13
tools/gyp/test/additional-targets/src/all.gyp

@ -0,0 +1,13 @@
# Copyright (c) 2009 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': 'all_targets',
'type': 'none',
'dependencies': ['dir1/actions.gyp:*'],
},
],
}

56
tools/gyp/test/additional-targets/src/dir1/actions.gyp

@ -0,0 +1,56 @@
# Copyright (c) 2009 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': 'action1_target',
'type': 'none',
'suppress_wildcard': 1,
'actions': [
{
'action_name': 'action1',
'inputs': [
'emit.py',
],
'outputs': [
'<(PRODUCT_DIR)/out.txt',
],
'action': ['python', 'emit.py', '<(PRODUCT_DIR)/out.txt'],
'msvs_cygwin_shell': 0,
},
],
},
{
'target_name': 'action2_target',
'type': 'none',
'actions': [
{
'action_name': 'action2',
'inputs': [
'emit.py',
],
'outputs': [
'<(PRODUCT_DIR)/out2.txt',
],
'action': ['python', 'emit.py', '<(PRODUCT_DIR)/out2.txt'],
'msvs_cygwin_shell': 0,
},
],
},
{
'target_name': 'foolib1',
'type': 'shared_library',
'suppress_wildcard': 1,
'sources': ['lib1.c'],
},
],
'conditions': [
['OS=="linux"', {
'target_defaults': {
'cflags': ['-fPIC'],
},
}],
],
}

11
tools/gyp/test/additional-targets/src/dir1/emit.py

@ -0,0 +1,11 @@
#!/usr/bin/env python
# Copyright (c) 2009 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('Hello from emit.py\n')
f.close()

6
tools/gyp/test/additional-targets/src/dir1/lib1.c

@ -0,0 +1,6 @@
#ifdef _WIN32
__declspec(dllexport)
#endif
int func1(void) {
return 42;
}

31
tools/gyp/test/assembly/gyptest-assembly.py

@ -0,0 +1,31 @@
#!/usr/bin/env python
# Copyright (c) 2009 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 .hpp files are ignored when included in the source list on all
platforms.
"""
import sys
import TestGyp
# TODO(bradnelson): get this working for windows.
test = TestGyp.TestGyp(formats=['make', 'ninja', 'scons', 'xcode'])
test.run_gyp('assembly.gyp', chdir='src')
test.relocate('src', 'relocate/src')
test.build('assembly.gyp', test.ALL, chdir='relocate/src')
expect = """\
Hello from program.c
Got 42.
"""
test.run_built_executable('program', chdir='relocate/src', stdout=expect)
test.pass_test()

4
tools/gyp/test/assembly/src/as.bat

@ -0,0 +1,4 @@
@echo off
:: Mock windows assembler.
cl /c %1 /Fo"%2"

59
tools/gyp/test/assembly/src/assembly.gyp

@ -0,0 +1,59 @@
# Copyright (c) 2009 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.
{
'target_defaults': {
'conditions': [
['OS=="win"', {
'defines': ['PLATFORM_WIN'],
}],
['OS=="mac"', {
'defines': ['PLATFORM_MAC'],
}],
['OS=="linux"', {
'defines': ['PLATFORM_LINUX'],
}],
],
},
'targets': [
{
'target_name': 'program',
'type': 'executable',
'dependencies': ['lib1'],
'sources': [
'program.c',
],
},
{
'target_name': 'lib1',
'type': 'static_library',
'sources': [
'lib1.S',
],
},
],
'conditions': [
['OS=="win"', {
'target_defaults': {
'rules': [
{
'rule_name': 'assembler',
'msvs_cygwin_shell': 0,
'extension': 'S',
'inputs': [
'as.bat',
],
'outputs': [
'<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).obj',
],
'action':
['as.bat', 'lib1.c', '<(_outputs)'],
'message': 'Building assembly file <(RULE_INPUT_PATH)',
'process_outputs_as_sources': 1,
},
],
},
},],
],
}

10
tools/gyp/test/assembly/src/lib1.S

@ -0,0 +1,10 @@
#if PLATFORM_WINDOWS || PLATFORM_MAC
# define IDENTIFIER(n) _##n
#else /* Linux */
# define IDENTIFIER(n) n
#endif
.globl IDENTIFIER(lib1_function)
IDENTIFIER(lib1_function):
movl $42, %eax
ret

3
tools/gyp/test/assembly/src/lib1.c

@ -0,0 +1,3 @@
int lib1_function(void) {
return 42;
}

12
tools/gyp/test/assembly/src/program.c

@ -0,0 +1,12 @@
#include <stdio.h>
extern int lib1_function(void);
int main(int argc, char *argv[])
{
fprintf(stdout, "Hello from program.c\n");
fflush(stdout);
fprintf(stdout, "Got %d.\n", lib1_function());
fflush(stdout);
return 0;
}

77
tools/gyp/test/builddir/gyptest-all.py

@ -0,0 +1,77 @@
#!/usr/bin/env python
# Copyright (c) 2009 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 the settings that cause a set of programs to be created in
a specific build directory, and that no intermediate built files
get created outside of that build directory hierarchy even when
referred to with deeply-nested ../../.. paths.
"""
import TestGyp
# TODO(mmoss): Make only supports (theoretically) a single, global build
# directory (through GYP_GENERATOR_FLAGS 'output_dir'), rather than
# gyp-file-specific settings (e.g. the stuff in builddir.gypi) that the other
# generators support, so this doesn't work yet for make.
# TODO(mmoss) Make also has the issue that the top-level Makefile is written to
# the "--depth" location, which is one level above 'src', but then this test
# moves 'src' somewhere else, leaving the Makefile behind, so make can't find
# its sources. I'm not sure if make is wrong for writing outside the current
# directory, or if the test is wrong for assuming everything generated is under
# the current directory.
test = TestGyp.TestGyp(formats=['!make', '!ninja'])
test.run_gyp('prog1.gyp', '--depth=..', chdir='src')
test.relocate('src', 'relocate/src')
test.subdir('relocate/builddir')
# Make sure that all the built ../../etc. files only get put under builddir,
# by making all of relocate read-only and then making only builddir writable.
test.writable('relocate', False)
test.writable('relocate/builddir', True)
# Suppress the test infrastructure's setting SYMROOT on the command line.
test.build('prog1.gyp', test.ALL, SYMROOT=None, chdir='relocate/src')
expect1 = """\
Hello from prog1.c
Hello from func1.c
"""
expect2 = """\
Hello from subdir2/prog2.c
Hello from func2.c
"""
expect3 = """\
Hello from subdir2/subdir3/prog3.c
Hello from func3.c
"""
expect4 = """\
Hello from subdir2/subdir3/subdir4/prog4.c
Hello from func4.c
"""
expect5 = """\
Hello from subdir2/subdir3/subdir4/subdir5/prog5.c
Hello from func5.c
"""
def run_builddir(prog, expect):
dir = 'relocate/builddir/Default/'
test.run(program=test.workpath(dir + prog), stdout=expect)
run_builddir('prog1', expect1)
run_builddir('prog2', expect2)
run_builddir('prog3', expect3)
run_builddir('prog4', expect4)
run_builddir('prog5', expect5)
test.pass_test()

77
tools/gyp/test/builddir/gyptest-default.py

@ -0,0 +1,77 @@
#!/usr/bin/env python
# Copyright (c) 2009 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 the settings that cause a set of programs to be created in
a specific build directory, and that no intermediate built files
get created outside of that build directory hierarchy even when
referred to with deeply-nested ../../.. paths.
"""
import TestGyp
# TODO(mmoss): Make only supports (theoretically) a single, global build
# directory (through GYP_GENERATOR_FLAGS 'output_dir'), rather than
# gyp-file-specific settings (e.g. the stuff in builddir.gypi) that the other
# generators support, so this doesn't work yet for make.
# TODO(mmoss) Make also has the issue that the top-level Makefile is written to
# the "--depth" location, which is one level above 'src', but then this test
# moves 'src' somewhere else, leaving the Makefile behind, so make can't find
# its sources. I'm not sure if make is wrong for writing outside the current
# directory, or if the test is wrong for assuming everything generated is under
# the current directory.
test = TestGyp.TestGyp(formats=['!make', '!ninja'])
test.run_gyp('prog1.gyp', '--depth=..', chdir='src')
test.relocate('src', 'relocate/src')
test.subdir('relocate/builddir')
# Make sure that all the built ../../etc. files only get put under builddir,
# by making all of relocate read-only and then making only builddir writable.
test.writable('relocate', False)
test.writable('relocate/builddir', True)
# Suppress the test infrastructure's setting SYMROOT on the command line.
test.build('prog1.gyp', SYMROOT=None, chdir='relocate/src')
expect1 = """\
Hello from prog1.c
Hello from func1.c
"""
expect2 = """\
Hello from subdir2/prog2.c
Hello from func2.c
"""
expect3 = """\
Hello from subdir2/subdir3/prog3.c
Hello from func3.c
"""
expect4 = """\
Hello from subdir2/subdir3/subdir4/prog4.c
Hello from func4.c
"""
expect5 = """\
Hello from subdir2/subdir3/subdir4/subdir5/prog5.c
Hello from func5.c
"""
def run_builddir(prog, expect):
dir = 'relocate/builddir/Default/'
test.run(program=test.workpath(dir + prog), stdout=expect)
run_builddir('prog1', expect1)
run_builddir('prog2', expect2)
run_builddir('prog3', expect3)
run_builddir('prog4', expect4)
run_builddir('prog5', expect5)
test.pass_test()

21
tools/gyp/test/builddir/src/builddir.gypi

@ -0,0 +1,21 @@
# Copyright (c) 2009 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.
{
'target_defaults': {
'configurations': {
'Default': {
'msvs_configuration_attributes': {
'OutputDirectory': '<(DEPTH)\\builddir\Default',
},
},
},
},
'scons_settings': {
'sconsbuild_dir': '<(DEPTH)/builddir',
},
'xcode_settings': {
'SYMROOT': '<(DEPTH)/builddir',
},
}

6
tools/gyp/test/builddir/src/func1.c

@ -0,0 +1,6 @@
#include <stdio.h>
void func1(void)
{
printf("Hello from func1.c\n");
}

6
tools/gyp/test/builddir/src/func2.c

@ -0,0 +1,6 @@
#include <stdio.h>
void func2(void)
{
printf("Hello from func2.c\n");
}

6
tools/gyp/test/builddir/src/func3.c

@ -0,0 +1,6 @@
#include <stdio.h>
void func3(void)
{
printf("Hello from func3.c\n");
}

6
tools/gyp/test/builddir/src/func4.c

@ -0,0 +1,6 @@
#include <stdio.h>
void func4(void)
{
printf("Hello from func4.c\n");
}

6
tools/gyp/test/builddir/src/func5.c

@ -0,0 +1,6 @@
#include <stdio.h>
void func5(void)
{
printf("Hello from func5.c\n");
}

10
tools/gyp/test/builddir/src/prog1.c

@ -0,0 +1,10 @@
#include <stdio.h>
extern void func1(void);
int main(int argc, char *argv[])
{
printf("Hello from prog1.c\n");
func1();
return 0;
}

30
tools/gyp/test/builddir/src/prog1.gyp

@ -0,0 +1,30 @@
# Copyright (c) 2009 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.
{
'includes': [
'builddir.gypi',
],
'targets': [
{
'target_name': 'pull_in_all',
'type': 'none',
'dependencies': [
'prog1',
'subdir2/prog2.gyp:prog2',
'subdir2/subdir3/prog3.gyp:prog3',
'subdir2/subdir3/subdir4/prog4.gyp:prog4',
'subdir2/subdir3/subdir4/subdir5/prog5.gyp:prog5',
],
},
{
'target_name': 'prog1',
'type': 'executable',
'sources': [
'prog1.c',
'func1.c',
],
},
],
}

10
tools/gyp/test/builddir/src/subdir2/prog2.c

@ -0,0 +1,10 @@
#include <stdio.h>
extern void func2(void);
int main(int argc, char *argv[])
{
printf("Hello from subdir2/prog2.c\n");
func2();
return 0;
}

19
tools/gyp/test/builddir/src/subdir2/prog2.gyp

@ -0,0 +1,19 @@
# Copyright (c) 2009 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.
{
'includes': [
'../builddir.gypi',
],
'targets': [
{
'target_name': 'prog2',
'type': 'executable',
'sources': [
'prog2.c',
'../func2.c',
],
},
],
}

10
tools/gyp/test/builddir/src/subdir2/subdir3/prog3.c

@ -0,0 +1,10 @@
#include <stdio.h>
extern void func3(void);
int main(int argc, char *argv[])
{
printf("Hello from subdir2/subdir3/prog3.c\n");
func3();
return 0;
}

19
tools/gyp/test/builddir/src/subdir2/subdir3/prog3.gyp

@ -0,0 +1,19 @@
# Copyright (c) 2009 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.
{
'includes': [
'../../builddir.gypi',
],
'targets': [
{
'target_name': 'prog3',
'type': 'executable',
'sources': [
'prog3.c',
'../../func3.c',
],
},
],
}

10
tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/prog4.c

@ -0,0 +1,10 @@
#include <stdio.h>
extern void func4(void);
int main(int argc, char *argv[])
{
printf("Hello from subdir2/subdir3/subdir4/prog4.c\n");
func4();
return 0;
}

19
tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/prog4.gyp

@ -0,0 +1,19 @@
# Copyright (c) 2009 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.
{
'includes': [
'../../../builddir.gypi',
],
'targets': [
{
'target_name': 'prog4',
'type': 'executable',
'sources': [
'prog4.c',
'../../../func4.c',
],
},
],
}

10
tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.c

@ -0,0 +1,10 @@
#include <stdio.h>
extern void func5(void);
int main(int argc, char *argv[])
{
printf("Hello from subdir2/subdir3/subdir4/subdir5/prog5.c\n");
func5();
return 0;
}

19
tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.gyp

@ -0,0 +1,19 @@
# Copyright (c) 2009 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.
{
'includes': [
'../../../../builddir.gypi',
],
'targets': [
{
'target_name': 'prog5',
'type': 'executable',
'sources': [
'prog5.c',
'../../../../func5.c',
],
},
],
}

15
tools/gyp/test/cflags/cflags.c

@ -0,0 +1,15 @@
/* Copyright (c) 2010 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 <stdio.h>
int main(int argc, char *argv[])
{
#ifdef __OPTIMIZE__
printf("Using an optimization flag\n");
#else
printf("Using no optimization flag\n");
#endif
return 0;
}

16
tools/gyp/test/cflags/cflags.gyp

@ -0,0 +1,16 @@
# Copyright (c) 2010 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': 'cflags',
'type': 'executable',
'opt': '-Os',
'sources': [
'cflags.c',
],
},
],
}

65
tools/gyp/test/cflags/gyptest-cflags.py

@ -0,0 +1,65 @@
#!/usr/bin/env python
# Copyright (c) 2010 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 build of an executable with C++ define specified by a gyp define, and
the use of the environment during regeneration when the gyp file changes.
"""
import os
import TestGyp
env_stack = []
def PushEnv():
env_copy = os.environ.copy()
env_stack.append(env_copy)
def PopEnv():
os.eniron=env_stack.pop()
# Regenerating build files when a gyp file changes is currently only supported
# by the make generator.
test = TestGyp.TestGyp(formats=['make'])
try:
PushEnv()
os.environ['CFLAGS'] = '-O0'
test.run_gyp('cflags.gyp')
finally:
# We clear the environ after calling gyp. When the auto-regeneration happens,
# the same define should be reused anyway. Reset to empty string first in
# case the platform doesn't support unsetenv.
PopEnv()
test.build('cflags.gyp')
expect = """\
Using no optimization flag
"""
test.run_built_executable('cflags', stdout=expect)
test.sleep()
try:
PushEnv()
os.environ['CFLAGS'] = '-O2'
test.run_gyp('cflags.gyp')
finally:
# We clear the environ after calling gyp. When the auto-regeneration happens,
# the same define should be reused anyway. Reset to empty string first in
# case the platform doesn't support unsetenv.
PopEnv()
test.build('cflags.gyp')
expect = """\
Using an optimization flag
"""
test.run_built_executable('cflags', stdout=expect)
test.pass_test()

29
tools/gyp/test/compilable/gyptest-headers.py

@ -0,0 +1,29 @@
#!/usr/bin/env python
# Copyright (c) 2009 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 .hpp files are ignored when included in the source list on all
platforms.
"""
import TestGyp
test = TestGyp.TestGyp()
test.run_gyp('headers.gyp', chdir='src')
test.relocate('src', 'relocate/src')
test.build('headers.gyp', test.ALL, chdir='relocate/src')
expect = """\
Hello from program.c
Hello from lib1.c
"""
test.run_built_executable('program', chdir='relocate/src', stdout=expect)
test.pass_test()

26
tools/gyp/test/compilable/src/headers.gyp

@ -0,0 +1,26 @@
# Copyright (c) 2009 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',
'dependencies': [
'lib1'
],
'sources': [
'program.cpp',
],
},
{
'target_name': 'lib1',
'type': 'static_library',
'sources': [
'lib1.hpp',
'lib1.cpp',
],
},
],
}

7
tools/gyp/test/compilable/src/lib1.cpp

@ -0,0 +1,7 @@
#include <stdio.h>
#include "lib1.hpp"
void lib1_function(void) {
fprintf(stdout, "Hello from lib1.c\n");
fflush(stdout);
}

6
tools/gyp/test/compilable/src/lib1.hpp

@ -0,0 +1,6 @@
#ifndef _lib1_hpp
#define _lib1_hpp
extern void lib1_function(void);
#endif

9
tools/gyp/test/compilable/src/program.cpp

@ -0,0 +1,9 @@
#include <stdio.h>
#include "lib1.hpp"
int main(int argc, char *argv[]) {
fprintf(stdout, "Hello from program.c\n");
fflush(stdout);
lib1_function();
return 0;
}

15
tools/gyp/test/configurations/basics/configurations.c

@ -0,0 +1,15 @@
#include <stdio.h>
int main(int argc, char *argv[])
{
#ifdef FOO
printf("Foo configuration\n");
#endif
#ifdef DEBUG
printf("Debug configuration\n");
#endif
#ifdef RELEASE
printf("Release configuration\n");
#endif
return 0;
}

32
tools/gyp/test/configurations/basics/configurations.gyp

@ -0,0 +1,32 @@
# Copyright (c) 2009 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': 'configurations',
'type': 'executable',
'sources': [
'configurations.c',
],
'configurations': {
'Debug': {
'defines': [
'DEBUG',
],
},
'Release': {
'defines': [
'RELEASE',
],
},
'Foo': {
'defines': [
'FOO',
],
},
}
},
],
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save