diff options
author | Ben Noordhuis <info@bnoordhuis.nl> | 2011-12-04 00:26:50 +0400 |
---|---|---|
committer | Ben Noordhuis <info@bnoordhuis.nl> | 2011-12-04 00:28:17 +0400 |
commit | e90623edc2befb06602ff8c3e01809ba0a21d593 (patch) | |
tree | 142a84aa010f924262925eb2b959d292d6624576 /tools | |
parent | 49ba55b10045969d9dba89ee11a53ca2d35d8f7f (diff) |
gyp: upgrade to r1103
Diffstat (limited to 'tools')
527 files changed, 20547 insertions, 334 deletions
diff --git a/tools/gyp/PRESUBMIT.py b/tools/gyp/PRESUBMIT.py index 737584bc7e0..146327d784b 100755..100644 --- a/tools/gyp/PRESUBMIT.py +++ b/tools/gyp/PRESUBMIT.py @@ -34,6 +34,16 @@ def CheckChangeOnCommit(input_api, output_api): input_api, output_api, 'http://gyp-status.appspot.com/status', '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 diff --git a/tools/gyp/buildbot/buildbot_run.py b/tools/gyp/buildbot/buildbot_run.py index adad7f9da00..df1cc8ad5e3 100755 --- a/tools/gyp/buildbot/buildbot_run.py +++ b/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. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/tools/gyp/pylib/gyp/MSVSNew.py b/tools/gyp/pylib/gyp/MSVSNew.py index ae8cbee688a..6906c7bc774 100644 --- a/tools/gyp/pylib/gyp/MSVSNew.py +++ b/tools/gyp/pylib/gyp/MSVSNew.py @@ -1,6 +1,4 @@ -#!/usr/bin/python2.4 - -# Copyright (c) 2009 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 # 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.""" def __init__(self, path, name = None, entries = None, @@ -103,7 +101,7 @@ class MSVSFolder: #------------------------------------------------------------------------------ -class MSVSProject: +class MSVSProject(object): """Visual Studio project.""" def __init__(self, path, name = None, dependencies = None, guid = None, diff --git a/tools/gyp/pylib/gyp/MSVSProject.py b/tools/gyp/pylib/gyp/MSVSProject.py index fab11f9d0d5..4713787cd49 100644 --- a/tools/gyp/pylib/gyp/MSVSProject.py +++ b/tools/gyp/pylib/gyp/MSVSProject.py @@ -1,6 +1,4 @@ -#!/usr/bin/python2.4 - -# Copyright (c) 2009 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 # found in the LICENSE file. @@ -208,5 +206,3 @@ class Writer(object): ] easy_xml.WriteXmlIfChanged(content, self.project_path, encoding="Windows-1252") - -#------------------------------------------------------------------------------ diff --git a/tools/gyp/pylib/gyp/MSVSSettings.py b/tools/gyp/pylib/gyp/MSVSSettings.py index 6b364826a5e..bf3cc7300fd 100644 --- a/tools/gyp/pylib/gyp/MSVSSettings.py +++ b/tools/gyp/pylib/gyp/MSVSSettings.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # Copyright (c) 2011 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/tools/gyp/pylib/gyp/MSVSSettings_test.py b/tools/gyp/pylib/gyp/MSVSSettings_test.py index 199f98b1b3f..49e8a1d57fb 100644..100755 --- a/tools/gyp/pylib/gyp/MSVSSettings_test.py +++ b/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. # 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._ExpectedWarnings([]) + if __name__ == '__main__': unittest.main() diff --git a/tools/gyp/pylib/gyp/MSVSToolFile.py b/tools/gyp/pylib/gyp/MSVSToolFile.py index fcad90ad953..25d97a1798e 100644 --- a/tools/gyp/pylib/gyp/MSVSToolFile.py +++ b/tools/gyp/pylib/gyp/MSVSToolFile.py @@ -1,5 +1,3 @@ -#!/usr/bin/python2.4 - # 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. diff --git a/tools/gyp/pylib/gyp/MSVSUserFile.py b/tools/gyp/pylib/gyp/MSVSUserFile.py index 423649f6344..8cc5def5684 100644 --- a/tools/gyp/pylib/gyp/MSVSUserFile.py +++ b/tools/gyp/pylib/gyp/MSVSUserFile.py @@ -1,5 +1,3 @@ -#!/usr/bin/python2.4 - # 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. diff --git a/tools/gyp/pylib/gyp/MSVSVersion.py b/tools/gyp/pylib/gyp/MSVSVersion.py index fd3e191a498..4958ee0d3dd 100755..100644 --- a/tools/gyp/pylib/gyp/MSVSVersion.py +++ b/tools/gyp/pylib/gyp/MSVSVersion.py @@ -1,4 +1,3 @@ -#!/usr/bin/python # Copyright (c) 2011 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -12,7 +11,7 @@ import subprocess import sys -class VisualStudioVersion: +class VisualStudioVersion(object): """Information regarding a version of Visual Studio.""" def __init__(self, short_name, description, @@ -80,6 +79,7 @@ def _RegistryQueryBase(sysdir, key, value): return None return text + def _RegistryQuery(key, value=None): """Use reg.exe to read a particular key through _RegistryQueryBase. @@ -107,6 +107,7 @@ def _RegistryQuery(key, value=None): raise return text + def _RegistryGetValue(key, value): """Use reg.exe to obtain the value of a registry key. @@ -125,6 +126,7 @@ def _RegistryGetValue(key, value): return None return match.group(1) + def _RegistryKeyExists(key): """Use reg.exe to see if a key exists. diff --git a/tools/gyp/pylib/gyp/SCons.py b/tools/gyp/pylib/gyp/SCons.py index 9c57bcbfc48..568645daa67 100644 --- a/tools/gyp/pylib/gyp/SCons.py +++ b/tools/gyp/pylib/gyp/SCons.py @@ -1,6 +1,4 @@ -#!/usr/bin/env python - -# Copyright (c) 2009 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 # found in the LICENSE file. @@ -196,5 +194,6 @@ TargetMap = { 'loadable_module' : LoadableModuleTarget, } + def Target(spec): return TargetMap[spec.get('type')](spec) diff --git a/tools/gyp/pylib/gyp/__init__.py b/tools/gyp/pylib/gyp/__init__.py index 36d1b996ea5..1402713889a 100644..100755 --- a/tools/gyp/pylib/gyp/__init__.py +++ b/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. # 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 shlex import sys +import traceback # Default debug modes for GYP debug = {} @@ -20,9 +21,18 @@ DEBUG_GENERAL = 'general' DEBUG_VARIABLES = 'variables' DEBUG_INCLUDES = 'includes' + def DebugOutput(mode, message): - if mode in gyp.debug.keys(): - print "%s: %s" % (mode.upper(), message) + if 'all' in gyp.debug.keys() or mode in gyp.debug.keys(): + 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(): extension = '.gyp' @@ -266,8 +276,8 @@ def main(args): help='set DEPTH gyp variable to a relative path to PATH') parser.add_option('-d', '--debug', dest='debug', metavar='DEBUGMODE', action='append', default=[], help='turn on a debugging ' - 'mode for debugging GYP. Supported modes are "variables" ' - 'and "general"') + 'mode for debugging GYP. Supported modes are "variables", ' + '"includes" and "general" or "all" for all of them.') parser.add_option('-S', '--suffix', dest='suffix', default='', help='suffix to add to generated files') parser.add_option('-G', dest='generator_flags', action='append', default=[], @@ -327,16 +337,12 @@ def main(args): options.formats = generate_formats else: # Nothing in the variable, default based on platform. - options.formats = [ {'darwin': 'xcode', - 'win32': 'msvs', - 'cygwin': 'msvs', - 'freebsd7': 'make', - 'freebsd8': 'make', - 'linux2': 'make', - 'linux3': 'make', - 'openbsd4': 'make', - 'openbsd5': 'make', - 'sunos5': 'make',}[sys.platform] ] + if sys.platform == 'darwin': + options.formats = ['xcode'] + elif sys.platform in ('win32', 'cygwin'): + options.formats = ['msvs'] + else: + options.formats = ['make'] if not options.generator_output and options.use_environment: g_o = os.environ.get('GYP_GENERATOR_OUTPUT') diff --git a/tools/gyp/pylib/gyp/common.py b/tools/gyp/pylib/gyp/common.py index 880820e330a..b5a6e820494 100644 --- a/tools/gyp/pylib/gyp/common.py +++ b/tools/gyp/pylib/gyp/common.py @@ -1,6 +1,4 @@ -#!/usr/bin/python - -# Copyright (c) 2009 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 # found in the LICENSE file. diff --git a/tools/gyp/pylib/gyp/easy_xml.py b/tools/gyp/pylib/gyp/easy_xml.py index 66241758d07..db54aadbee7 100644 --- a/tools/gyp/pylib/gyp/easy_xml.py +++ b/tools/gyp/pylib/gyp/easy_xml.py @@ -1,5 +1,3 @@ -#!/usr/bin/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. diff --git a/tools/gyp/pylib/gyp/easy_xml_test.py b/tools/gyp/pylib/gyp/easy_xml_test.py index 9e59559818e..a2aa4f20c26 100644..100755 --- a/tools/gyp/pylib/gyp/easy_xml_test.py +++ b/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. # Use of this source code is governed by a BSD-style license that can be diff --git a/tools/gyp/pylib/gyp/generator/dump_dependency_json.py b/tools/gyp/pylib/gyp/generator/dump_dependency_json.py index ebb7ff97bea..ada1d35b070 100644 --- a/tools/gyp/pylib/gyp/generator/dump_dependency_json.py +++ b/tools/gyp/pylib/gyp/generator/dump_dependency_json.py @@ -1,5 +1,3 @@ -#!/usr/bin/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. @@ -8,18 +6,18 @@ import collections import gyp import gyp.common import json +import sys generator_wants_static_library_dependencies_adjusted = False generator_default_variables = { - 'OS': 'linux', } for dirname in ['INTERMEDIATE_DIR', 'SHARED_INTERMEDIATE_DIR', 'PRODUCT_DIR', 'LIB_DIR', 'SHARED_LIB_DIR']: # Some gyp steps fail if these are empty(!). generator_default_variables[dirname] = 'dir' 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', 'STATIC_LIB_PREFIX', 'STATIC_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] = '' +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): 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): diff --git a/tools/gyp/pylib/gyp/generator/gypd.py b/tools/gyp/pylib/gyp/generator/gypd.py index eeb8d5756e7..22ef57f847d 100644 --- a/tools/gyp/pylib/gyp/generator/gypd.py +++ b/tools/gyp/pylib/gyp/generator/gypd.py @@ -1,5 +1,3 @@ -#!/usr/bin/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. diff --git a/tools/gyp/pylib/gyp/generator/gypsh.py b/tools/gyp/pylib/gyp/generator/gypsh.py index 75d20f5813c..bd405f43a99 100644 --- a/tools/gyp/pylib/gyp/generator/gypsh.py +++ b/tools/gyp/pylib/gyp/generator/gypsh.py @@ -1,5 +1,3 @@ -#!/usr/bin/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. diff --git a/tools/gyp/pylib/gyp/generator/make.py b/tools/gyp/pylib/gyp/generator/make.py index 1007672ad88..39713606189 100644 --- a/tools/gyp/pylib/gyp/generator/make.py +++ b/tools/gyp/pylib/gyp/generator/make.py @@ -1,5 +1,3 @@ -#!/usr/bin/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. @@ -26,21 +24,18 @@ import gyp import gyp.common import gyp.system_test -import os.path import os +import re +import shlex import sys -# Debugging-related imports -- remove me once we're solid. -import code -import pprint - generator_default_variables = { 'EXECUTABLE_PREFIX': '', 'EXECUTABLE_SUFFIX': '', 'STATIC_LIB_PREFIX': 'lib', 'SHARED_LIB_PREFIX': 'lib', 'STATIC_LIB_SUFFIX': '.a', - 'INTERMEDIATE_DIR': '$(obj).$(TOOLSET)/geni', + 'INTERMEDIATE_DIR': '$(obj).$(TOOLSET)/$(TARGET)/geni', 'SHARED_INTERMEDIATE_DIR': '$(obj)/gen', 'PRODUCT_DIR': '$(builddir)', 'RULE_INPUT_ROOT': '%(INPUT_ROOT)s', # This gets expanded by Python. @@ -452,10 +447,10 @@ $(if $(or $(command_changed),$(prereq_changed)), ) endef -# Declare "all" target first so it is the default, even though we don't have the -# deps yet. -.PHONY: all -all: +# Declare the "%(default_target)s" target first so it is the default, +# even though we don't have the deps yet. +.PHONY: %(default_target)s +%(default_target)s: # Use FORCE_DO_CMD to force a target to run. Should be coupled with # do_cmd. @@ -489,6 +484,9 @@ cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@" quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@ 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 = """ @@ -901,8 +899,6 @@ class XcodeSettings(object): self._WarnUnimplemented('GCC_DEBUGGING_SYMBOLS') self._WarnUnimplemented('GCC_ENABLE_OBJC_EXCEPTIONS') 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. self._WarnUnimplemented('MACH_O_TYPE') @@ -917,7 +913,7 @@ class XcodeSettings(object): config = self.spec['configurations'][self.configname] framework_dirs = config.get('mac_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 return cflags @@ -1499,6 +1495,12 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD 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 # build which links to shared libs from this build. # 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: mkdirs = 'mkdir -p %s; ' % ' '.join(dirs) 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 # build which links to shared libs from this build. # 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; " "export LD_LIBRARY_PATH; " "%(cd_action)s%(mkdirs)s%(action)s" % { - 'action': gyp.common.EncodePOSIXShellList(action), + 'action': action, 'cd_action': cd_action, 'count': count, 'mkdirs': mkdirs, @@ -1666,6 +1677,7 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD outputs = [] for copy in copies: for path in copy['files']: + # Absolutify() calls normpath, stripping trailing slashes. path = Sourceify(self.Absolutify(path)) filename = os.path.split(path)[1] 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, ( "Spaces in resource filenames not supported (%s)" % 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'] - dest_plist = os.path.join(path, self.xcode_settings.GetBundlePlistPath()) + dest_plist = os.path.join(path, settings.GetBundlePlistPath()) 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.. self.WriteXcodeEnv(dest_plist, spec, additional_settings=extra_settings) 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, # so we need lots of escaping. 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) libraries = spec.get('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 'FULL_PRODUCT_NAME' : product_name, 'SRCROOT' : srcroot, + 'SOURCE_ROOT': '$(SRCROOT)', # This is not true for static libraries, but currently the env is only # written for bundles: 'TARGET_BUILD_DIR' : built_products_dir, @@ -2453,14 +2487,66 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD # GetXcodeEnv() for the full rationale. keys_to_not_absolutify = ('PRODUCT_NAME', 'FULL_PRODUCT_NAME') - # Perform some transformations that are required to mimic Xcode behavior. - for k in env: - # 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 - # not needed and it's undefined how multi-valued keys should be written. - if not isinstance(env[k], str): + # First sort the list of keys, removing any non-string values. + # 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 + # not needed and it's undefined how multi-valued keys should be written. + key_list = env.keys() + 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 + 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 # foo := a\ b # 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. Skips over paths that contain variables.""" 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)) @@ -2634,6 +2722,7 @@ def GenerateOutput(target_list, target_dicts, data, params): generator_flags = params.get('generator_flags', {}) builddir_name = generator_flags.get('output_dir', 'out') android_ndk_version = generator_flags.get('android_ndk_version', None) + default_target = generator_flags.get('default_target', 'all') def CalculateMakefilePath(build_file, base_name): """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' header_params = { + 'default_target': default_target, 'builddir': builddir_name, 'default_configuration': default_configuration, 'flock': flock_command, @@ -2714,7 +2804,8 @@ def GenerateOutput(target_list, target_dicts, data, params): if value[0] != '$': value = '$(abspath %s)' % value 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']: make_global_settings += ( 'ifneq (,$(filter $(origin %s), undefined default))\n' % key) diff --git a/tools/gyp/pylib/gyp/generator/msvs.py b/tools/gyp/pylib/gyp/generator/msvs.py index 0efea704705..e9ead80d6a2 100644 --- a/tools/gyp/pylib/gyp/generator/msvs.py +++ b/tools/gyp/pylib/gyp/generator/msvs.py @@ -1,5 +1,3 @@ -#!/usr/bin/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. diff --git a/tools/gyp/pylib/gyp/generator/msvs_test.py b/tools/gyp/pylib/gyp/generator/msvs_test.py index 60d25abe095..5a69c1c288a 100644..100755 --- a/tools/gyp/pylib/gyp/generator/msvs_test.py +++ b/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. # Use of this source code is governed by a BSD-style license that can be diff --git a/tools/gyp/pylib/gyp/generator/ninja.py b/tools/gyp/pylib/gyp/generator/ninja.py index f044f3746ca..b307da650d9 100644 --- a/tools/gyp/pylib/gyp/generator/ninja.py +++ b/tools/gyp/pylib/gyp/generator/ninja.py @@ -1,5 +1,3 @@ -#!/usr/bin/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. @@ -65,12 +63,6 @@ def QuoteShellArgument(arg): return "'" + arg.replace("'", "'" + '"\'"' + "'") + "'" -def MaybeQuoteShellArgument(arg): - if '"' in arg or ' ' in arg: - return QuoteShellArgument(arg) - return arg - - def InvertRelativePath(path): """Given a relative path like foo/bar, return the inverse relative path: the path from the relative path back to the origin dir. @@ -154,6 +146,15 @@ class NinjaWriter: 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): """Translate a gyp path to a ninja path. @@ -211,7 +212,8 @@ class NinjaWriter: def WriteSpec(self, spec, config): """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.toolset = spec['toolset'] @@ -226,43 +228,56 @@ class NinjaWriter: spec['type'] = 'none' # Compute predepends for all rules. - # prebuild is the dependencies this target depends on before - # running any of its internal steps. - prebuild = [] + # actions_depends is the dependencies this target depends on before running + # any of its action/rule/copy steps. + # compile_depends is the dependencies this target depends on before running + # any of its compile steps. + actions_depends = [] + compile_depends = [] if 'dependencies' in spec: for dep in spec['dependencies']: if dep in self.target_outputs: - prebuild.append(self.target_outputs[dep][0]) - prebuild = self.WriteCollapsedDependencies('predepends', prebuild) + input, precompile_input, linkable = self.target_outputs[dep] + 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 # compile any sources, so compute a list of predependencies for sources # while we do it. extra_sources = [] - sources_predepends = self.WriteActionsRulesCopies(spec, extra_sources, - prebuild) + sources_depends = self.WriteActionsRulesCopies(spec, extra_sources, + 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. link_deps = [] sources = spec.get('sources', []) + extra_sources if sources: - link_deps = self.WriteSources(config, sources, - sources_predepends or prebuild) + link_deps = self.WriteSources(config, sources, compile_depends) # Some actions/rules output 'sources' that are already object files. 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 # above steps. output = None - final_deps = link_deps or sources_predepends or prebuild + final_deps = link_deps or sources_depends or actions_depends 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': # 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 # able to run actions and build libraries by their short name. self.ninja.build(self.name, 'phony', output) - return output + return output, compile_depends def WriteActionsRulesCopies(self, spec, extra_sources, prebuild): """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. outputs = [] for output in rule['outputs']: - outputs.append(output.replace( - generator_default_variables['RULE_INPUT_ROOT'], root).replace( - generator_default_variables['RULE_INPUT_DIRNAME'], dirname)) + outputs.append(self.ExpandRuleVariables(output, root, dirname, + source, ext, basename)) if int(rule.get('process_outputs_as_sources', False)): extra_sources += outputs @@ -409,14 +423,17 @@ class NinjaWriter: self.ninja.variable('cxx', '$cxx_host') self.WriteVariableList('defines', - ['-D' + MaybeQuoteShellArgument(ninja_syntax.escape(d)) + [QuoteShellArgument(ninja_syntax.escape('-D' + d)) for d in config.get('defines', [])]) self.WriteVariableList('includes', ['-I' + self.GypPathToNinja(i) for i in config.get('include_dirs', [])]) - self.WriteVariableList('cflags', config.get('cflags')) - self.WriteVariableList('cflags_c', config.get('cflags_c')) - self.WriteVariableList('cflags_cc', config.get('cflags_cc')) + self.WriteVariableList('cflags', map(self.ExpandSpecial, + config.get('cflags', []))) + 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() outputs = [] for source in sources: @@ -437,7 +454,7 @@ class NinjaWriter: self.ninja.newline() return outputs - def WriteTarget(self, spec, config, final_deps): + def WriteTarget(self, spec, config, final_deps, order_only): if spec['type'] == 'none': # This target doesn't have any explicit final output, but is instead # used for its effects before the final output (e.g. copies steps). @@ -460,7 +477,7 @@ class NinjaWriter: if output_uses_linker: extra_deps = set() 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: continue if linkable: @@ -494,6 +511,7 @@ class NinjaWriter: self.ninja.build(output, command, final_deps, implicit=list(implicit_deps), + order_only=order_only, variables=extra_bindings) return output @@ -711,10 +729,10 @@ def GenerateOutput(target_list, target_dicts, data, params): output_file))) master_ninja.subninja(output_file) - output = writer.WriteSpec(spec, config) + output, compile_depends = writer.WriteSpec(spec, config) if output: 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: all_outputs.add(output) diff --git a/tools/gyp/pylib/gyp/generator/scons.py b/tools/gyp/pylib/gyp/generator/scons.py index 623c6d5a9f6..90418875af4 100644 --- a/tools/gyp/pylib/gyp/generator/scons.py +++ b/tools/gyp/pylib/gyp/generator/scons.py @@ -1,5 +1,3 @@ -#!/usr/bin/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. diff --git a/tools/gyp/pylib/gyp/generator/xcode.py b/tools/gyp/pylib/gyp/generator/xcode.py index f905efdd896..8b17517b76c 100644 --- a/tools/gyp/pylib/gyp/generator/xcode.py +++ b/tools/gyp/pylib/gyp/generator/xcode.py @@ -1,5 +1,3 @@ -#!/usr/bin/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. @@ -1161,7 +1159,7 @@ exit 1 if support_xct: support_xct.AddDependency(xcode_targets[dependency]) - if spec['type'] != 'none' and 'libraries' in spec: + if 'libraries' in spec: for library in spec['libraries']: xct.FrameworksPhase().AddFile(library) # Add the library's directory to LIBRARY_SEARCH_PATHS if necessary. diff --git a/tools/gyp/pylib/gyp/input.py b/tools/gyp/pylib/gyp/input.py index 4204f63276e..ef30efa4dab 100644 --- a/tools/gyp/pylib/gyp/input.py +++ b/tools/gyp/pylib/gyp/input.py @@ -1,5 +1,3 @@ -#!/usr/bin/python - # Copyright (c) 2011 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/tools/gyp/pylib/gyp/mac_tool.py b/tools/gyp/pylib/gyp/mac_tool.py index b64ea986ae2..64707762d3b 100644..100755 --- a/tools/gyp/pylib/gyp/mac_tool.py +++ b/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. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -16,10 +16,12 @@ import string import subprocess import sys + def main(args): executor = MacTool() executor.Dispatch(args) + class MacTool(object): """This class performs all the Mac tooling steps. The methods can either be executed directly, or dispatched from an argument list.""" @@ -185,5 +187,6 @@ class MacTool(object): else: return None + if __name__ == '__main__': sys.exit(main(sys.argv[1:])) diff --git a/tools/gyp/pylib/gyp/ninja_syntax.py b/tools/gyp/pylib/gyp/ninja_syntax.py index a8735225b19..d4776fb236e 100644 --- a/tools/gyp/pylib/gyp/ninja_syntax.py +++ b/tools/gyp/pylib/gyp/ninja_syntax.py @@ -1,5 +1,3 @@ -#!/usr/bin/python - # This file comes from # https://github.com/martine/ninja/blob/master/misc/ninja_syntax.py # Do not edit! Edit the upstream one instead. diff --git a/tools/gyp/pylib/gyp/sun_tool.py b/tools/gyp/pylib/gyp/sun_tool.py index fe5d97dcc86..90d59c82409 100644..100755 --- a/tools/gyp/pylib/gyp/sun_tool.py +++ b/tools/gyp/pylib/gyp/sun_tool.py @@ -12,58 +12,12 @@ import struct import subprocess 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): 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.""" @@ -92,5 +46,6 @@ class SunTool(object): fcntl.fcntl(fd, fcntl.F_SETLK, op) return subprocess.call(cmd_list) + if __name__ == '__main__': sys.exit(main(sys.argv[1:])) diff --git a/tools/gyp/pylib/gyp/system_test.py b/tools/gyp/pylib/gyp/system_test.py index 887d57d4f72..4245f86e112 100644..100755 --- a/tools/gyp/pylib/gyp/system_test.py +++ b/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. # Use of this source code is governed by a BSD-style license that can be @@ -9,6 +9,7 @@ import tempfile import shutil import subprocess + def TestCommands(commands, files={}, env={}): """Run commands in a temporary directory, returning true if they all succeed. Return false on failures or if any commands produce output. @@ -64,7 +65,7 @@ def TestLinkerSupportsICF(cc_command='cc'): env={'cc': cc_command}) -if __name__ == '__main__': +def main(): # Run the various test functions and print the results. def RunTest(description, function, **kwargs): print "Testing " + description + ':', @@ -75,3 +76,8 @@ if __name__ == '__main__': RunTest("ar 'T' flag", TestArSupportsT) RunTest("ar 'T' flag with ccache", TestArSupportsT, cc_command='ccache cc') RunTest("ld --threads", TestLinkerSupportsThreads) + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/tools/gyp/pylib/gyp/xcodeproj_file.py b/tools/gyp/pylib/gyp/xcodeproj_file.py index fcf9abfe473..f6ee765d593 100644 --- a/tools/gyp/pylib/gyp/xcodeproj_file.py +++ b/tools/gyp/pylib/gyp/xcodeproj_file.py @@ -1,5 +1,3 @@ -#!/usr/bin/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. @@ -13,8 +11,8 @@ Xcode.app and observing the resultant changes in the associated project files. XCODE PROJECT FILES -The generator targets the file format as written by Xcode 3.1 (specifically, -3.1.2), but past experience has taught that the format has not changed +The generator targets the file format as written by Xcode 3.2 (specifically, +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 to read older project files. @@ -2444,7 +2442,7 @@ class PBXProject(XCContainerPortal): 'attributes': [0, dict, 0, 0], 'buildConfigurationList': [0, XCConfigurationList, 1, 1, XCConfigurationList()], - 'compatibilityVersion': [0, str, 0, 1, 'Xcode 3.1'], + 'compatibilityVersion': [0, str, 0, 1, 'Xcode 3.2'], 'hasScannedForEncodings': [0, int, 0, 1, 1], 'mainGroup': [0, PBXGroup, 1, 1, PBXGroup()], 'projectDirPath': [0, str, 0, 1, ''], diff --git a/tools/gyp/pylib/gyp/xml_fix.py b/tools/gyp/pylib/gyp/xml_fix.py index 20f782d2832..5de848158d2 100644 --- a/tools/gyp/pylib/gyp/xml_fix.py +++ b/tools/gyp/pylib/gyp/xml_fix.py @@ -1,4 +1,3 @@ -#!/usr/bin/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. diff --git a/tools/gyp/pylintrc b/tools/gyp/pylintrc new file mode 100644 index 00000000000..d7c23d2a211 --- /dev/null +++ b/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 diff --git a/tools/gyp/test/actions-bare/gyptest-bare.py b/tools/gyp/test/actions-bare/gyptest-bare.py new file mode 100755 index 00000000000..b0c10938d1d --- /dev/null +++ b/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() diff --git a/tools/gyp/test/actions-bare/src/bare.gyp b/tools/gyp/test/actions-bare/src/bare.gyp new file mode 100644 index 00000000000..3d28f099d44 --- /dev/null +++ b/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, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/actions-bare/src/bare.py b/tools/gyp/test/actions-bare/src/bare.py new file mode 100755 index 00000000000..12307500f2d --- /dev/null +++ b/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() diff --git a/tools/gyp/test/actions-multiple/gyptest-all.py b/tools/gyp/test/actions-multiple/gyptest-all.py new file mode 100755 index 00000000000..7b94fef4088 --- /dev/null +++ b/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() diff --git a/tools/gyp/test/actions-multiple/src/actions.gyp b/tools/gyp/test/actions-multiple/src/actions.gyp new file mode 100644 index 00000000000..2d721ff61ad --- /dev/null +++ b/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, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/actions-multiple/src/copy.py b/tools/gyp/test/actions-multiple/src/copy.py new file mode 100755 index 00000000000..07746793806 --- /dev/null +++ b/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]) diff --git a/tools/gyp/test/actions-multiple/src/filter.py b/tools/gyp/test/actions-multiple/src/filter.py new file mode 100755 index 00000000000..f61a5fa59a9 --- /dev/null +++ b/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() diff --git a/tools/gyp/test/actions-multiple/src/foo.c b/tools/gyp/test/actions-multiple/src/foo.c new file mode 100644 index 00000000000..23c4ef7f26f --- /dev/null +++ b/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"); +} diff --git a/tools/gyp/test/actions-multiple/src/input.txt b/tools/gyp/test/actions-multiple/src/input.txt new file mode 100644 index 00000000000..c7c7da3c64e --- /dev/null +++ b/tools/gyp/test/actions-multiple/src/input.txt @@ -0,0 +1 @@ +hello there diff --git a/tools/gyp/test/actions-multiple/src/main.c b/tools/gyp/test/actions-multiple/src/main.c new file mode 100644 index 00000000000..0a420b90343 --- /dev/null +++ b/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; +} diff --git a/tools/gyp/test/actions-subdir/gyptest-action.py b/tools/gyp/test/actions-subdir/gyptest-action.py new file mode 100755 index 00000000000..09cfef1893d --- /dev/null +++ b/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() diff --git a/tools/gyp/test/actions-subdir/src/make-file.py b/tools/gyp/test/actions-subdir/src/make-file.py new file mode 100755 index 00000000000..74e55811d23 --- /dev/null +++ b/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) diff --git a/tools/gyp/test/actions-subdir/src/none.gyp b/tools/gyp/test/actions-subdir/src/none.gyp new file mode 100644 index 00000000000..23f8d25a53e --- /dev/null +++ b/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', + ], + }, + ], +} diff --git a/tools/gyp/test/actions-subdir/src/subdir/make-subdir-file.py b/tools/gyp/test/actions-subdir/src/subdir/make-subdir-file.py new file mode 100755 index 00000000000..80ce19ae0ea --- /dev/null +++ b/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) diff --git a/tools/gyp/test/actions-subdir/src/subdir/subdir.gyp b/tools/gyp/test/actions-subdir/src/subdir/subdir.gyp new file mode 100644 index 00000000000..0315d4eb83f --- /dev/null +++ b/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, + } + ], + }, + ], +} diff --git a/tools/gyp/test/actions/gyptest-all.py b/tools/gyp/test/actions/gyptest-all.py new file mode 100755 index 00000000000..ad04f1f2819 --- /dev/null +++ b/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() diff --git a/tools/gyp/test/actions/gyptest-default.py b/tools/gyp/test/actions/gyptest-default.py new file mode 100755 index 00000000000..b5bf7e99d97 --- /dev/null +++ b/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() diff --git a/tools/gyp/test/actions/gyptest-errors.py b/tools/gyp/test/actions/gyptest-errors.py new file mode 100755 index 00000000000..e1ef883e1e8 --- /dev/null +++ b/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() diff --git a/tools/gyp/test/actions/src/action_missing_name.gyp b/tools/gyp/test/actions/src/action_missing_name.gyp new file mode 100644 index 00000000000..00424c35a11 --- /dev/null +++ b/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\'', + ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/actions/src/actions.gyp b/tools/gyp/test/actions/src/actions.gyp new file mode 100644 index 00000000000..5d2db1955e2 --- /dev/null +++ b/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, + }], + }, + + ], +} diff --git a/tools/gyp/test/actions/src/confirm-dep-files.py b/tools/gyp/test/actions/src/confirm-dep-files.py new file mode 100755 index 00000000000..3b8463057df --- /dev/null +++ b/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") diff --git a/tools/gyp/test/actions/src/subdir1/counter.py b/tools/gyp/test/actions/src/subdir1/counter.py new file mode 100755 index 00000000000..3612d7d2bfb --- /dev/null +++ b/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) diff --git a/tools/gyp/test/actions/src/subdir1/executable.gyp b/tools/gyp/test/actions/src/subdir1/executable.gyp new file mode 100644 index 00000000000..6a1ce4f91e0 --- /dev/null +++ b/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, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/actions/src/subdir1/make-prog1.py b/tools/gyp/test/actions/src/subdir1/make-prog1.py new file mode 100755 index 00000000000..7ea1d8a2d48 --- /dev/null +++ b/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) diff --git a/tools/gyp/test/actions/src/subdir1/make-prog2.py b/tools/gyp/test/actions/src/subdir1/make-prog2.py new file mode 100755 index 00000000000..0bfe4973c24 --- /dev/null +++ b/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) diff --git a/tools/gyp/test/actions/src/subdir1/program.c b/tools/gyp/test/actions/src/subdir1/program.c new file mode 100644 index 00000000000..d5f661d905b --- /dev/null +++ b/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;
+}
diff --git a/tools/gyp/test/actions/src/subdir2/make-file.py b/tools/gyp/test/actions/src/subdir2/make-file.py new file mode 100755 index 00000000000..fff06531447 --- /dev/null +++ b/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) diff --git a/tools/gyp/test/actions/src/subdir2/none.gyp b/tools/gyp/test/actions/src/subdir2/none.gyp new file mode 100644 index 00000000000..2caa97d55c9 --- /dev/null +++ b/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, + } + ], + }, + ], +} diff --git a/tools/gyp/test/actions/src/subdir3/generate_main.py b/tools/gyp/test/actions/src/subdir3/generate_main.py new file mode 100755 index 00000000000..b90b3aa6d19 --- /dev/null +++ b/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) diff --git a/tools/gyp/test/actions/src/subdir3/null_input.gyp b/tools/gyp/test/actions/src/subdir3/null_input.gyp new file mode 100644 index 00000000000..9b0bea5fdb4 --- /dev/null +++ b/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, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/additional-targets/gyptest-additional.py b/tools/gyp/test/additional-targets/gyptest-additional.py new file mode 100755 index 00000000000..af35b33de6a --- /dev/null +++ b/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() diff --git a/tools/gyp/test/additional-targets/src/all.gyp b/tools/gyp/test/additional-targets/src/all.gyp new file mode 100644 index 00000000000..21c83080aaf --- /dev/null +++ b/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:*'], + }, + ], +} diff --git a/tools/gyp/test/additional-targets/src/dir1/actions.gyp b/tools/gyp/test/additional-targets/src/dir1/actions.gyp new file mode 100644 index 00000000000..5089c809131 --- /dev/null +++ b/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'], + }, + }], + ], +} diff --git a/tools/gyp/test/additional-targets/src/dir1/emit.py b/tools/gyp/test/additional-targets/src/dir1/emit.py new file mode 100755 index 00000000000..fd3138738ed --- /dev/null +++ b/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() diff --git a/tools/gyp/test/additional-targets/src/dir1/lib1.c b/tools/gyp/test/additional-targets/src/dir1/lib1.c new file mode 100644 index 00000000000..df4cb10f796 --- /dev/null +++ b/tools/gyp/test/additional-targets/src/dir1/lib1.c @@ -0,0 +1,6 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int func1(void) { + return 42; +} diff --git a/tools/gyp/test/assembly/gyptest-assembly.py b/tools/gyp/test/assembly/gyptest-assembly.py new file mode 100755 index 00000000000..09d612b9455 --- /dev/null +++ b/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() diff --git a/tools/gyp/test/assembly/src/as.bat b/tools/gyp/test/assembly/src/as.bat new file mode 100644 index 00000000000..0a47382cb74 --- /dev/null +++ b/tools/gyp/test/assembly/src/as.bat @@ -0,0 +1,4 @@ +@echo off +:: Mock windows assembler. +cl /c %1 /Fo"%2" + diff --git a/tools/gyp/test/assembly/src/assembly.gyp b/tools/gyp/test/assembly/src/assembly.gyp new file mode 100644 index 00000000000..872dd5ec0c0 --- /dev/null +++ b/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, + }, + ], + }, + },], + ], +} diff --git a/tools/gyp/test/assembly/src/lib1.S b/tools/gyp/test/assembly/src/lib1.S new file mode 100644 index 00000000000..e7102bf249c --- /dev/null +++ b/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 diff --git a/tools/gyp/test/assembly/src/lib1.c b/tools/gyp/test/assembly/src/lib1.c new file mode 100644 index 00000000000..be21ecd5f6a --- /dev/null +++ b/tools/gyp/test/assembly/src/lib1.c @@ -0,0 +1,3 @@ +int lib1_function(void) { + return 42; +} diff --git a/tools/gyp/test/assembly/src/program.c b/tools/gyp/test/assembly/src/program.c new file mode 100644 index 00000000000..ecce3b0bbbe --- /dev/null +++ b/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; +} diff --git a/tools/gyp/test/builddir/gyptest-all.py b/tools/gyp/test/builddir/gyptest-all.py new file mode 100755 index 00000000000..885d680bd02 --- /dev/null +++ b/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() diff --git a/tools/gyp/test/builddir/gyptest-default.py b/tools/gyp/test/builddir/gyptest-default.py new file mode 100755 index 00000000000..8c6302618fa --- /dev/null +++ b/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() diff --git a/tools/gyp/test/builddir/src/builddir.gypi b/tools/gyp/test/builddir/src/builddir.gypi new file mode 100644 index 00000000000..e3c61475b57 --- /dev/null +++ b/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', + }, +} diff --git a/tools/gyp/test/builddir/src/func1.c b/tools/gyp/test/builddir/src/func1.c new file mode 100644 index 00000000000..b8e6a06951c --- /dev/null +++ b/tools/gyp/test/builddir/src/func1.c @@ -0,0 +1,6 @@ +#include <stdio.h> + +void func1(void) +{ + printf("Hello from func1.c\n"); +} diff --git a/tools/gyp/test/builddir/src/func2.c b/tools/gyp/test/builddir/src/func2.c new file mode 100644 index 00000000000..14aabac475a --- /dev/null +++ b/tools/gyp/test/builddir/src/func2.c @@ -0,0 +1,6 @@ +#include <stdio.h> + +void func2(void) +{ + printf("Hello from func2.c\n"); +} diff --git a/tools/gyp/test/builddir/src/func3.c b/tools/gyp/test/builddir/src/func3.c new file mode 100644 index 00000000000..3b4edeae6dd --- /dev/null +++ b/tools/gyp/test/builddir/src/func3.c @@ -0,0 +1,6 @@ +#include <stdio.h> + +void func3(void) +{ + printf("Hello from func3.c\n"); +} diff --git a/tools/gyp/test/builddir/src/func4.c b/tools/gyp/test/builddir/src/func4.c new file mode 100644 index 00000000000..732891b79a9 --- /dev/null +++ b/tools/gyp/test/builddir/src/func4.c @@ -0,0 +1,6 @@ +#include <stdio.h> + +void func4(void) +{ + printf("Hello from func4.c\n"); +} diff --git a/tools/gyp/test/builddir/src/func5.c b/tools/gyp/test/builddir/src/func5.c new file mode 100644 index 00000000000..18fdfabbbed --- /dev/null +++ b/tools/gyp/test/builddir/src/func5.c @@ -0,0 +1,6 @@ +#include <stdio.h> + +void func5(void) +{ + printf("Hello from func5.c\n"); +} diff --git a/tools/gyp/test/builddir/src/prog1.c b/tools/gyp/test/builddir/src/prog1.c new file mode 100644 index 00000000000..674ca747b76 --- /dev/null +++ b/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; +} diff --git a/tools/gyp/test/builddir/src/prog1.gyp b/tools/gyp/test/builddir/src/prog1.gyp new file mode 100644 index 00000000000..5b96f035ec7 --- /dev/null +++ b/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', + ], + }, + ], +} diff --git a/tools/gyp/test/builddir/src/subdir2/prog2.c b/tools/gyp/test/builddir/src/subdir2/prog2.c new file mode 100644 index 00000000000..bbdf4f0603d --- /dev/null +++ b/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; +} diff --git a/tools/gyp/test/builddir/src/subdir2/prog2.gyp b/tools/gyp/test/builddir/src/subdir2/prog2.gyp new file mode 100644 index 00000000000..96299b646d2 --- /dev/null +++ b/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', + ], + }, + ], +} diff --git a/tools/gyp/test/builddir/src/subdir2/subdir3/prog3.c b/tools/gyp/test/builddir/src/subdir2/subdir3/prog3.c new file mode 100644 index 00000000000..10c530b23f5 --- /dev/null +++ b/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; +} diff --git a/tools/gyp/test/builddir/src/subdir2/subdir3/prog3.gyp b/tools/gyp/test/builddir/src/subdir2/subdir3/prog3.gyp new file mode 100644 index 00000000000..d7df43c7bde --- /dev/null +++ b/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', + ], + }, + ], +} diff --git a/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/prog4.c b/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/prog4.c new file mode 100644 index 00000000000..dcba9a9d4ae --- /dev/null +++ b/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; +} diff --git a/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/prog4.gyp b/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/prog4.gyp new file mode 100644 index 00000000000..862a8a18cd7 --- /dev/null +++ b/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', + ], + }, + ], +} diff --git a/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.c b/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.c new file mode 100644 index 00000000000..69132e57632 --- /dev/null +++ b/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; +} diff --git a/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.gyp b/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.gyp new file mode 100644 index 00000000000..fe1c9cbf50f --- /dev/null +++ b/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', + ], + }, + ], +} diff --git a/tools/gyp/test/cflags/cflags.c b/tools/gyp/test/cflags/cflags.c new file mode 100644 index 00000000000..c1e2452070c --- /dev/null +++ b/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; +} diff --git a/tools/gyp/test/cflags/cflags.gyp b/tools/gyp/test/cflags/cflags.gyp new file mode 100644 index 00000000000..9003fb16794 --- /dev/null +++ b/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', + ], + }, + ], +} diff --git a/tools/gyp/test/cflags/gyptest-cflags.py b/tools/gyp/test/cflags/gyptest-cflags.py new file mode 100755 index 00000000000..acc424a2c43 --- /dev/null +++ b/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() diff --git a/tools/gyp/test/compilable/gyptest-headers.py b/tools/gyp/test/compilable/gyptest-headers.py new file mode 100755 index 00000000000..91760216fbb --- /dev/null +++ b/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() diff --git a/tools/gyp/test/compilable/src/headers.gyp b/tools/gyp/test/compilable/src/headers.gyp new file mode 100644 index 00000000000..b6c2a8857be --- /dev/null +++ b/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', + ], + }, + ], +} diff --git a/tools/gyp/test/compilable/src/lib1.cpp b/tools/gyp/test/compilable/src/lib1.cpp new file mode 100644 index 00000000000..51bc31a40b8 --- /dev/null +++ b/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); +} diff --git a/tools/gyp/test/compilable/src/lib1.hpp b/tools/gyp/test/compilable/src/lib1.hpp new file mode 100644 index 00000000000..72e63e8acdb --- /dev/null +++ b/tools/gyp/test/compilable/src/lib1.hpp @@ -0,0 +1,6 @@ +#ifndef _lib1_hpp +#define _lib1_hpp + +extern void lib1_function(void); + +#endif diff --git a/tools/gyp/test/compilable/src/program.cpp b/tools/gyp/test/compilable/src/program.cpp new file mode 100644 index 00000000000..81420bad431 --- /dev/null +++ b/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; +} diff --git a/tools/gyp/test/configurations/basics/configurations.c b/tools/gyp/test/configurations/basics/configurations.c new file mode 100644 index 00000000000..6c1f900169e --- /dev/null +++ b/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; +} diff --git a/tools/gyp/test/configurations/basics/configurations.gyp b/tools/gyp/test/configurations/basics/configurations.gyp new file mode 100644 index 00000000000..93f1d8d5c7f --- /dev/null +++ b/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', + ], + }, + } + }, + ], +} diff --git a/tools/gyp/test/configurations/basics/gyptest-configurations.py b/tools/gyp/test/configurations/basics/gyptest-configurations.py new file mode 100755 index 00000000000..27cd2e87d22 --- /dev/null +++ b/tools/gyp/test/configurations/basics/gyptest-configurations.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 build of an executable in three different configurations. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('configurations.gyp') + +test.set_configuration('Release') +test.build('configurations.gyp') +test.run_built_executable('configurations', stdout="Release configuration\n") + +test.set_configuration('Debug') +test.build('configurations.gyp') +test.run_built_executable('configurations', stdout="Debug configuration\n") + +test.set_configuration('Foo') +test.build('configurations.gyp') +test.run_built_executable('configurations', stdout="Foo configuration\n") + +test.pass_test() diff --git a/tools/gyp/test/configurations/inheritance/configurations.c b/tools/gyp/test/configurations/inheritance/configurations.c new file mode 100644 index 00000000000..2d5565eeb54 --- /dev/null +++ b/tools/gyp/test/configurations/inheritance/configurations.c @@ -0,0 +1,21 @@ +#include <stdio.h> + +int main(int argc, char *argv[]) +{ +#ifdef BASE + printf("Base configuration\n"); +#endif +#ifdef COMMON + printf("Common configuration\n"); +#endif +#ifdef COMMON2 + printf("Common2 configuration\n"); +#endif +#ifdef DEBUG + printf("Debug configuration\n"); +#endif +#ifdef RELEASE + printf("Release configuration\n"); +#endif + return 0; +} diff --git a/tools/gyp/test/configurations/inheritance/configurations.gyp b/tools/gyp/test/configurations/inheritance/configurations.gyp new file mode 100644 index 00000000000..9441376b4d1 --- /dev/null +++ b/tools/gyp/test/configurations/inheritance/configurations.gyp @@ -0,0 +1,40 @@ +# 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': { + 'Base': { + 'abstract': 1, + 'defines': ['BASE'], + }, + 'Common': { + 'abstract': 1, + 'inherit_from': ['Base'], + 'defines': ['COMMON'], + }, + 'Common2': { + 'abstract': 1, + 'defines': ['COMMON2'], + }, + 'Debug': { + 'inherit_from': ['Common', 'Common2'], + 'defines': ['DEBUG'], + }, + 'Release': { + 'inherit_from': ['Common', 'Common2'], + 'defines': ['RELEASE'], + }, + }, + }, + 'targets': [ + { + 'target_name': 'configurations', + 'type': 'executable', + 'sources': [ + 'configurations.c', + ], + }, + ], +} diff --git a/tools/gyp/test/configurations/inheritance/gyptest-inheritance.py b/tools/gyp/test/configurations/inheritance/gyptest-inheritance.py new file mode 100755 index 00000000000..22c73a3754d --- /dev/null +++ b/tools/gyp/test/configurations/inheritance/gyptest-inheritance.py @@ -0,0 +1,33 @@ +#!/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 build of an executable in three different configurations. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('configurations.gyp') + +test.set_configuration('Release') +test.build('configurations.gyp') +test.run_built_executable('configurations', + stdout=('Base configuration\n' + 'Common configuration\n' + 'Common2 configuration\n' + 'Release configuration\n')) + +test.set_configuration('Debug') +test.build('configurations.gyp') +test.run_built_executable('configurations', + stdout=('Base configuration\n' + 'Common configuration\n' + 'Common2 configuration\n' + 'Debug configuration\n')) + +test.pass_test() diff --git a/tools/gyp/test/configurations/invalid/actions.gyp b/tools/gyp/test/configurations/invalid/actions.gyp new file mode 100644 index 00000000000..a6e42089eba --- /dev/null +++ b/tools/gyp/test/configurations/invalid/actions.gyp @@ -0,0 +1,18 @@ +# 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': 'configurations', + 'type': 'none', + 'configurations': { + 'Debug': { + 'actions': [ + ], + }, + } + }, + ], +} diff --git a/tools/gyp/test/configurations/invalid/all_dependent_settings.gyp b/tools/gyp/test/configurations/invalid/all_dependent_settings.gyp new file mode 100644 index 00000000000..b16a245df54 --- /dev/null +++ b/tools/gyp/test/configurations/invalid/all_dependent_settings.gyp @@ -0,0 +1,18 @@ +# 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': 'configurations', + 'type': 'none', + 'configurations': { + 'Debug': { + 'all_dependent_settings': [ + ], + }, + } + }, + ], +} diff --git a/tools/gyp/test/configurations/invalid/configurations.gyp b/tools/gyp/test/configurations/invalid/configurations.gyp new file mode 100644 index 00000000000..2cfc9600498 --- /dev/null +++ b/tools/gyp/test/configurations/invalid/configurations.gyp @@ -0,0 +1,18 @@ +# 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': 'configurations', + 'type': 'none', + 'configurations': { + 'Debug': { + 'configurations': [ + ], + }, + } + }, + ], +} diff --git a/tools/gyp/test/configurations/invalid/dependencies.gyp b/tools/gyp/test/configurations/invalid/dependencies.gyp new file mode 100644 index 00000000000..74633f3f111 --- /dev/null +++ b/tools/gyp/test/configurations/invalid/dependencies.gyp @@ -0,0 +1,18 @@ +# 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': 'configurations', + 'type': 'none', + 'configurations': { + 'Debug': { + 'dependencies': [ + ], + }, + } + }, + ], +} diff --git a/tools/gyp/test/configurations/invalid/direct_dependent_settings.gyp b/tools/gyp/test/configurations/invalid/direct_dependent_settings.gyp new file mode 100644 index 00000000000..8a0f2e95ea7 --- /dev/null +++ b/tools/gyp/test/configurations/invalid/direct_dependent_settings.gyp @@ -0,0 +1,18 @@ +# 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': 'configurations', + 'type': 'none', + 'configurations': { + 'Debug': { + 'direct_dependent_settings': [ + ], + }, + } + }, + ], +} diff --git a/tools/gyp/test/configurations/invalid/gyptest-configurations.py b/tools/gyp/test/configurations/invalid/gyptest-configurations.py new file mode 100755 index 00000000000..d76cdedb0c0 --- /dev/null +++ b/tools/gyp/test/configurations/invalid/gyptest-configurations.py @@ -0,0 +1,38 @@ +#!/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 in three different configurations. +""" + +import TestGyp + +# Keys that do not belong inside a configuration dictionary. +invalid_configuration_keys = [ + 'actions', + 'all_dependent_settings', + 'configurations', + 'dependencies', + 'direct_dependent_settings', + 'libraries', + 'link_settings', + 'sources', + 'target_name', + 'type', +] + +test = TestGyp.TestGyp() + +if test.format == 'scons': + test.skip_test('TODO: http://code.google.com/p/gyp/issues/detail?id=176\n') + +for test_key in invalid_configuration_keys: + test.run_gyp('%s.gyp' % test_key, status=1, stderr=None) + expect = ['%s not allowed in the Debug configuration, found in target ' + '%s.gyp:configurations#target' % (test_key, test_key)] + test.must_contain_all_lines(test.stderr(), expect) + +test.pass_test() diff --git a/tools/gyp/test/configurations/invalid/libraries.gyp b/tools/gyp/test/configurations/invalid/libraries.gyp new file mode 100644 index 00000000000..c4014ed4065 --- /dev/null +++ b/tools/gyp/test/configurations/invalid/libraries.gyp @@ -0,0 +1,18 @@ +# 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': 'configurations', + 'type': 'none', + 'configurations': { + 'Debug': { + 'libraries': [ + ], + }, + } + }, + ], +} diff --git a/tools/gyp/test/configurations/invalid/link_settings.gyp b/tools/gyp/test/configurations/invalid/link_settings.gyp new file mode 100644 index 00000000000..2f0e1c46f5c --- /dev/null +++ b/tools/gyp/test/configurations/invalid/link_settings.gyp @@ -0,0 +1,18 @@ +# 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': 'configurations', + 'type': 'none', + 'configurations': { + 'Debug': { + 'link_settings': [ + ], + }, + } + }, + ], +} diff --git a/tools/gyp/test/configurations/invalid/sources.gyp b/tools/gyp/test/configurations/invalid/sources.gyp new file mode 100644 index 00000000000..b38cca03818 --- /dev/null +++ b/tools/gyp/test/configurations/invalid/sources.gyp @@ -0,0 +1,18 @@ +# 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': 'configurations', + 'type': 'none', + 'configurations': { + 'Debug': { + 'sources': [ + ], + }, + } + }, + ], +} diff --git a/tools/gyp/test/configurations/invalid/target_name.gyp b/tools/gyp/test/configurations/invalid/target_name.gyp new file mode 100644 index 00000000000..83baad95d60 --- /dev/null +++ b/tools/gyp/test/configurations/invalid/target_name.gyp @@ -0,0 +1,18 @@ +# 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': 'configurations', + 'type': 'none', + 'configurations': { + 'Debug': { + 'target_name': [ + ], + }, + } + }, + ], +} diff --git a/tools/gyp/test/configurations/invalid/type.gyp b/tools/gyp/test/configurations/invalid/type.gyp new file mode 100644 index 00000000000..bc55898b89e --- /dev/null +++ b/tools/gyp/test/configurations/invalid/type.gyp @@ -0,0 +1,18 @@ +# 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': 'configurations', + 'type': 'none', + 'configurations': { + 'Debug': { + 'type': [ + ], + }, + } + }, + ], +} diff --git a/tools/gyp/test/configurations/target_platform/configurations.gyp b/tools/gyp/test/configurations/target_platform/configurations.gyp new file mode 100644 index 00000000000..d15429f4e5d --- /dev/null +++ b/tools/gyp/test/configurations/target_platform/configurations.gyp @@ -0,0 +1,58 @@ +# 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': { + 'Debug_Win32': { + 'msvs_configuration_platform': 'Win32', + }, + 'Debug_x64': { + 'msvs_configuration_platform': 'x64', + }, + }, + }, + 'targets': [ + { + 'target_name': 'left', + 'type': 'static_library', + 'sources': [ + 'left.c', + ], + 'configurations': { + 'Debug_Win32': { + 'msvs_target_platform': 'x64', + }, + }, + }, + { + 'target_name': 'right', + 'type': 'static_library', + 'sources': [ + 'right.c', + ], + }, + { + 'target_name': 'front_left', + 'type': 'executable', + 'dependencies': ['left'], + 'sources': [ + 'front.c', + ], + 'configurations': { + 'Debug_Win32': { + 'msvs_target_platform': 'x64', + }, + }, + }, + { + 'target_name': 'front_right', + 'type': 'executable', + 'dependencies': ['right'], + 'sources': [ + 'front.c', + ], + }, + ], +} diff --git a/tools/gyp/test/configurations/target_platform/front.c b/tools/gyp/test/configurations/target_platform/front.c new file mode 100644 index 00000000000..12b1d0aa3b9 --- /dev/null +++ b/tools/gyp/test/configurations/target_platform/front.c @@ -0,0 +1,8 @@ +#include <stdio.h> + +const char *message(void); + +int main(int argc, char *argv[]) { + printf("%s\n", message()); + return 0; +} diff --git a/tools/gyp/test/configurations/target_platform/gyptest-target_platform.py b/tools/gyp/test/configurations/target_platform/gyptest-target_platform.py new file mode 100755 index 00000000000..ae4e9e5a2df --- /dev/null +++ b/tools/gyp/test/configurations/target_platform/gyptest-target_platform.py @@ -0,0 +1,40 @@ +#!/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. + +""" +Tests the msvs specific msvs_target_platform option. +""" + +import TestGyp +import TestCommon + + +def RunX64(exe, stdout): + try: + test.run_built_executable(exe, stdout=stdout) + except WindowsError, e: + # Assume the exe is 64-bit if it can't load on 32-bit systems. + # Both versions of the error are required because different versions + # of python seem to return different errors for invalid exe type. + if e.errno != 193 and '[Error 193]' not in str(e): + raise + + +test = TestGyp.TestGyp(formats=['msvs']) + +test.run_gyp('configurations.gyp') + +test.set_configuration('Debug|x64') +test.build('configurations.gyp', rebuild=True) +RunX64('front_left', stdout=('left\n')) +RunX64('front_right', stdout=('right\n')) + +test.set_configuration('Debug|Win32') +test.build('configurations.gyp', rebuild=True) +RunX64('front_left', stdout=('left\n')) +test.run_built_executable('front_right', stdout=('right\n')) + +test.pass_test() diff --git a/tools/gyp/test/configurations/target_platform/left.c b/tools/gyp/test/configurations/target_platform/left.c new file mode 100644 index 00000000000..1ce2ea12272 --- /dev/null +++ b/tools/gyp/test/configurations/target_platform/left.c @@ -0,0 +1,3 @@ +const char *message(void) { + return "left"; +} diff --git a/tools/gyp/test/configurations/target_platform/right.c b/tools/gyp/test/configurations/target_platform/right.c new file mode 100644 index 00000000000..b1578492fe4 --- /dev/null +++ b/tools/gyp/test/configurations/target_platform/right.c @@ -0,0 +1,3 @@ +const char *message(void) { + return "right"; +} diff --git a/tools/gyp/test/configurations/x64/configurations.c b/tools/gyp/test/configurations/x64/configurations.c new file mode 100644 index 00000000000..72c97e31da6 --- /dev/null +++ b/tools/gyp/test/configurations/x64/configurations.c @@ -0,0 +1,12 @@ +#include <stdio.h> + +int main(int argc, char *argv[]) { + if (sizeof(void*) == 4) { + printf("Running Win32\n"); + } else if (sizeof(void*) == 8) { + printf("Running x64\n"); + } else { + printf("Unexpected platform\n"); + } + return 0; +} diff --git a/tools/gyp/test/configurations/x64/configurations.gyp b/tools/gyp/test/configurations/x64/configurations.gyp new file mode 100644 index 00000000000..06ffa3758b8 --- /dev/null +++ b/tools/gyp/test/configurations/x64/configurations.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. + +{ + 'target_defaults': { + 'configurations': { + 'Debug': { + 'msvs_configuration_platform': 'Win32', + }, + 'Debug_x64': { + 'inherit_from': ['Debug'], + 'msvs_configuration_platform': 'x64', + }, + }, + }, + 'targets': [ + { + 'target_name': 'configurations', + 'type': 'executable', + 'sources': [ + 'configurations.c', + ], + }, + ], +} diff --git a/tools/gyp/test/configurations/x64/gyptest-x86.py b/tools/gyp/test/configurations/x64/gyptest-x86.py new file mode 100755 index 00000000000..254ea6fbc0d --- /dev/null +++ b/tools/gyp/test/configurations/x64/gyptest-x86.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 build of an executable in three different configurations. +""" + +import TestGyp + +test = TestGyp.TestGyp(formats=['msvs']) + +test.run_gyp('configurations.gyp') + +for platform in ['Win32', 'x64']: + test.set_configuration('Debug|%s' % platform) + test.build('configurations.gyp', rebuild=True) + try: + test.run_built_executable('configurations', + stdout=('Running %s\n' % platform)) + except WindowsError, e: + # Assume the exe is 64-bit if it can't load on 32-bit systems. + if platform == 'x64' and (e.errno == 193 or '[Error 193]' in str(e)): + continue + raise + +test.pass_test() diff --git a/tools/gyp/test/copies/gyptest-all.py b/tools/gyp/test/copies/gyptest-all.py new file mode 100755 index 00000000000..8542ab7b92c --- /dev/null +++ b/tools/gyp/test/copies/gyptest-all.py @@ -0,0 +1,40 @@ +#!/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 file copies using an explicit build target of 'all'. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('copies.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('copies.gyp', test.ALL, chdir='relocate/src') + +test.must_match(['relocate', 'src', 'copies-out', 'file1'], 'file1 contents\n') + +test.built_file_must_match('copies-out/file2', + 'file2 contents\n', + chdir='relocate/src') + +test.built_file_must_match('copies-out/directory/file3', + 'file3 contents\n', + chdir='relocate/src') +test.built_file_must_match('copies-out/directory/file4', + 'file4 contents\n', + chdir='relocate/src') +test.built_file_must_match('copies-out/directory/subdir/file5', + 'file5 contents\n', + chdir='relocate/src') +test.built_file_must_match('copies-out/subdir/file6', + 'file6 contents\n', + chdir='relocate/src') + +test.pass_test() diff --git a/tools/gyp/test/copies/gyptest-default.py b/tools/gyp/test/copies/gyptest-default.py new file mode 100755 index 00000000000..a5d1bf9c3c4 --- /dev/null +++ b/tools/gyp/test/copies/gyptest-default.py @@ -0,0 +1,40 @@ +#!/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 file copies using the build tool default. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('copies.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('copies.gyp', chdir='relocate/src') + +test.must_match(['relocate', 'src', 'copies-out', 'file1'], 'file1 contents\n') + +test.built_file_must_match('copies-out/file2', + 'file2 contents\n', + chdir='relocate/src') + +test.built_file_must_match('copies-out/directory/file3', + 'file3 contents\n', + chdir='relocate/src') +test.built_file_must_match('copies-out/directory/file4', + 'file4 contents\n', + chdir='relocate/src') +test.built_file_must_match('copies-out/directory/subdir/file5', + 'file5 contents\n', + chdir='relocate/src') +test.built_file_must_match('copies-out/subdir/file6', + 'file6 contents\n', + chdir='relocate/src') + +test.pass_test() diff --git a/tools/gyp/test/copies/gyptest-slash.py b/tools/gyp/test/copies/gyptest-slash.py new file mode 100755 index 00000000000..81a4f42a323 --- /dev/null +++ b/tools/gyp/test/copies/gyptest-slash.py @@ -0,0 +1,38 @@ +#!/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 file copies with a trailing slash in the destination directory. +""" + +import TestGyp + +test = TestGyp.TestGyp() +test.run_gyp('copies-slash.gyp', chdir='src') +test.relocate('src', 'relocate/src') +test.build('copies-slash.gyp', chdir='relocate/src') + +test.built_file_must_match('copies-out-slash/directory/file3', + 'file3 contents\n', + chdir='relocate/src') +test.built_file_must_match('copies-out-slash/directory/file4', + 'file4 contents\n', + chdir='relocate/src') +test.built_file_must_match('copies-out-slash/directory/subdir/file5', + 'file5 contents\n', + chdir='relocate/src') + +test.built_file_must_match('copies-out-slash-2/directory/file3', + 'file3 contents\n', + chdir='relocate/src') +test.built_file_must_match('copies-out-slash-2/directory/file4', + 'file4 contents\n', + chdir='relocate/src') +test.built_file_must_match('copies-out-slash-2/directory/subdir/file5', + 'file5 contents\n', + chdir='relocate/src') + +test.pass_test() diff --git a/tools/gyp/test/copies/src/copies-slash.gyp b/tools/gyp/test/copies/src/copies-slash.gyp new file mode 100644 index 00000000000..9bf54bd1814 --- /dev/null +++ b/tools/gyp/test/copies/src/copies-slash.gyp @@ -0,0 +1,36 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + # A trailing slash on the destination directory should be ignored. + { + 'target_name': 'copies_recursive_trailing_slash', + 'type': 'none', + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/copies-out-slash/', + 'files': [ + 'directory/', + ], + }, + ], + }, + # Even if the source directory is below <(PRODUCT_DIR). + { + 'target_name': 'copies_recursive_trailing_slash_in_product_dir', + 'type': 'none', + 'dependencies': [ ':copies_recursive_trailing_slash' ], + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/copies-out-slash-2/', + 'files': [ + '<(PRODUCT_DIR)/copies-out-slash/directory/', + ], + }, + ], + }, + ], +} + diff --git a/tools/gyp/test/copies/src/copies.gyp b/tools/gyp/test/copies/src/copies.gyp new file mode 100644 index 00000000000..ce2e0cabca5 --- /dev/null +++ b/tools/gyp/test/copies/src/copies.gyp @@ -0,0 +1,70 @@ +# 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': 'copies1', + 'type': 'none', + 'copies': [ + { + 'destination': 'copies-out', + 'files': [ + 'file1', + ], + }, + ], + }, + { + 'target_name': 'copies2', + 'type': 'none', + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/copies-out', + 'files': [ + 'file2', + ], + }, + ], + }, + # Copy a directory tree. + { + 'target_name': 'copies_recursive', + 'type': 'none', + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/copies-out', + 'files': [ + 'directory/', + ], + }, + ], + }, + # Copy a directory from deeper in the tree (this should not reproduce the + # entire directory path in the destination, only the final directory). + { + 'target_name': 'copies_recursive_depth', + 'type': 'none', + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/copies-out', + 'files': [ + 'parentdir/subdir/', + ], + }, + ], + }, + # Verify that a null 'files' list doesn't gag the generators. + { + 'target_name': 'copies_null', + 'type': 'none', + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/copies-null', + 'files': [], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/copies/src/directory/file3 b/tools/gyp/test/copies/src/directory/file3 new file mode 100644 index 00000000000..43f16f35220 --- /dev/null +++ b/tools/gyp/test/copies/src/directory/file3 @@ -0,0 +1 @@ +file3 contents diff --git a/tools/gyp/test/copies/src/directory/file4 b/tools/gyp/test/copies/src/directory/file4 new file mode 100644 index 00000000000..5f7270a0847 --- /dev/null +++ b/tools/gyp/test/copies/src/directory/file4 @@ -0,0 +1 @@ +file4 contents diff --git a/tools/gyp/test/copies/src/directory/subdir/file5 b/tools/gyp/test/copies/src/directory/subdir/file5 new file mode 100644 index 00000000000..41f47186bd2 --- /dev/null +++ b/tools/gyp/test/copies/src/directory/subdir/file5 @@ -0,0 +1 @@ +file5 contents diff --git a/tools/gyp/test/copies/src/file1 b/tools/gyp/test/copies/src/file1 new file mode 100644 index 00000000000..84d55c5759c --- /dev/null +++ b/tools/gyp/test/copies/src/file1 @@ -0,0 +1 @@ +file1 contents diff --git a/tools/gyp/test/copies/src/file2 b/tools/gyp/test/copies/src/file2 new file mode 100644 index 00000000000..af1b8ae35db --- /dev/null +++ b/tools/gyp/test/copies/src/file2 @@ -0,0 +1 @@ +file2 contents diff --git a/tools/gyp/test/copies/src/parentdir/subdir/file6 b/tools/gyp/test/copies/src/parentdir/subdir/file6 new file mode 100644 index 00000000000..f5d57573486 --- /dev/null +++ b/tools/gyp/test/copies/src/parentdir/subdir/file6 @@ -0,0 +1 @@ +file6 contents diff --git a/tools/gyp/test/cxxflags/cxxflags.cc b/tools/gyp/test/cxxflags/cxxflags.cc new file mode 100644 index 00000000000..c1e2452070c --- /dev/null +++ b/tools/gyp/test/cxxflags/cxxflags.cc @@ -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; +} diff --git a/tools/gyp/test/cxxflags/cxxflags.gyp b/tools/gyp/test/cxxflags/cxxflags.gyp new file mode 100644 index 00000000000..24d883aaed6 --- /dev/null +++ b/tools/gyp/test/cxxflags/cxxflags.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': 'cxxflags', + 'type': 'executable', + 'opt': '-Os', + 'sources': [ + 'cxxflags.cc', + ], + }, + ], +} diff --git a/tools/gyp/test/cxxflags/gyptest-cxxflags.py b/tools/gyp/test/cxxflags/gyptest-cxxflags.py new file mode 100755 index 00000000000..2e5a6d9474a --- /dev/null +++ b/tools/gyp/test/cxxflags/gyptest-cxxflags.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['CXXFLAGS'] = '-O0' + test.run_gyp('cxxflags.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('cxxflags.gyp') + +expect = """\ +Using no optimization flag +""" +test.run_built_executable('cxxflags', stdout=expect) + +test.sleep() + +try: + PushEnv() + os.environ['CXXFLAGS'] = '-O2' + test.run_gyp('cxxflags.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('cxxflags.gyp') + +expect = """\ +Using an optimization flag +""" +test.run_built_executable('cxxflags', stdout=expect) + +test.pass_test() diff --git a/tools/gyp/test/defines-escaping/defines-escaping.c b/tools/gyp/test/defines-escaping/defines-escaping.c new file mode 100644 index 00000000000..440757222e9 --- /dev/null +++ b/tools/gyp/test/defines-escaping/defines-escaping.c @@ -0,0 +1,11 @@ +/* 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[]) +{ + printf(TEST_FORMAT, TEST_ARGS); + return 0; +} diff --git a/tools/gyp/test/defines-escaping/defines-escaping.gyp b/tools/gyp/test/defines-escaping/defines-escaping.gyp new file mode 100644 index 00000000000..6f0f3fde41f --- /dev/null +++ b/tools/gyp/test/defines-escaping/defines-escaping.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. + +{ + 'targets': [ + { + 'target_name': 'defines_escaping', + 'type': 'executable', + 'sources': [ + 'defines-escaping.c', + ], + 'defines': [ + 'TEST_FORMAT="<(test_format)"', + 'TEST_ARGS=<(test_args)', + ], + }, + ], +} diff --git a/tools/gyp/test/defines-escaping/gyptest-defines-escaping.py b/tools/gyp/test/defines-escaping/gyptest-defines-escaping.py new file mode 100755 index 00000000000..eb18a3d369f --- /dev/null +++ b/tools/gyp/test/defines-escaping/gyptest-defines-escaping.py @@ -0,0 +1,184 @@ +#!/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 using +various special characters such as quotes, commas, etc. +""" + +import os +import TestGyp + +test = TestGyp.TestGyp() + +# Tests string literals, percents, and backslash escapes. +try: + os.environ['GYP_DEFINES'] = ( + r"""test_format='\n%s\n' """ + r"""test_args='"Simple test of %s with a literal"'""") + test.run_gyp('defines-escaping.gyp') +finally: + del os.environ['GYP_DEFINES'] + +test.build('defines-escaping.gyp') + +expect = """ +Simple test of %s with a literal +""" +test.run_built_executable('defines_escaping', stdout=expect) + + +# Test multiple comma-and-space-separated string literals. +try: + os.environ['GYP_DEFINES'] = \ + r"""test_format='\n%s and %s\n' test_args='"foo", "bar"'""" + test.run_gyp('defines-escaping.gyp') +finally: + del os.environ['GYP_DEFINES'] + +test.sleep() +test.touch('defines-escaping.c') +test.build('defines-escaping.gyp') + +expect = """ +foo and bar +""" +test.run_built_executable('defines_escaping', stdout=expect) + + +# Test string literals containing quotes. +try: + os.environ['GYP_DEFINES'] = ( + r"""test_format='\n%s %s %s %s %s\n' """ + r"""test_args='"\"These,\"",""" + r""" "\"words,\"",""" + r""" "\"are,\"",""" + r""" "\"in,\"",""" + r""" "\"quotes.\""'""") + test.run_gyp('defines-escaping.gyp') +finally: + del os.environ['GYP_DEFINES'] + +test.sleep() +test.touch('defines-escaping.c') +test.build('defines-escaping.gyp') + +expect = """ +"These," "words," "are," "in," "quotes." +""" +test.run_built_executable('defines_escaping', stdout=expect) + + +# Test string literals containing single quotes. +try: + os.environ['GYP_DEFINES'] = ( + r"""test_format='\n%s %s %s %s %s\n' """ + r"""test_args="\"'These,'\",""" + r""" \"'words,'\",""" + r""" \"'are,'\",""" + r""" \"'in,'\",""" + r""" \"'quotes.'\"" """) + test.run_gyp('defines-escaping.gyp') +finally: + del os.environ['GYP_DEFINES'] + +test.sleep() +test.touch('defines-escaping.c') +test.build('defines-escaping.gyp') + +expect = """ +'These,' 'words,' 'are,' 'in,' 'quotes.' +""" +test.run_built_executable('defines_escaping', stdout=expect) + + +# Test string literals containing different numbers of backslashes before quotes +# (to exercise Windows' quoting behaviour). +try: + os.environ['GYP_DEFINES'] = ( + r"""test_format='\n%s\n%s\n%s\n' """ + r"""test_args='"\\\"1 visible slash\\\"",""" + r""" "\\\\\"2 visible slashes\\\\\"",""" + r""" "\\\\\\\"3 visible slashes\\\\\\\""'""") + test.run_gyp('defines-escaping.gyp') +finally: + del os.environ['GYP_DEFINES'] + +test.sleep() +test.touch('defines-escaping.c') +test.build('defines-escaping.gyp') + +expect = r""" +\"1 visible slash\" +\\"2 visible slashes\\" +\\\"3 visible slashes\\\" +""" +test.run_built_executable('defines_escaping', stdout=expect) + + +# Test that various scary sequences are passed unfettered. +try: + os.environ['GYP_DEFINES'] = ( + r"""test_format='\n%s\n' """ + r"""test_args='"$foo, " `foo`;"'""") + test.run_gyp('defines-escaping.gyp') +finally: + del os.environ['GYP_DEFINES'] + +test.sleep() +test.touch('defines-escaping.c') +test.build('defines-escaping.gyp') + +expect = """ +$foo, " `foo`; +""" +test.run_built_executable('defines_escaping', stdout=expect) + + +# VisualStudio 2010 can't handle passing %PATH% +if not (test.format == 'msvs' and test.uses_msbuild): + try: + os.environ['GYP_DEFINES'] = ( + """test_format='%s' """ + """test_args='"%PATH%"'""") + test.run_gyp('defines-escaping.gyp') + finally: + del os.environ['GYP_DEFINES'] + + test.sleep() + test.touch('defines-escaping.c') + test.build('defines-escaping.gyp') + + expect = "%PATH%" + test.run_built_executable('defines_escaping', stdout=expect) + + +# Test commas and semi-colons preceded by backslashes (to exercise Windows' +# quoting behaviour). +try: + os.environ['GYP_DEFINES'] = ( + r"""test_format='\n%s\n%s\n' """ + r"""test_args='"\\, \\\\;",""" + # Same thing again, but enclosed in visible quotes. + r""" "\"\\, \\\\;\""'""") + test.run_gyp('defines-escaping.gyp') +finally: + del os.environ['GYP_DEFINES'] + +test.sleep() +test.touch('defines-escaping.c') +test.build('defines-escaping.gyp') + +expect = r""" +\, \\; +"\, \\;" +""" +test.run_built_executable('defines_escaping', stdout=expect) + +# We deliberately do not test having an odd number of quotes in a string +# literal because that isn't feasible in MSVS. + +test.pass_test() diff --git a/tools/gyp/test/defines/defines-env.gyp b/tools/gyp/test/defines/defines-env.gyp new file mode 100644 index 00000000000..1781546ae08 --- /dev/null +++ b/tools/gyp/test/defines/defines-env.gyp @@ -0,0 +1,22 @@ +# 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. + +{ + 'variables': { + 'value%': '5', + }, + 'targets': [ + { + 'target_name': 'defines', + 'type': 'executable', + 'sources': [ + 'defines.c', + ], + 'defines': [ + 'VALUE=<(value)', + ], + }, + ], +} + diff --git a/tools/gyp/test/defines/defines.c b/tools/gyp/test/defines/defines.c new file mode 100644 index 00000000000..47215490b19 --- /dev/null +++ b/tools/gyp/test/defines/defines.c @@ -0,0 +1,18 @@ +/* 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> + +int main(int argc, char *argv[]) +{ +#ifdef FOO + printf("FOO is defined\n"); +#endif + printf("VALUE is %d\n", VALUE); + +#ifdef PAREN_VALUE + printf("2*PAREN_VALUE is %d\n", 2*PAREN_VALUE); +#endif + return 0; +} diff --git a/tools/gyp/test/defines/defines.gyp b/tools/gyp/test/defines/defines.gyp new file mode 100644 index 00000000000..25d8c41f9a0 --- /dev/null +++ b/tools/gyp/test/defines/defines.gyp @@ -0,0 +1,37 @@ +# 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': 'defines', + 'type': 'executable', + 'sources': [ + 'defines.c', + ], + 'defines': [ + 'FOO', + 'VALUE=1', + 'PAREN_VALUE=(1+2+3)', + ], + }, + ], + 'conditions': [ + ['OS=="fakeos"', { + 'targets': [ + { + 'target_name': 'fakeosprogram', + 'type': 'executable', + 'sources': [ + 'defines.c', + ], + 'defines': [ + 'FOO', + 'VALUE=1', + ], + }, + ], + }], + ], +} diff --git a/tools/gyp/test/defines/gyptest-define-override.py b/tools/gyp/test/defines/gyptest-define-override.py new file mode 100755 index 00000000000..82e325af2ce --- /dev/null +++ b/tools/gyp/test/defines/gyptest-define-override.py @@ -0,0 +1,34 @@ +#!/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 a default gyp define can be overridden. +""" + +import os +import TestGyp + +test = TestGyp.TestGyp() + +# Command-line define +test.run_gyp('defines.gyp', '-D', 'OS=fakeos') +test.build('defines.gyp') +test.built_file_must_exist('fakeosprogram', type=test.EXECUTABLE) +# Clean up the exe so subsequent tests don't find an old exe. +os.remove(test.built_file_path('fakeosprogram', type=test.EXECUTABLE)) + +# Without "OS" override, fokeosprogram shouldn't be built. +test.run_gyp('defines.gyp') +test.build('defines.gyp') +test.built_file_must_not_exist('fakeosprogram', type=test.EXECUTABLE) + +# Environment define +os.environ['GYP_DEFINES'] = 'OS=fakeos' +test.run_gyp('defines.gyp') +test.build('defines.gyp') +test.built_file_must_exist('fakeosprogram', type=test.EXECUTABLE) + +test.pass_test() diff --git a/tools/gyp/test/defines/gyptest-defines-env-regyp.py b/tools/gyp/test/defines/gyptest-defines-env-regyp.py new file mode 100755 index 00000000000..57ca42b2fc4 --- /dev/null +++ b/tools/gyp/test/defines/gyptest-defines-env-regyp.py @@ -0,0 +1,50 @@ +#!/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 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 + +# Regenerating build files when a gyp file changes is currently only supported +# by the make generator. +test = TestGyp.TestGyp(formats=['make']) + +try: + os.environ['GYP_DEFINES'] = 'value=50' + test.run_gyp('defines.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. + os.environ['GYP_DEFINES'] = '' + del os.environ['GYP_DEFINES'] + +test.build('defines.gyp') + +expect = """\ +FOO is defined +VALUE is 1 +2*PAREN_VALUE is 12 +""" +test.run_built_executable('defines', stdout=expect) + +# Sleep so that the changed gyp file will have a newer timestamp than the +# previously generated build files. +test.sleep() +test.write('defines.gyp', test.read('defines-env.gyp')) + +test.build('defines.gyp', test.ALL) + +expect = """\ +VALUE is 50 +""" +test.run_built_executable('defines', stdout=expect) + +test.pass_test() diff --git a/tools/gyp/test/defines/gyptest-defines-env.py b/tools/gyp/test/defines/gyptest-defines-env.py new file mode 100755 index 00000000000..6b4e7175a6d --- /dev/null +++ b/tools/gyp/test/defines/gyptest-defines-env.py @@ -0,0 +1,85 @@ +#!/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 build of an executable with C++ define specified by a gyp define. +""" + +import os +import TestGyp + +test = TestGyp.TestGyp() + +# With the value only given in environment, it should be used. +try: + os.environ['GYP_DEFINES'] = 'value=10' + test.run_gyp('defines-env.gyp') +finally: + del os.environ['GYP_DEFINES'] + +test.build('defines-env.gyp') + +expect = """\ +VALUE is 10 +""" +test.run_built_executable('defines', stdout=expect) + + +# With the value given in both command line and environment, +# command line should take precedence. +try: + os.environ['GYP_DEFINES'] = 'value=20' + test.run_gyp('defines-env.gyp', '-Dvalue=25') +finally: + del os.environ['GYP_DEFINES'] + +test.sleep() +test.touch('defines.c') +test.build('defines-env.gyp') + +expect = """\ +VALUE is 25 +""" +test.run_built_executable('defines', stdout=expect) + + +# With the value only given in environment, it should be ignored if +# --ignore-environment is specified. +try: + os.environ['GYP_DEFINES'] = 'value=30' + test.run_gyp('defines-env.gyp', '--ignore-environment') +finally: + del os.environ['GYP_DEFINES'] + +test.sleep() +test.touch('defines.c') +test.build('defines-env.gyp') + +expect = """\ +VALUE is 5 +""" +test.run_built_executable('defines', stdout=expect) + + +# With the value given in both command line and environment, and +# --ignore-environment also specified, command line should still be used. +try: + os.environ['GYP_DEFINES'] = 'value=40' + test.run_gyp('defines-env.gyp', '--ignore-environment', '-Dvalue=45') +finally: + del os.environ['GYP_DEFINES'] + +test.sleep() +test.touch('defines.c') +test.build('defines-env.gyp') + +expect = """\ +VALUE is 45 +""" +test.run_built_executable('defines', stdout=expect) + + +test.pass_test() diff --git a/tools/gyp/test/defines/gyptest-defines.py b/tools/gyp/test/defines/gyptest-defines.py new file mode 100755 index 00000000000..0b6d64b8553 --- /dev/null +++ b/tools/gyp/test/defines/gyptest-defines.py @@ -0,0 +1,26 @@ +#!/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 build of an executable with C++ defines. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('defines.gyp') + +test.build('defines.gyp') + +expect = """\ +FOO is defined +VALUE is 1 +2*PAREN_VALUE is 12 +""" +test.run_built_executable('defines', stdout=expect) + +test.pass_test() diff --git a/tools/gyp/test/dependencies/a.c b/tools/gyp/test/dependencies/a.c new file mode 100755 index 00000000000..3bba111d24e --- /dev/null +++ b/tools/gyp/test/dependencies/a.c @@ -0,0 +1,9 @@ +/* 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. */ + +extern int funcB(); + +int funcA() { + return funcB(); +} diff --git a/tools/gyp/test/dependencies/b/b.c b/tools/gyp/test/dependencies/b/b.c new file mode 100755 index 00000000000..b5e771bcc77 --- /dev/null +++ b/tools/gyp/test/dependencies/b/b.c @@ -0,0 +1,3 @@ +int funcB() { + return 2; +} diff --git a/tools/gyp/test/dependencies/b/b.gyp b/tools/gyp/test/dependencies/b/b.gyp new file mode 100755 index 00000000000..f09e1ff13c9 --- /dev/null +++ b/tools/gyp/test/dependencies/b/b.gyp @@ -0,0 +1,15 @@ +# 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': 'b', + 'type': 'static_library', + 'sources': [ + 'b.c', + ], + }, + ], +} diff --git a/tools/gyp/test/dependencies/c/c.c b/tools/gyp/test/dependencies/c/c.c new file mode 100644 index 00000000000..4949daf3ee1 --- /dev/null +++ b/tools/gyp/test/dependencies/c/c.c @@ -0,0 +1,4 @@ +int funcC() { + return 3 + // Intentional syntax error. This file should never be compiled, so this + // shouldn't be a problem. diff --git a/tools/gyp/test/dependencies/c/c.gyp b/tools/gyp/test/dependencies/c/c.gyp new file mode 100644 index 00000000000..eabebea9efb --- /dev/null +++ b/tools/gyp/test/dependencies/c/c.gyp @@ -0,0 +1,22 @@ +# 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': 'c_unused', + 'type': 'static_library', + 'sources': [ + 'c.c', + ], + }, + { + 'target_name': 'd', + 'type': 'static_library', + 'sources': [ + 'd.c', + ], + }, + ], +} diff --git a/tools/gyp/test/dependencies/c/d.c b/tools/gyp/test/dependencies/c/d.c new file mode 100644 index 00000000000..05465fc1af7 --- /dev/null +++ b/tools/gyp/test/dependencies/c/d.c @@ -0,0 +1,3 @@ +int funcD() { + return 4; +} diff --git a/tools/gyp/test/dependencies/extra_targets.gyp b/tools/gyp/test/dependencies/extra_targets.gyp new file mode 100644 index 00000000000..c1a26de4228 --- /dev/null +++ b/tools/gyp/test/dependencies/extra_targets.gyp @@ -0,0 +1,18 @@ +# 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': 'a', + 'type': 'static_library', + 'sources': [ + 'a.c', + ], + # This only depends on the "d" target; other targets in c.gyp + # should not become part of the build (unlike with 'c/c.gyp:*'). + 'dependencies': ['c/c.gyp:d'], + }, + ], +} diff --git a/tools/gyp/test/dependencies/gyptest-extra-targets.py b/tools/gyp/test/dependencies/gyptest-extra-targets.py new file mode 100755 index 00000000000..3752f7445d5 --- /dev/null +++ b/tools/gyp/test/dependencies/gyptest-extra-targets.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. + +""" +Verify that dependencies don't pull unused targets into the build. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('extra_targets.gyp') + +# This should fail if it tries to build 'c_unused' since 'c/c.c' has a syntax +# error and won't compile. +test.build('extra_targets.gyp', test.ALL) + +test.pass_test() diff --git a/tools/gyp/test/dependencies/gyptest-lib-only.py b/tools/gyp/test/dependencies/gyptest-lib-only.py new file mode 100755 index 00000000000..4355d578ae4 --- /dev/null +++ b/tools/gyp/test/dependencies/gyptest-lib-only.py @@ -0,0 +1,39 @@ +#!/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. + +""" +Verify that a link time only dependency will get pulled into the set of built +targets, even if no executable uses it. +""" + +import TestGyp + +import sys + +test = TestGyp.TestGyp() + +test.run_gyp('lib_only.gyp') + +test.build('lib_only.gyp', test.ALL) + +test.built_file_must_exist('a', type=test.STATIC_LIB) + +# TODO(bradnelson/mark): +# On linux and windows a library target will at least pull its link dependencies +# into the generated sln/_main.scons, since not doing so confuses users. +# This is not currently implemented on mac, which has the opposite behavior. +if sys.platform == 'darwin': + if test.format == 'xcode': + test.built_file_must_not_exist('b', type=test.STATIC_LIB) + else: + assert test.format == 'make' + test.built_file_must_exist('b', type=test.STATIC_LIB) +else: + # Make puts the resulting library in a directory matching the input gyp file; + # for the 'b' library, that is in the 'b' subdirectory. + test.built_file_must_exist('b', type=test.STATIC_LIB, subdir='b') + +test.pass_test() diff --git a/tools/gyp/test/dependencies/lib_only.gyp b/tools/gyp/test/dependencies/lib_only.gyp new file mode 100755 index 00000000000..f6c84dea64f --- /dev/null +++ b/tools/gyp/test/dependencies/lib_only.gyp @@ -0,0 +1,16 @@ +# 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': 'a', + 'type': 'static_library', + 'sources': [ + 'a.c', + ], + 'dependencies': ['b/b.gyp:b'], + }, + ], +} diff --git a/tools/gyp/test/dependency-copy/gyptest-copy.py b/tools/gyp/test/dependency-copy/gyptest-copy.py new file mode 100755 index 00000000000..5ba7c73d413 --- /dev/null +++ b/tools/gyp/test/dependency-copy/gyptest-copy.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. + +""" +Verifies dependencies do the copy step. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('copies.gyp', chdir='src') + +test.build('copies.gyp', 'proj2', chdir='src') + +test.run_built_executable('proj1', + chdir='src', + stdout="Hello from file1.c\n") +test.run_built_executable('proj2', + chdir='src', + stdout="Hello from file2.c\n") + +test.pass_test() diff --git a/tools/gyp/test/dependency-copy/src/copies.gyp b/tools/gyp/test/dependency-copy/src/copies.gyp new file mode 100644 index 00000000000..4176b18787b --- /dev/null +++ b/tools/gyp/test/dependency-copy/src/copies.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': 'proj1', + 'type': 'executable', + 'sources': [ + 'file1.c', + ], + }, + { + 'target_name': 'proj2', + 'type': 'executable', + 'sources': [ + 'file2.c', + ], + 'dependencies': [ + 'proj1', + ] + }, + ], +} diff --git a/tools/gyp/test/dependency-copy/src/file1.c b/tools/gyp/test/dependency-copy/src/file1.c new file mode 100644 index 00000000000..3caf5d63457 --- /dev/null +++ b/tools/gyp/test/dependency-copy/src/file1.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main(int argc, char *argv[]) +{ + printf("Hello from file1.c\n"); + return 0; +} diff --git a/tools/gyp/test/dependency-copy/src/file2.c b/tools/gyp/test/dependency-copy/src/file2.c new file mode 100644 index 00000000000..ed45cc012d7 --- /dev/null +++ b/tools/gyp/test/dependency-copy/src/file2.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main(int argc, char *argv[]) +{ + printf("Hello from file2.c\n"); + return 0; +} diff --git a/tools/gyp/test/exclusion/exclusion.gyp b/tools/gyp/test/exclusion/exclusion.gyp new file mode 100644 index 00000000000..1232dabaef9 --- /dev/null +++ b/tools/gyp/test/exclusion/exclusion.gyp @@ -0,0 +1,23 @@ +# 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': 'hello', + 'type': 'executable', + 'sources': [ + 'hello.c', + 'bogus.c', + 'also/not/real.c', + 'also/not/real2.c', + ], + 'sources!': [ + 'bogus.c', + 'also/not/real.c', + 'also/not/real2.c', + ], + }, + ], +} diff --git a/tools/gyp/test/exclusion/gyptest-exclusion.py b/tools/gyp/test/exclusion/gyptest-exclusion.py new file mode 100755 index 00000000000..1fc32bf871a --- /dev/null +++ b/tools/gyp/test/exclusion/gyptest-exclusion.py @@ -0,0 +1,22 @@ +#!/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 that exclusions (e.g. sources!) are respected. Excluded sources +that do not exist should not prevent the build from succeeding. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('exclusion.gyp') +test.build('exclusion.gyp') + +# executables +test.built_file_must_exist('hello' + test._exe, test.EXECUTABLE, bare=True) + +test.pass_test() diff --git a/tools/gyp/test/exclusion/hello.c b/tools/gyp/test/exclusion/hello.c new file mode 100644 index 00000000000..30e8d5416dc --- /dev/null +++ b/tools/gyp/test/exclusion/hello.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 func1(void) { + return 42; +} + +int main(int argc, char *argv[]) { + printf("Hello, world!\n"); + printf("%d\n", func1()); + return 0; +} diff --git a/tools/gyp/test/generator-output/actions/actions.gyp b/tools/gyp/test/generator-output/actions/actions.gyp new file mode 100644 index 00000000000..dded59aff3e --- /dev/null +++ b/tools/gyp/test/generator-output/actions/actions.gyp @@ -0,0 +1,16 @@ +# 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:*', + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/actions/build/README.txt b/tools/gyp/test/generator-output/actions/build/README.txt new file mode 100644 index 00000000000..1b052c9a245 --- /dev/null +++ b/tools/gyp/test/generator-output/actions/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the
+test script can verify that .xcodeproj files are not created in
+their normal location by making the src/ read-only, and then
+selectively making this build directory writable.
diff --git a/tools/gyp/test/generator-output/actions/subdir1/actions-out/README.txt b/tools/gyp/test/generator-output/actions/subdir1/actions-out/README.txt new file mode 100644 index 00000000000..1b052c9a245 --- /dev/null +++ b/tools/gyp/test/generator-output/actions/subdir1/actions-out/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the
+test script can verify that .xcodeproj files are not created in
+their normal location by making the src/ read-only, and then
+selectively making this build directory writable.
diff --git a/tools/gyp/test/generator-output/actions/subdir1/build/README.txt b/tools/gyp/test/generator-output/actions/subdir1/build/README.txt new file mode 100644 index 00000000000..1b052c9a245 --- /dev/null +++ b/tools/gyp/test/generator-output/actions/subdir1/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the
+test script can verify that .xcodeproj files are not created in
+their normal location by making the src/ read-only, and then
+selectively making this build directory writable.
diff --git a/tools/gyp/test/generator-output/actions/subdir1/executable.gyp b/tools/gyp/test/generator-output/actions/subdir1/executable.gyp new file mode 100644 index 00000000000..6bdd60a1fb7 --- /dev/null +++ b/tools/gyp/test/generator-output/actions/subdir1/executable.gyp @@ -0,0 +1,44 @@ +# 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, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/actions/subdir1/make-prog1.py b/tools/gyp/test/generator-output/actions/subdir1/make-prog1.py new file mode 100755 index 00000000000..7ea1d8a2d48 --- /dev/null +++ b/tools/gyp/test/generator-output/actions/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) diff --git a/tools/gyp/test/generator-output/actions/subdir1/make-prog2.py b/tools/gyp/test/generator-output/actions/subdir1/make-prog2.py new file mode 100755 index 00000000000..0bfe4973c24 --- /dev/null +++ b/tools/gyp/test/generator-output/actions/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) diff --git a/tools/gyp/test/generator-output/actions/subdir1/program.c b/tools/gyp/test/generator-output/actions/subdir1/program.c new file mode 100644 index 00000000000..d5f661d905b --- /dev/null +++ b/tools/gyp/test/generator-output/actions/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;
+}
diff --git a/tools/gyp/test/generator-output/actions/subdir2/actions-out/README.txt b/tools/gyp/test/generator-output/actions/subdir2/actions-out/README.txt new file mode 100644 index 00000000000..1b052c9a245 --- /dev/null +++ b/tools/gyp/test/generator-output/actions/subdir2/actions-out/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the
+test script can verify that .xcodeproj files are not created in
+their normal location by making the src/ read-only, and then
+selectively making this build directory writable.
diff --git a/tools/gyp/test/generator-output/actions/subdir2/build/README.txt b/tools/gyp/test/generator-output/actions/subdir2/build/README.txt new file mode 100644 index 00000000000..1b052c9a245 --- /dev/null +++ b/tools/gyp/test/generator-output/actions/subdir2/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the
+test script can verify that .xcodeproj files are not created in
+their normal location by making the src/ read-only, and then
+selectively making this build directory writable.
diff --git a/tools/gyp/test/generator-output/actions/subdir2/make-file.py b/tools/gyp/test/generator-output/actions/subdir2/make-file.py new file mode 100755 index 00000000000..fff06531447 --- /dev/null +++ b/tools/gyp/test/generator-output/actions/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) diff --git a/tools/gyp/test/generator-output/actions/subdir2/none.gyp b/tools/gyp/test/generator-output/actions/subdir2/none.gyp new file mode 100644 index 00000000000..f98f52753d0 --- /dev/null +++ b/tools/gyp/test/generator-output/actions/subdir2/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': [ + 'actions-out/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, + } + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/copies/build/README.txt b/tools/gyp/test/generator-output/copies/build/README.txt new file mode 100644 index 00000000000..90ef8861931 --- /dev/null +++ b/tools/gyp/test/generator-output/copies/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/copies/copies-out/README.txt b/tools/gyp/test/generator-output/copies/copies-out/README.txt new file mode 100644 index 00000000000..90ef8861931 --- /dev/null +++ b/tools/gyp/test/generator-output/copies/copies-out/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/copies/copies.gyp b/tools/gyp/test/generator-output/copies/copies.gyp new file mode 100644 index 00000000000..479a3d9b6e8 --- /dev/null +++ b/tools/gyp/test/generator-output/copies/copies.gyp @@ -0,0 +1,50 @@ +# 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_subdir', + 'type': 'none', + 'dependencies': [ + 'subdir/subdir.gyp:*', + ], + }, + { + 'target_name': 'copies1', + 'type': 'none', + 'copies': [ + { + 'destination': 'copies-out', + 'files': [ + 'file1', + ], + }, + ], + }, + { + 'target_name': 'copies2', + 'type': 'none', + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/copies-out', + 'files': [ + 'file2', + ], + }, + ], + }, + # Verify that a null 'files' list doesn't gag the generators. + { + 'target_name': 'copies_null', + 'type': 'none', + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/copies-null', + 'files': [], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/copies/file1 b/tools/gyp/test/generator-output/copies/file1 new file mode 100644 index 00000000000..84d55c5759c --- /dev/null +++ b/tools/gyp/test/generator-output/copies/file1 @@ -0,0 +1 @@ +file1 contents diff --git a/tools/gyp/test/generator-output/copies/file2 b/tools/gyp/test/generator-output/copies/file2 new file mode 100644 index 00000000000..af1b8ae35db --- /dev/null +++ b/tools/gyp/test/generator-output/copies/file2 @@ -0,0 +1 @@ +file2 contents diff --git a/tools/gyp/test/generator-output/copies/subdir/build/README.txt b/tools/gyp/test/generator-output/copies/subdir/build/README.txt new file mode 100644 index 00000000000..90ef8861931 --- /dev/null +++ b/tools/gyp/test/generator-output/copies/subdir/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/copies/subdir/copies-out/README.txt b/tools/gyp/test/generator-output/copies/subdir/copies-out/README.txt new file mode 100644 index 00000000000..90ef8861931 --- /dev/null +++ b/tools/gyp/test/generator-output/copies/subdir/copies-out/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/copies/subdir/file3 b/tools/gyp/test/generator-output/copies/subdir/file3 new file mode 100644 index 00000000000..43f16f35220 --- /dev/null +++ b/tools/gyp/test/generator-output/copies/subdir/file3 @@ -0,0 +1 @@ +file3 contents diff --git a/tools/gyp/test/generator-output/copies/subdir/file4 b/tools/gyp/test/generator-output/copies/subdir/file4 new file mode 100644 index 00000000000..5f7270a0847 --- /dev/null +++ b/tools/gyp/test/generator-output/copies/subdir/file4 @@ -0,0 +1 @@ +file4 contents diff --git a/tools/gyp/test/generator-output/copies/subdir/subdir.gyp b/tools/gyp/test/generator-output/copies/subdir/subdir.gyp new file mode 100644 index 00000000000..af031d283ae --- /dev/null +++ b/tools/gyp/test/generator-output/copies/subdir/subdir.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': 'copies3', + 'type': 'none', + 'copies': [ + { + 'destination': 'copies-out', + 'files': [ + 'file3', + ], + }, + ], + }, + { + 'target_name': 'copies4', + 'type': 'none', + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/copies-out', + 'files': [ + 'file4', + ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/gyptest-actions.py b/tools/gyp/test/generator-output/gyptest-actions.py new file mode 100755 index 00000000000..6e62720c2b6 --- /dev/null +++ b/tools/gyp/test/generator-output/gyptest-actions.py @@ -0,0 +1,58 @@ +#!/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 --generator-output= behavior when using actions. +""" + +import TestGyp + +# Ninja doesn't support --generator-output. +test = TestGyp.TestGyp(formats=['!ninja']) + +# All the generated files should go under 'gypfiles'. The source directory +# ('actions') should be untouched. +test.writable(test.workpath('actions'), False) +test.run_gyp('actions.gyp', + '--generator-output=' + test.workpath('gypfiles'), + chdir='actions') + +test.writable(test.workpath('actions'), True) + +test.relocate('actions', 'relocate/actions') +test.relocate('gypfiles', 'relocate/gypfiles') + +test.writable(test.workpath('relocate/actions'), False) + +# Some of the action outputs use "pure" relative paths (i.e. without prefixes +# like <(INTERMEDIATE_DIR) or <(PROGRAM_DIR)). Even though we are building under +# 'gypfiles', such outputs will still be created relative to the original .gyp +# sources. Projects probably wouldn't normally do this, since it kind of defeats +# the purpose of '--generator-output', but it is supported behaviour. +test.writable(test.workpath('relocate/actions/build'), True) +test.writable(test.workpath('relocate/actions/subdir1/build'), True) +test.writable(test.workpath('relocate/actions/subdir1/actions-out'), True) +test.writable(test.workpath('relocate/actions/subdir2/build'), True) +test.writable(test.workpath('relocate/actions/subdir2/actions-out'), True) + +test.build('actions.gyp', test.ALL, chdir='relocate/gypfiles') + +expect = """\ +Hello from program.c +Hello from make-prog1.py +Hello from make-prog2.py +""" + +if test.format == 'xcode': + chdir = 'relocate/actions/subdir1' +else: + chdir = 'relocate/gypfiles' +test.run_built_executable('program', chdir=chdir, stdout=expect) + +test.must_match('relocate/actions/subdir2/actions-out/file.out', + "Hello from make-file.py\n") + +test.pass_test() diff --git a/tools/gyp/test/generator-output/gyptest-copies.py b/tools/gyp/test/generator-output/gyptest-copies.py new file mode 100755 index 00000000000..83ba013f0fe --- /dev/null +++ b/tools/gyp/test/generator-output/gyptest-copies.py @@ -0,0 +1,59 @@ +#!/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 file copies with --generator-output using an explicit build +target of 'all'. +""" + +import TestGyp + +# Ninja doesn't support --generator-output. +test = TestGyp.TestGyp(formats=['!ninja']) + +test.writable(test.workpath('copies'), False) + +test.run_gyp('copies.gyp', + '--generator-output=' + test.workpath('gypfiles'), + chdir='copies') + +test.writable(test.workpath('copies'), True) + +test.relocate('copies', 'relocate/copies') +test.relocate('gypfiles', 'relocate/gypfiles') + +test.writable(test.workpath('relocate/copies'), False) + +test.writable(test.workpath('relocate/copies/build'), True) +test.writable(test.workpath('relocate/copies/copies-out'), True) +test.writable(test.workpath('relocate/copies/subdir/build'), True) +test.writable(test.workpath('relocate/copies/subdir/copies-out'), True) + +test.build('copies.gyp', test.ALL, chdir='relocate/gypfiles') + +test.must_match(['relocate', 'copies', 'copies-out', 'file1'], + "file1 contents\n") + +if test.format == 'xcode': + chdir = 'relocate/copies/build' +elif test.format == 'make': + chdir = 'relocate/gypfiles/out' +else: + chdir = 'relocate/gypfiles' +test.must_match([chdir, 'Default', 'copies-out', 'file2'], "file2 contents\n") + +test.must_match(['relocate', 'copies', 'subdir', 'copies-out', 'file3'], + "file3 contents\n") + +if test.format == 'xcode': + chdir = 'relocate/copies/subdir/build' +elif test.format == 'make': + chdir = 'relocate/gypfiles/out' +else: + chdir = 'relocate/gypfiles' +test.must_match([chdir, 'Default', 'copies-out', 'file4'], "file4 contents\n") + +test.pass_test() diff --git a/tools/gyp/test/generator-output/gyptest-relocate.py b/tools/gyp/test/generator-output/gyptest-relocate.py new file mode 100755 index 00000000000..31a98ea1c27 --- /dev/null +++ b/tools/gyp/test/generator-output/gyptest-relocate.py @@ -0,0 +1,60 @@ +#!/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 a project hierarchy created with the --generator-output= +option can be built even when it's relocated to a different path. +""" + +import TestGyp + +# Ninja doesn't support --generator-output. +test = TestGyp.TestGyp(formats=['!ninja']) + +test.writable(test.workpath('src'), False) + +test.run_gyp('prog1.gyp', + '-Dset_symroot=1', + '--generator-output=' + test.workpath('gypfiles'), + chdir='src') + +test.writable(test.workpath('src'), True) + +test.relocate('src', 'relocate/src') +test.relocate('gypfiles', 'relocate/gypfiles') + +test.writable(test.workpath('relocate/src'), False) + +test.writable(test.workpath('relocate/src/build'), True) +test.writable(test.workpath('relocate/src/subdir2/build'), True) +test.writable(test.workpath('relocate/src/subdir3/build'), True) + +test.build('prog1.gyp', test.ALL, chdir='relocate/gypfiles') + +chdir = 'relocate/gypfiles' + +expect = """\ +Hello from %s +Hello from inc.h +Hello from inc1/include1.h +Hello from inc2/include2.h +Hello from inc3/include3.h +Hello from subdir2/deeper/deeper.h +""" + +if test.format == 'xcode': + chdir = 'relocate/src' +test.run_built_executable('prog1', chdir=chdir, stdout=expect % 'prog1.c') + +if test.format == 'xcode': + chdir = 'relocate/src/subdir2' +test.run_built_executable('prog2', chdir=chdir, stdout=expect % 'prog2.c') + +if test.format == 'xcode': + chdir = 'relocate/src/subdir3' +test.run_built_executable('prog3', chdir=chdir, stdout=expect % 'prog3.c') + +test.pass_test() diff --git a/tools/gyp/test/generator-output/gyptest-rules.py b/tools/gyp/test/generator-output/gyptest-rules.py new file mode 100755 index 00000000000..678416a2fc2 --- /dev/null +++ b/tools/gyp/test/generator-output/gyptest-rules.py @@ -0,0 +1,58 @@ +#!/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 --generator-output= behavior when using rules. +""" + +import TestGyp + +test = TestGyp.TestGyp(formats=['!ninja']) + +test.writable(test.workpath('rules'), False) + +test.run_gyp('rules.gyp', + '--generator-output=' + test.workpath('gypfiles'), + chdir='rules') + +test.writable(test.workpath('rules'), True) + +test.relocate('rules', 'relocate/rules') +test.relocate('gypfiles', 'relocate/gypfiles') + +test.writable(test.workpath('relocate/rules'), False) + +test.writable(test.workpath('relocate/rules/build'), True) +test.writable(test.workpath('relocate/rules/subdir1/build'), True) +test.writable(test.workpath('relocate/rules/subdir2/build'), True) +test.writable(test.workpath('relocate/rules/subdir2/rules-out'), True) + +test.build('rules.gyp', test.ALL, chdir='relocate/gypfiles') + +expect = """\ +Hello from program.c +Hello from function1.in1 +Hello from function2.in1 +Hello from define3.in0 +Hello from define4.in0 +""" + +if test.format == 'xcode': + chdir = 'relocate/rules/subdir1' +else: + chdir = 'relocate/gypfiles' +test.run_built_executable('program', chdir=chdir, stdout=expect) + +test.must_match('relocate/rules/subdir2/rules-out/file1.out', + "Hello from file1.in0\n") +test.must_match('relocate/rules/subdir2/rules-out/file2.out', + "Hello from file2.in0\n") +test.must_match('relocate/rules/subdir2/rules-out/file3.out', + "Hello from file3.in1\n") +test.must_match('relocate/rules/subdir2/rules-out/file4.out', + "Hello from file4.in1\n") + +test.pass_test() diff --git a/tools/gyp/test/generator-output/gyptest-subdir2-deep.py b/tools/gyp/test/generator-output/gyptest-subdir2-deep.py new file mode 100755 index 00000000000..cb5ea15bf10 --- /dev/null +++ b/tools/gyp/test/generator-output/gyptest-subdir2-deep.py @@ -0,0 +1,36 @@ +#!/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 building a target from a .gyp file a few subdirectories +deep when the --generator-output= option is used to put the build +configuration files in a separate directory tree. +""" + +import TestGyp + +test = TestGyp.TestGyp(formats=['!ninja']) + +test.writable(test.workpath('src'), False) + +test.writable(test.workpath('src/subdir2/deeper/build'), True) + +test.run_gyp('deeper.gyp', + '-Dset_symroot=1', + '--generator-output=' + test.workpath('gypfiles'), + chdir='src/subdir2/deeper') + +test.build('deeper.gyp', test.ALL, chdir='gypfiles') + +chdir = 'gypfiles' + +if test.format == 'xcode': + chdir = 'src/subdir2/deeper' +test.run_built_executable('deeper', + chdir=chdir, + stdout="Hello from deeper.c\n") + +test.pass_test() diff --git a/tools/gyp/test/generator-output/gyptest-top-all.py b/tools/gyp/test/generator-output/gyptest-top-all.py new file mode 100755 index 00000000000..4841f9b6b02 --- /dev/null +++ b/tools/gyp/test/generator-output/gyptest-top-all.py @@ -0,0 +1,53 @@ +#!/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 building a project hierarchy created when the --generator-output= +option is used to put the build configuration files in a separate +directory tree. +""" + +import TestGyp + +test = TestGyp.TestGyp(formats=['!ninja']) + +test.writable(test.workpath('src'), False) + +test.run_gyp('prog1.gyp', + '-Dset_symroot=1', + '--generator-output=' + test.workpath('gypfiles'), + chdir='src') + +test.writable(test.workpath('src/build'), True) +test.writable(test.workpath('src/subdir2/build'), True) +test.writable(test.workpath('src/subdir3/build'), True) + +test.build('prog1.gyp', test.ALL, chdir='gypfiles') + +chdir = 'gypfiles' + +expect = """\ +Hello from %s +Hello from inc.h +Hello from inc1/include1.h +Hello from inc2/include2.h +Hello from inc3/include3.h +Hello from subdir2/deeper/deeper.h +""" + +if test.format == 'xcode': + chdir = 'src' +test.run_built_executable('prog1', chdir=chdir, stdout=expect % 'prog1.c') + +if test.format == 'xcode': + chdir = 'src/subdir2' +test.run_built_executable('prog2', chdir=chdir, stdout=expect % 'prog2.c') + +if test.format == 'xcode': + chdir = 'src/subdir3' +test.run_built_executable('prog3', chdir=chdir, stdout=expect % 'prog3.c') + +test.pass_test() diff --git a/tools/gyp/test/generator-output/rules/build/README.txt b/tools/gyp/test/generator-output/rules/build/README.txt new file mode 100644 index 00000000000..1b052c9a245 --- /dev/null +++ b/tools/gyp/test/generator-output/rules/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the
+test script can verify that .xcodeproj files are not created in
+their normal location by making the src/ read-only, and then
+selectively making this build directory writable.
diff --git a/tools/gyp/test/generator-output/rules/copy-file.py b/tools/gyp/test/generator-output/rules/copy-file.py new file mode 100755 index 00000000000..938c336adb0 --- /dev/null +++ b/tools/gyp/test/generator-output/rules/copy-file.py @@ -0,0 +1,12 @@ +#!/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 = open(sys.argv[1], 'r').read() +open(sys.argv[2], 'wb').write(contents) + +sys.exit(0) diff --git a/tools/gyp/test/generator-output/rules/rules.gyp b/tools/gyp/test/generator-output/rules/rules.gyp new file mode 100644 index 00000000000..dded59aff3e --- /dev/null +++ b/tools/gyp/test/generator-output/rules/rules.gyp @@ -0,0 +1,16 @@ +# 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:*', + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/rules/subdir1/build/README.txt b/tools/gyp/test/generator-output/rules/subdir1/build/README.txt new file mode 100644 index 00000000000..1b052c9a245 --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir1/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the
+test script can verify that .xcodeproj files are not created in
+their normal location by making the src/ read-only, and then
+selectively making this build directory writable.
diff --git a/tools/gyp/test/generator-output/rules/subdir1/define3.in0 b/tools/gyp/test/generator-output/rules/subdir1/define3.in0 new file mode 100644 index 00000000000..cc29c643f39 --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir1/define3.in0 @@ -0,0 +1 @@ +#define STRING3 "Hello from define3.in0\n" diff --git a/tools/gyp/test/generator-output/rules/subdir1/define4.in0 b/tools/gyp/test/generator-output/rules/subdir1/define4.in0 new file mode 100644 index 00000000000..c9b0467b328 --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir1/define4.in0 @@ -0,0 +1 @@ +#define STRING4 "Hello from define4.in0\n" diff --git a/tools/gyp/test/generator-output/rules/subdir1/executable.gyp b/tools/gyp/test/generator-output/rules/subdir1/executable.gyp new file mode 100644 index 00000000000..2fd89a0d523 --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir1/executable.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. + +{ + 'targets': [ + { + 'target_name': 'program', + 'type': 'executable', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'program.c', + 'function1.in1', + 'function2.in1', + 'define3.in0', + 'define4.in0', + ], + 'include_dirs': [ + '<(INTERMEDIATE_DIR)', + ], + 'rules': [ + { + 'rule_name': 'copy_file_0', + 'extension': 'in0', + 'inputs': [ + '../copy-file.py', + ], + 'outputs': [ + # TODO: fix SCons and Make to support generated files not + # in a variable-named path like <(INTERMEDIATE_DIR) + #'<(RULE_INPUT_ROOT).c', + '<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).h', + ], + 'action': [ + 'python', '<(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 0, + }, + { + 'rule_name': 'copy_file_1', + 'extension': 'in1', + 'inputs': [ + '../copy-file.py', + ], + 'outputs': [ + # TODO: fix SCons and Make to support generated files not + # in a variable-named path like <(INTERMEDIATE_DIR) + #'<(RULE_INPUT_ROOT).c', + '<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).c', + ], + 'action': [ + 'python', '<(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/rules/subdir1/function1.in1 b/tools/gyp/test/generator-output/rules/subdir1/function1.in1 new file mode 100644 index 00000000000..545e7ca16bb --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir1/function1.in1 @@ -0,0 +1,6 @@ +#include <stdio.h> + +void function1(void) +{ + printf("Hello from function1.in1\n"); +} diff --git a/tools/gyp/test/generator-output/rules/subdir1/function2.in1 b/tools/gyp/test/generator-output/rules/subdir1/function2.in1 new file mode 100644 index 00000000000..6bad43f9cf4 --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir1/function2.in1 @@ -0,0 +1,6 @@ +#include <stdio.h> + +void function2(void) +{ + printf("Hello from function2.in1\n"); +} diff --git a/tools/gyp/test/generator-output/rules/subdir1/program.c b/tools/gyp/test/generator-output/rules/subdir1/program.c new file mode 100644 index 00000000000..27fd31ed4e7 --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir1/program.c @@ -0,0 +1,18 @@ +#include <stdio.h> +#include "define3.h" +#include "define4.h" + +extern void function1(void); +extern void function2(void); +extern void function3(void); +extern void function4(void); + +int main(int argc, char *argv[]) +{ + printf("Hello from program.c\n"); + function1(); + function2(); + printf("%s", STRING3); + printf("%s", STRING4); + return 0; +} diff --git a/tools/gyp/test/generator-output/rules/subdir2/build/README.txt b/tools/gyp/test/generator-output/rules/subdir2/build/README.txt new file mode 100644 index 00000000000..1b052c9a245 --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir2/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the
+test script can verify that .xcodeproj files are not created in
+their normal location by making the src/ read-only, and then
+selectively making this build directory writable.
diff --git a/tools/gyp/test/generator-output/rules/subdir2/file1.in0 b/tools/gyp/test/generator-output/rules/subdir2/file1.in0 new file mode 100644 index 00000000000..7aca64f4ce0 --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir2/file1.in0 @@ -0,0 +1 @@ +Hello from file1.in0 diff --git a/tools/gyp/test/generator-output/rules/subdir2/file2.in0 b/tools/gyp/test/generator-output/rules/subdir2/file2.in0 new file mode 100644 index 00000000000..80a281a2a9a --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir2/file2.in0 @@ -0,0 +1 @@ +Hello from file2.in0 diff --git a/tools/gyp/test/generator-output/rules/subdir2/file3.in1 b/tools/gyp/test/generator-output/rules/subdir2/file3.in1 new file mode 100644 index 00000000000..60ae2e79311 --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir2/file3.in1 @@ -0,0 +1 @@ +Hello from file3.in1 diff --git a/tools/gyp/test/generator-output/rules/subdir2/file4.in1 b/tools/gyp/test/generator-output/rules/subdir2/file4.in1 new file mode 100644 index 00000000000..5a3c30720e7 --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir2/file4.in1 @@ -0,0 +1 @@ +Hello from file4.in1 diff --git a/tools/gyp/test/generator-output/rules/subdir2/none.gyp b/tools/gyp/test/generator-output/rules/subdir2/none.gyp new file mode 100644 index 00000000000..664cbd9cb75 --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir2/none.gyp @@ -0,0 +1,49 @@ +# 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': 'files', + 'type': 'none', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'file1.in0', + 'file2.in0', + 'file3.in1', + 'file4.in1', + ], + 'rules': [ + { + 'rule_name': 'copy_file_0', + 'extension': 'in0', + 'inputs': [ + '../copy-file.py', + ], + 'outputs': [ + 'rules-out/<(RULE_INPUT_ROOT).out', + ], + 'action': [ + 'python', '<(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 0, + }, + { + 'rule_name': 'copy_file_1', + 'extension': 'in1', + 'inputs': [ + '../copy-file.py', + ], + 'outputs': [ + 'rules-out/<(RULE_INPUT_ROOT).out', + ], + 'action': [ + 'python', '<(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/rules/subdir2/rules-out/README.txt b/tools/gyp/test/generator-output/rules/subdir2/rules-out/README.txt new file mode 100644 index 00000000000..1b052c9a245 --- /dev/null +++ b/tools/gyp/test/generator-output/rules/subdir2/rules-out/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the
+test script can verify that .xcodeproj files are not created in
+their normal location by making the src/ read-only, and then
+selectively making this build directory writable.
diff --git a/tools/gyp/test/generator-output/src/build/README.txt b/tools/gyp/test/generator-output/src/build/README.txt new file mode 100644 index 00000000000..90ef8861931 --- /dev/null +++ b/tools/gyp/test/generator-output/src/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/src/inc.h b/tools/gyp/test/generator-output/src/inc.h new file mode 100644 index 00000000000..57aa1a5a744 --- /dev/null +++ b/tools/gyp/test/generator-output/src/inc.h @@ -0,0 +1 @@ +#define INC_STRING "inc.h" diff --git a/tools/gyp/test/generator-output/src/inc1/include1.h b/tools/gyp/test/generator-output/src/inc1/include1.h new file mode 100644 index 00000000000..1d59065fc90 --- /dev/null +++ b/tools/gyp/test/generator-output/src/inc1/include1.h @@ -0,0 +1 @@ +#define INCLUDE1_STRING "inc1/include1.h" diff --git a/tools/gyp/test/generator-output/src/prog1.c b/tools/gyp/test/generator-output/src/prog1.c new file mode 100644 index 00000000000..656f81d5fe5 --- /dev/null +++ b/tools/gyp/test/generator-output/src/prog1.c @@ -0,0 +1,18 @@ +#include <stdio.h> + +#include "inc.h" +#include "include1.h" +#include "include2.h" +#include "include3.h" +#include "deeper.h" + +int main(int argc, char *argv[]) +{ + printf("Hello from prog1.c\n"); + printf("Hello from %s\n", INC_STRING); + printf("Hello from %s\n", INCLUDE1_STRING); + printf("Hello from %s\n", INCLUDE2_STRING); + printf("Hello from %s\n", INCLUDE3_STRING); + printf("Hello from %s\n", DEEPER_STRING); + return 0; +} diff --git a/tools/gyp/test/generator-output/src/prog1.gyp b/tools/gyp/test/generator-output/src/prog1.gyp new file mode 100644 index 00000000000..d50e6fb0a7e --- /dev/null +++ b/tools/gyp/test/generator-output/src/prog1.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. + +{ + 'includes': [ + 'symroot.gypi', + ], + 'targets': [ + { + 'target_name': 'prog1', + 'type': 'executable', + 'dependencies': [ + 'subdir2/prog2.gyp:prog2', + ], + 'include_dirs': [ + '.', + 'inc1', + 'subdir2/inc2', + 'subdir3/inc3', + 'subdir2/deeper', + ], + 'sources': [ + 'prog1.c', + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/src/subdir2/build/README.txt b/tools/gyp/test/generator-output/src/subdir2/build/README.txt new file mode 100644 index 00000000000..90ef8861931 --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir2/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/src/subdir2/deeper/build/README.txt b/tools/gyp/test/generator-output/src/subdir2/deeper/build/README.txt new file mode 100644 index 00000000000..90ef8861931 --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir2/deeper/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/src/subdir2/deeper/deeper.c b/tools/gyp/test/generator-output/src/subdir2/deeper/deeper.c new file mode 100644 index 00000000000..56c49d1f78b --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir2/deeper/deeper.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main(int argc, char *argv[]) +{ + printf("Hello from deeper.c\n"); + return 0; +} diff --git a/tools/gyp/test/generator-output/src/subdir2/deeper/deeper.gyp b/tools/gyp/test/generator-output/src/subdir2/deeper/deeper.gyp new file mode 100644 index 00000000000..86487708723 --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir2/deeper/deeper.gyp @@ -0,0 +1,18 @@ +# 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': [ + '../../symroot.gypi', + ], + 'targets': [ + { + 'target_name': 'deeper', + 'type': 'executable', + 'sources': [ + 'deeper.c', + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/src/subdir2/deeper/deeper.h b/tools/gyp/test/generator-output/src/subdir2/deeper/deeper.h new file mode 100644 index 00000000000..f6484a0fe58 --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir2/deeper/deeper.h @@ -0,0 +1 @@ +#define DEEPER_STRING "subdir2/deeper/deeper.h" diff --git a/tools/gyp/test/generator-output/src/subdir2/inc2/include2.h b/tools/gyp/test/generator-output/src/subdir2/inc2/include2.h new file mode 100644 index 00000000000..1ccfa5dea79 --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir2/inc2/include2.h @@ -0,0 +1 @@ +#define INCLUDE2_STRING "inc2/include2.h" diff --git a/tools/gyp/test/generator-output/src/subdir2/prog2.c b/tools/gyp/test/generator-output/src/subdir2/prog2.c new file mode 100644 index 00000000000..38d6c84d111 --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir2/prog2.c @@ -0,0 +1,18 @@ +#include <stdio.h> + +#include "inc.h" +#include "include1.h" +#include "include2.h" +#include "include3.h" +#include "deeper.h" + +int main(int argc, char *argv[]) +{ + printf("Hello from prog2.c\n"); + printf("Hello from %s\n", INC_STRING); + printf("Hello from %s\n", INCLUDE1_STRING); + printf("Hello from %s\n", INCLUDE2_STRING); + printf("Hello from %s\n", INCLUDE3_STRING); + printf("Hello from %s\n", DEEPER_STRING); + return 0; +} diff --git a/tools/gyp/test/generator-output/src/subdir2/prog2.gyp b/tools/gyp/test/generator-output/src/subdir2/prog2.gyp new file mode 100644 index 00000000000..7176ed8be74 --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir2/prog2.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. + +{ + 'includes': [ + '../symroot.gypi', + ], + 'targets': [ + { + 'target_name': 'prog2', + 'type': 'executable', + 'include_dirs': [ + '..', + '../inc1', + 'inc2', + '../subdir3/inc3', + 'deeper', + ], + 'dependencies': [ + '../subdir3/prog3.gyp:prog3', + ], + 'sources': [ + 'prog2.c', + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/src/subdir3/build/README.txt b/tools/gyp/test/generator-output/src/subdir3/build/README.txt new file mode 100644 index 00000000000..90ef8861931 --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir3/build/README.txt @@ -0,0 +1,4 @@ +A place-holder for this Xcode build output directory, so that the +test script can verify that .xcodeproj files are not created in +their normal location by making the src/ read-only, and then +selectively making this build directory writable. diff --git a/tools/gyp/test/generator-output/src/subdir3/inc3/include3.h b/tools/gyp/test/generator-output/src/subdir3/inc3/include3.h new file mode 100644 index 00000000000..bf53bf1f007 --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir3/inc3/include3.h @@ -0,0 +1 @@ +#define INCLUDE3_STRING "inc3/include3.h" diff --git a/tools/gyp/test/generator-output/src/subdir3/prog3.c b/tools/gyp/test/generator-output/src/subdir3/prog3.c new file mode 100644 index 00000000000..7848b45abd4 --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir3/prog3.c @@ -0,0 +1,18 @@ +#include <stdio.h> + +#include "inc.h" +#include "include1.h" +#include "include2.h" +#include "include3.h" +#include "deeper.h" + +int main(int argc, char *argv[]) +{ + printf("Hello from prog3.c\n"); + printf("Hello from %s\n", INC_STRING); + printf("Hello from %s\n", INCLUDE1_STRING); + printf("Hello from %s\n", INCLUDE2_STRING); + printf("Hello from %s\n", INCLUDE3_STRING); + printf("Hello from %s\n", DEEPER_STRING); + return 0; +} diff --git a/tools/gyp/test/generator-output/src/subdir3/prog3.gyp b/tools/gyp/test/generator-output/src/subdir3/prog3.gyp new file mode 100644 index 00000000000..46c5e000a27 --- /dev/null +++ b/tools/gyp/test/generator-output/src/subdir3/prog3.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. + +{ + 'includes': [ + '../symroot.gypi', + ], + 'targets': [ + { + 'target_name': 'prog3', + 'type': 'executable', + 'include_dirs': [ + '..', + '../inc1', + '../subdir2/inc2', + 'inc3', + '../subdir2/deeper', + ], + 'sources': [ + 'prog3.c', + ], + }, + ], +} diff --git a/tools/gyp/test/generator-output/src/symroot.gypi b/tools/gyp/test/generator-output/src/symroot.gypi new file mode 100644 index 00000000000..519916427c9 --- /dev/null +++ b/tools/gyp/test/generator-output/src/symroot.gypi @@ -0,0 +1,16 @@ +# 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. + +{ + 'variables': { + 'set_symroot%': 0, + }, + 'conditions': [ + ['set_symroot == 1', { + 'xcode_settings': { + 'SYMROOT': '<(DEPTH)/build', + }, + }], + ], +} diff --git a/tools/gyp/test/hard_dependency/gyptest-exported-hard-dependency.py b/tools/gyp/test/hard_dependency/gyptest-exported-hard-dependency.py new file mode 100755 index 00000000000..ba515288004 --- /dev/null +++ b/tools/gyp/test/hard_dependency/gyptest-exported-hard-dependency.py @@ -0,0 +1,37 @@ +#!/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 that a hard_dependency that is exported is pulled in as a dependency +for a target if the target is a static library and if the generator will +remove dependencies between static libraries. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +if test.format == 'dump_dependency_json': + test.skip_test('Skipping test; dependency JSON does not adjust ' \ + 'static libraries.\n') + +test.run_gyp('hard_dependency.gyp', chdir='src') + +chdir = 'relocate/src' +test.relocate('src', chdir) + +test.build('hard_dependency.gyp', 'c', chdir=chdir) + +# The 'a' static library should be built, as it has actions with side-effects +# that are necessary to compile 'c'. Even though 'c' does not directly depend +# on 'a', because 'a' is a hard_dependency that 'b' exports, 'c' should import +# it as a hard_dependency and ensure it is built before building 'c'. +test.built_file_must_exist('a', type=test.STATIC_LIB, chdir=chdir) +test.built_file_must_not_exist('b', type=test.STATIC_LIB, chdir=chdir) +test.built_file_must_exist('c', type=test.STATIC_LIB, chdir=chdir) +test.built_file_must_not_exist('d', type=test.STATIC_LIB, chdir=chdir) + +test.pass_test() diff --git a/tools/gyp/test/hard_dependency/gyptest-no-exported-hard-dependency.py b/tools/gyp/test/hard_dependency/gyptest-no-exported-hard-dependency.py new file mode 100755 index 00000000000..10774ca2a00 --- /dev/null +++ b/tools/gyp/test/hard_dependency/gyptest-no-exported-hard-dependency.py @@ -0,0 +1,36 @@ +#!/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 that a hard_dependency that is not exported is not pulled in as a +dependency for a target if the target does not explicitly specify a dependency +and none of its dependencies export the hard_dependency. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +if test.format == 'dump_dependency_json': + test.skip_test('Skipping test; dependency JSON does not adjust ' \ + 'static libaries.\n') + +test.run_gyp('hard_dependency.gyp', chdir='src') + +chdir = 'relocate/src' +test.relocate('src', chdir) + +test.build('hard_dependency.gyp', 'd', chdir=chdir) + +# Because 'c' does not export a hard_dependency, only the target 'd' should +# be built. This is because the 'd' target does not need the generated headers +# in order to be compiled. +test.built_file_must_not_exist('a', type=test.STATIC_LIB, chdir=chdir) +test.built_file_must_not_exist('b', type=test.STATIC_LIB, chdir=chdir) +test.built_file_must_not_exist('c', type=test.STATIC_LIB, chdir=chdir) +test.built_file_must_exist('d', type=test.STATIC_LIB, chdir=chdir) + +test.pass_test() diff --git a/tools/gyp/test/hard_dependency/src/a.c b/tools/gyp/test/hard_dependency/src/a.c new file mode 100644 index 00000000000..0fa0223c979 --- /dev/null +++ b/tools/gyp/test/hard_dependency/src/a.c @@ -0,0 +1,9 @@ +/* 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 "a.h" + +int funcA() { + return 42; +} diff --git a/tools/gyp/test/hard_dependency/src/a.h b/tools/gyp/test/hard_dependency/src/a.h new file mode 100644 index 00000000000..854a06504ad --- /dev/null +++ b/tools/gyp/test/hard_dependency/src/a.h @@ -0,0 +1,12 @@ +/* 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. */ + +#ifndef A_H_ +#define A_H_ + +#include "generated.h" + +int funcA(); + +#endif // A_H_ diff --git a/tools/gyp/test/hard_dependency/src/b.c b/tools/gyp/test/hard_dependency/src/b.c new file mode 100644 index 00000000000..0baace929e9 --- /dev/null +++ b/tools/gyp/test/hard_dependency/src/b.c @@ -0,0 +1,9 @@ +/* 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 "a.h" + +int funcB() { + return funcA(); +} diff --git a/tools/gyp/test/hard_dependency/src/b.h b/tools/gyp/test/hard_dependency/src/b.h new file mode 100644 index 00000000000..22b48cefe20 --- /dev/null +++ b/tools/gyp/test/hard_dependency/src/b.h @@ -0,0 +1,12 @@ +/* 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. */ + +#ifndef B_H_ +#define B_H_ + +#include "a.h" + +int funcB(); + +#endif // B_H_ diff --git a/tools/gyp/test/hard_dependency/src/c.c b/tools/gyp/test/hard_dependency/src/c.c new file mode 100644 index 00000000000..b0e0fb17d62 --- /dev/null +++ b/tools/gyp/test/hard_dependency/src/c.c @@ -0,0 +1,9 @@ +/* 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 "c.h" + +int funcC() { + return funcB(); +} diff --git a/tools/gyp/test/hard_dependency/src/c.h b/tools/gyp/test/hard_dependency/src/c.h new file mode 100644 index 00000000000..f4ea7fefa2b --- /dev/null +++ b/tools/gyp/test/hard_dependency/src/c.h @@ -0,0 +1,10 @@ +/* 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. */ + +#ifndef C_H_ +#define C_H_ + +int funcC(); + +#endif // C_H_ diff --git a/tools/gyp/test/hard_dependency/src/d.c b/tools/gyp/test/hard_dependency/src/d.c new file mode 100644 index 00000000000..d016c3ce718 --- /dev/null +++ b/tools/gyp/test/hard_dependency/src/d.c @@ -0,0 +1,9 @@ +/* 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. */ + +#include "c.h" + +int funcD() { + return funcC(); +} diff --git a/tools/gyp/test/hard_dependency/src/emit.py b/tools/gyp/test/hard_dependency/src/emit.py new file mode 100755 index 00000000000..2df74b79a12 --- /dev/null +++ b/tools/gyp/test/hard_dependency/src/emit.py @@ -0,0 +1,11 @@ +#!/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 + +f = open(sys.argv[1], 'wb') +f.write('/* Hello World */\n') +f.close() diff --git a/tools/gyp/test/hard_dependency/src/hard_dependency.gyp b/tools/gyp/test/hard_dependency/src/hard_dependency.gyp new file mode 100644 index 00000000000..4479c5f0452 --- /dev/null +++ b/tools/gyp/test/hard_dependency/src/hard_dependency.gyp @@ -0,0 +1,78 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'a', + 'type': 'static_library', + 'sources': [ + 'a.c', + 'a.h', + ], + 'hard_dependency': 1, + 'actions': [ + { + 'action_name': 'generate_headers', + 'inputs': [ + 'emit.py' + ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/generated.h' + ], + 'action': [ + 'python', + 'emit.py', + '<(SHARED_INTERMEDIATE_DIR)/generated.h', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + 'include_dirs': [ + '<(SHARED_INTERMEDIATE_DIR)', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '<(SHARED_INTERMEDIATE_DIR)', + ], + }, + }, + { + 'target_name': 'b', + 'type': 'static_library', + 'sources': [ + 'b.c', + 'b.h', + ], + 'dependencies': [ + 'a', + ], + 'export_dependent_settings': [ + 'a', + ], + }, + { + 'target_name': 'c', + 'type': 'static_library', + 'sources': [ + 'c.c', + 'c.h', + ], + 'dependencies': [ + 'b', + ], + }, + { + 'target_name': 'd', + 'type': 'static_library', + 'sources': [ + 'd.c', + ], + 'dependencies': [ + 'c', + ], + } + ], +} diff --git a/tools/gyp/test/hello/gyptest-all.py b/tools/gyp/test/hello/gyptest-all.py new file mode 100755 index 00000000000..1739b6886e9 --- /dev/null +++ b/tools/gyp/test/hello/gyptest-all.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 simplest-possible build of a "Hello, world!" program +using an explicit build target of 'all'. +""" + +import TestGyp + +test = TestGyp.TestGyp(workdir='workarea_all') + +test.run_gyp('hello.gyp') + +test.build('hello.gyp', test.ALL) + +test.run_built_executable('hello', stdout="Hello, world!\n") + +test.up_to_date('hello.gyp', test.ALL) + +test.pass_test() diff --git a/tools/gyp/test/hello/gyptest-default.py b/tools/gyp/test/hello/gyptest-default.py new file mode 100755 index 00000000000..22377e7ac50 --- /dev/null +++ b/tools/gyp/test/hello/gyptest-default.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 simplest-possible build of a "Hello, world!" program +using the default build target. +""" + +import TestGyp + +test = TestGyp.TestGyp(workdir='workarea_default') + +test.run_gyp('hello.gyp') + +test.build('hello.gyp') + +test.run_built_executable('hello', stdout="Hello, world!\n") + +test.up_to_date('hello.gyp', test.DEFAULT) + +test.pass_test() diff --git a/tools/gyp/test/hello/gyptest-disable-regyp.py b/tools/gyp/test/hello/gyptest-disable-regyp.py new file mode 100755 index 00000000000..1e4b3066748 --- /dev/null +++ b/tools/gyp/test/hello/gyptest-disable-regyp.py @@ -0,0 +1,32 @@ +#!/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 Makefiles don't get rebuilt when a source gyp file changes and +the disable_regeneration generator flag is set. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('hello.gyp', '-Gauto_regeneration=0') + +test.build('hello.gyp', test.ALL) + +test.run_built_executable('hello', stdout="Hello, world!\n") + +# Sleep so that the changed gyp file will have a newer timestamp than the +# previously generated build files. +test.sleep() +test.write('hello.gyp', test.read('hello2.gyp')) + +test.build('hello.gyp', test.ALL) + +# Should still be the old executable, as regeneration was disabled. +test.run_built_executable('hello', stdout="Hello, world!\n") + +test.pass_test() diff --git a/tools/gyp/test/hello/gyptest-regyp.py b/tools/gyp/test/hello/gyptest-regyp.py new file mode 100755 index 00000000000..827c7235ce4 --- /dev/null +++ b/tools/gyp/test/hello/gyptest-regyp.py @@ -0,0 +1,32 @@ +#!/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 Makefiles get rebuilt when a source gyp file changes. +""" + +import TestGyp + +# Regenerating build files when a gyp file changes is currently only supported +# by the make generator. +test = TestGyp.TestGyp(formats=['make']) + +test.run_gyp('hello.gyp') + +test.build('hello.gyp', test.ALL) + +test.run_built_executable('hello', stdout="Hello, world!\n") + +# Sleep so that the changed gyp file will have a newer timestamp than the +# previously generated build files. +test.sleep() +test.write('hello.gyp', test.read('hello2.gyp')) + +test.build('hello.gyp', test.ALL) + +test.run_built_executable('hello', stdout="Hello, two!\n") + +test.pass_test() diff --git a/tools/gyp/test/hello/gyptest-target.py b/tools/gyp/test/hello/gyptest-target.py new file mode 100755 index 00000000000..1abaf7057bf --- /dev/null +++ b/tools/gyp/test/hello/gyptest-target.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 simplest-possible build of a "Hello, world!" program +using an explicit build target of 'hello'. +""" + +import TestGyp + +test = TestGyp.TestGyp(workdir='workarea_target') + +test.run_gyp('hello.gyp') + +test.build('hello.gyp', 'hello') + +test.run_built_executable('hello', stdout="Hello, world!\n") + +test.up_to_date('hello.gyp', 'hello') + +test.pass_test() diff --git a/tools/gyp/test/hello/hello.c b/tools/gyp/test/hello/hello.c new file mode 100644 index 00000000000..8dbecc0492c --- /dev/null +++ b/tools/gyp/test/hello/hello.c @@ -0,0 +1,11 @@ +/* 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. */ + +#include <stdio.h> + +int main(int argc, char *argv[]) +{ + printf("Hello, world!\n"); + return 0; +} diff --git a/tools/gyp/test/hello/hello.gyp b/tools/gyp/test/hello/hello.gyp new file mode 100644 index 00000000000..1974d51ccd1 --- /dev/null +++ b/tools/gyp/test/hello/hello.gyp @@ -0,0 +1,15 @@ +# 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': 'hello', + 'type': 'executable', + 'sources': [ + 'hello.c', + ], + }, + ], +} diff --git a/tools/gyp/test/hello/hello2.c b/tools/gyp/test/hello/hello2.c new file mode 100644 index 00000000000..19ef3fbd5cf --- /dev/null +++ b/tools/gyp/test/hello/hello2.c @@ -0,0 +1,11 @@ +/* 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. */ + +#include <stdio.h> + +int main(int argc, char *argv[]) +{ + printf("Hello, two!\n"); + return 0; +} diff --git a/tools/gyp/test/hello/hello2.gyp b/tools/gyp/test/hello/hello2.gyp new file mode 100644 index 00000000000..25b08caf3ca --- /dev/null +++ b/tools/gyp/test/hello/hello2.gyp @@ -0,0 +1,15 @@ +# 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': 'hello', + 'type': 'executable', + 'sources': [ + 'hello2.c', + ], + }, + ], +} diff --git a/tools/gyp/test/home_dot_gyp/gyptest-home-includes-regyp.py b/tools/gyp/test/home_dot_gyp/gyptest-home-includes-regyp.py new file mode 100755 index 00000000000..974db7fee5c --- /dev/null +++ b/tools/gyp/test/home_dot_gyp/gyptest-home-includes-regyp.py @@ -0,0 +1,44 @@ +#!/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 inclusion of $HOME/.gyp/includes.gypi works properly with relocation +and with regeneration. +""" + +import os +import TestGyp + +# Regenerating build files when a gyp file changes is currently only supported +# by the make generator. +test = TestGyp.TestGyp(formats=['make']) + +os.environ['HOME'] = os.path.abspath('home') + +test.run_gyp('all.gyp', chdir='src') + +# After relocating, we should still be able to build (build file shouldn't +# contain relative reference to ~/.gyp/includes.gypi) +test.relocate('src', 'relocate/src') + +test.build('all.gyp', test.ALL, chdir='relocate/src') + +test.run_built_executable('printfoo', + chdir='relocate/src', + stdout='FOO is fromhome\n') + +# Building should notice any changes to ~/.gyp/includes.gypi and regyp. +test.sleep() + +test.write('home/.gyp/include.gypi', test.read('home2/.gyp/include.gypi')) + +test.build('all.gyp', test.ALL, chdir='relocate/src') + +test.run_built_executable('printfoo', + chdir='relocate/src', + stdout='FOO is fromhome2\n') + +test.pass_test() diff --git a/tools/gyp/test/home_dot_gyp/gyptest-home-includes.py b/tools/gyp/test/home_dot_gyp/gyptest-home-includes.py new file mode 100755 index 00000000000..3131e2d2482 --- /dev/null +++ b/tools/gyp/test/home_dot_gyp/gyptest-home-includes.py @@ -0,0 +1,30 @@ +#!/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 inclusion of $HOME/.gyp/includes.gypi works. +""" + +import os +import TestGyp + +test = TestGyp.TestGyp() + +os.environ['HOME'] = os.path.abspath('home') + +test.run_gyp('all.gyp', chdir='src') + +# After relocating, we should still be able to build (build file shouldn't +# contain relative reference to ~/.gyp/includes.gypi) +test.relocate('src', 'relocate/src') + +test.build('all.gyp', test.ALL, chdir='relocate/src') + +test.run_built_executable('printfoo', + chdir='relocate/src', + stdout='FOO is fromhome\n') + +test.pass_test() diff --git a/tools/gyp/test/home_dot_gyp/home/.gyp/include.gypi b/tools/gyp/test/home_dot_gyp/home/.gyp/include.gypi new file mode 100644 index 00000000000..fcfb39befd8 --- /dev/null +++ b/tools/gyp/test/home_dot_gyp/home/.gyp/include.gypi @@ -0,0 +1,5 @@ +{ + 'variables': { + 'foo': '"fromhome"', + }, +} diff --git a/tools/gyp/test/home_dot_gyp/home2/.gyp/include.gypi b/tools/gyp/test/home_dot_gyp/home2/.gyp/include.gypi new file mode 100644 index 00000000000..f0d84b31ad5 --- /dev/null +++ b/tools/gyp/test/home_dot_gyp/home2/.gyp/include.gypi @@ -0,0 +1,5 @@ +{ + 'variables': { + 'foo': '"fromhome2"', + }, +} diff --git a/tools/gyp/test/home_dot_gyp/src/all.gyp b/tools/gyp/test/home_dot_gyp/src/all.gyp new file mode 100644 index 00000000000..14b6aea2859 --- /dev/null +++ b/tools/gyp/test/home_dot_gyp/src/all.gyp @@ -0,0 +1,22 @@ +# 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. + +{ + 'variables': { + 'foo%': '"fromdefault"', + }, + 'targets': [ + { + 'target_name': 'printfoo', + 'type': 'executable', + 'sources': [ + 'printfoo.c', + ], + 'defines': [ + 'FOO=<(foo)', + ], + }, + ], +} + diff --git a/tools/gyp/test/home_dot_gyp/src/printfoo.c b/tools/gyp/test/home_dot_gyp/src/printfoo.c new file mode 100644 index 00000000000..92d2cbacb7b --- /dev/null +++ b/tools/gyp/test/home_dot_gyp/src/printfoo.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main(int argc, char *argv[]) +{ + printf("FOO is %s\n", FOO); + return 0; +} diff --git a/tools/gyp/test/include_dirs/gyptest-all.py b/tools/gyp/test/include_dirs/gyptest-all.py new file mode 100755 index 00000000000..94a1338d493 --- /dev/null +++ b/tools/gyp/test/include_dirs/gyptest-all.py @@ -0,0 +1,46 @@ +#!/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 use of include_dirs when using an explicit build target of 'all'. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +if test.format == 'scons': + test.skip_test('TODO: http://code.google.com/p/gyp/issues/detail?id=176\n') + +test.run_gyp('includes.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('includes.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello from includes.c +Hello from inc.h +Hello from include1.h +Hello from subdir/inc2/include2.h +Hello from shadow2/shadow.h +""" +test.run_built_executable('includes', stdout=expect, chdir='relocate/src') + +if test.format == 'xcode': + chdir='relocate/src/subdir' +else: + chdir='relocate/src' + +expect = """\ +Hello from subdir/subdir_includes.c +Hello from subdir/inc.h +Hello from include1.h +Hello from subdir/inc2/include2.h +""" +test.run_built_executable('subdir_includes', stdout=expect, chdir=chdir) + +test.pass_test() diff --git a/tools/gyp/test/include_dirs/gyptest-default.py b/tools/gyp/test/include_dirs/gyptest-default.py new file mode 100755 index 00000000000..42acd1f9625 --- /dev/null +++ b/tools/gyp/test/include_dirs/gyptest-default.py @@ -0,0 +1,46 @@ +#!/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 use of include_dirs when using the default build target. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +if test.format == 'scons': + test.skip_test('TODO: http://code.google.com/p/gyp/issues/detail?id=176\n') + +test.run_gyp('includes.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('includes.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello from includes.c +Hello from inc.h +Hello from include1.h +Hello from subdir/inc2/include2.h +Hello from shadow2/shadow.h +""" +test.run_built_executable('includes', stdout=expect, chdir='relocate/src') + +if test.format == 'xcode': + chdir='relocate/src/subdir' +else: + chdir='relocate/src' + +expect = """\ +Hello from subdir/subdir_includes.c +Hello from subdir/inc.h +Hello from include1.h +Hello from subdir/inc2/include2.h +""" +test.run_built_executable('subdir_includes', stdout=expect, chdir=chdir) + +test.pass_test() diff --git a/tools/gyp/test/include_dirs/src/inc.h b/tools/gyp/test/include_dirs/src/inc.h new file mode 100644 index 00000000000..0398d6915f9 --- /dev/null +++ b/tools/gyp/test/include_dirs/src/inc.h @@ -0,0 +1 @@ +#define INC_STRING "inc.h" diff --git a/tools/gyp/test/include_dirs/src/inc1/include1.h b/tools/gyp/test/include_dirs/src/inc1/include1.h new file mode 100644 index 00000000000..43356b5f47a --- /dev/null +++ b/tools/gyp/test/include_dirs/src/inc1/include1.h @@ -0,0 +1 @@ +#define INCLUDE1_STRING "include1.h" diff --git a/tools/gyp/test/include_dirs/src/includes.c b/tools/gyp/test/include_dirs/src/includes.c new file mode 100644 index 00000000000..e2afbd3ed8c --- /dev/null +++ b/tools/gyp/test/include_dirs/src/includes.c @@ -0,0 +1,19 @@ +#include <stdio.h> + +#include "inc.h" +#include "include1.h" +#include "include2.h" +#include "shadow.h" + +int main(int argc, char *argv[]) +{ + printf("Hello from includes.c\n"); + printf("Hello from %s\n", INC_STRING); + printf("Hello from %s\n", INCLUDE1_STRING); + printf("Hello from %s\n", INCLUDE2_STRING); + /* Test that include_dirs happen first: The gyp file has a -Ishadow1 + cflag and an include_dir of shadow2. Including shadow.h should get + the shadow.h from the include_dir. */ + printf("Hello from %s\n", SHADOW_STRING); + return 0; +} diff --git a/tools/gyp/test/include_dirs/src/includes.gyp b/tools/gyp/test/include_dirs/src/includes.gyp new file mode 100644 index 00000000000..3592690208a --- /dev/null +++ b/tools/gyp/test/include_dirs/src/includes.gyp @@ -0,0 +1,27 @@ +# 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': 'includes', + 'type': 'executable', + 'dependencies': [ + 'subdir/subdir_includes.gyp:subdir_includes', + ], + 'cflags': [ + '-Ishadow1', + ], + 'include_dirs': [ + '.', + 'inc1', + 'shadow2', + 'subdir/inc2', + ], + 'sources': [ + 'includes.c', + ], + }, + ], +} diff --git a/tools/gyp/test/include_dirs/src/shadow1/shadow.h b/tools/gyp/test/include_dirs/src/shadow1/shadow.h new file mode 100644 index 00000000000..80f6de20b86 --- /dev/null +++ b/tools/gyp/test/include_dirs/src/shadow1/shadow.h @@ -0,0 +1 @@ +#define SHADOW_STRING "shadow1/shadow.h" diff --git a/tools/gyp/test/include_dirs/src/shadow2/shadow.h b/tools/gyp/test/include_dirs/src/shadow2/shadow.h new file mode 100644 index 00000000000..fad5ccd0856 --- /dev/null +++ b/tools/gyp/test/include_dirs/src/shadow2/shadow.h @@ -0,0 +1 @@ +#define SHADOW_STRING "shadow2/shadow.h" diff --git a/tools/gyp/test/include_dirs/src/subdir/inc.h b/tools/gyp/test/include_dirs/src/subdir/inc.h new file mode 100644 index 00000000000..0a68d7b36ad --- /dev/null +++ b/tools/gyp/test/include_dirs/src/subdir/inc.h @@ -0,0 +1 @@ +#define INC_STRING "subdir/inc.h" diff --git a/tools/gyp/test/include_dirs/src/subdir/inc2/include2.h b/tools/gyp/test/include_dirs/src/subdir/inc2/include2.h new file mode 100644 index 00000000000..721577effbd --- /dev/null +++ b/tools/gyp/test/include_dirs/src/subdir/inc2/include2.h @@ -0,0 +1 @@ +#define INCLUDE2_STRING "subdir/inc2/include2.h" diff --git a/tools/gyp/test/include_dirs/src/subdir/subdir_includes.c b/tools/gyp/test/include_dirs/src/subdir/subdir_includes.c new file mode 100644 index 00000000000..727f6822058 --- /dev/null +++ b/tools/gyp/test/include_dirs/src/subdir/subdir_includes.c @@ -0,0 +1,14 @@ +#include <stdio.h> + +#include "inc.h" +#include "include1.h" +#include "include2.h" + +int main(int argc, char *argv[]) +{ + printf("Hello from subdir/subdir_includes.c\n"); + printf("Hello from %s\n", INC_STRING); + printf("Hello from %s\n", INCLUDE1_STRING); + printf("Hello from %s\n", INCLUDE2_STRING); + return 0; +} diff --git a/tools/gyp/test/include_dirs/src/subdir/subdir_includes.gyp b/tools/gyp/test/include_dirs/src/subdir/subdir_includes.gyp new file mode 100644 index 00000000000..257d052c3c9 --- /dev/null +++ b/tools/gyp/test/include_dirs/src/subdir/subdir_includes.gyp @@ -0,0 +1,20 @@ +# 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_includes', + 'type': 'executable', + 'include_dirs': [ + '.', + '../inc1', + 'inc2', + ], + 'sources': [ + 'subdir_includes.c', + ], + }, + ], +} diff --git a/tools/gyp/test/intermediate_dir/gyptest-intermediate-dir.py b/tools/gyp/test/intermediate_dir/gyptest-intermediate-dir.py new file mode 100755 index 00000000000..b4fd16f4689 --- /dev/null +++ b/tools/gyp/test/intermediate_dir/gyptest-intermediate-dir.py @@ -0,0 +1,45 @@ +#!/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 that targets have independent INTERMEDIATE_DIRs. +""" + +import TestGyp + +import os +import sys + +test = TestGyp.TestGyp() + +test.run_gyp('test.gyp', chdir='src') +test.build('test.gyp', 'target1', chdir='src') +# Check stuff exists. +intermediate_file1 = test.read('src/outfile.txt') +test.must_contain(intermediate_file1, 'target1') + +shared_intermediate_file1 = test.read('src/shared_outfile.txt') +test.must_contain(shared_intermediate_file1, 'shared_target1') + +test.run_gyp('test2.gyp', chdir='src') +test.build('test2.gyp', 'target2', chdir='src') +# Check INTERMEDIATE_DIR file didn't get overwritten but SHARED_INTERMEDIAT_DIR +# file did. +intermediate_file2 = test.read('src/outfile.txt') +test.must_contain(intermediate_file1, 'target1') +test.must_contain(intermediate_file2, 'target2') + +shared_intermediate_file2 = test.read('src/shared_outfile.txt') +if shared_intermediate_file1 != shared_intermediate_file2: + test.fail_test(shared_intermediate_file1 + ' != ' + shared_intermediate_file2) + +# These sometimes fail flakily with the xcode generator due to the shared file +# still containing 'target1'. Maybe the xcode build runs actions asynchronously? +# Asserting that the intermediate file names are identical is good enough. +#test.must_contain(shared_intermediate_file1, 'shared_target2') +#test.must_contain(shared_intermediate_file2, 'shared_target2') + +test.pass_test() diff --git a/tools/gyp/test/intermediate_dir/src/script.py b/tools/gyp/test/intermediate_dir/src/script.py new file mode 100755 index 00000000000..fa828a06b98 --- /dev/null +++ b/tools/gyp/test/intermediate_dir/src/script.py @@ -0,0 +1,24 @@ +#!/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. + +# Takes 3 arguments. Writes the 1st argument to the file in the 2nd argument, +# and writes the absolute path to the file in the 2nd argument to the file in +# the 3rd argument. + +import os +import shlex +import sys + +if len(sys.argv) == 3 and ' ' in sys.argv[2]: + sys.argv[2], fourth = shlex.split(sys.argv[2]) + sys.argv.append(fourth) + +#print >>sys.stderr, sys.argv + +with open(sys.argv[2], 'w') as f: + f.write(sys.argv[1]) + +with open(sys.argv[3], 'w') as f: + f.write(os.path.abspath(sys.argv[2])) diff --git a/tools/gyp/test/intermediate_dir/src/test.gyp b/tools/gyp/test/intermediate_dir/src/test.gyp new file mode 100644 index 00000000000..9cd07c9e34b --- /dev/null +++ b/tools/gyp/test/intermediate_dir/src/test.gyp @@ -0,0 +1,40 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'target1', + 'type': 'none', + 'actions': [ + { + 'action_name': 'intermediate', + 'inputs': [], + 'outputs': [ + '<(INTERMEDIATE_DIR)/intermediate_out.txt', + 'outfile.txt', + ], + 'action': [ + 'python', 'script.py', 'target1', '<(_outputs)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + { + 'action_name': 'shared_intermediate', + 'inputs': [], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/intermediate_out.txt', + 'shared_outfile.txt', + ], + 'action': [ + 'python', 'script.py', 'shared_target1', '<(_outputs)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/intermediate_dir/src/test2.gyp b/tools/gyp/test/intermediate_dir/src/test2.gyp new file mode 100644 index 00000000000..07ed9a03e63 --- /dev/null +++ b/tools/gyp/test/intermediate_dir/src/test2.gyp @@ -0,0 +1,40 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'target2', + 'type': 'none', + 'actions': [ + { + 'action_name': 'intermediate', + 'inputs': [], + 'outputs': [ + '<(INTERMEDIATE_DIR)/intermediate_out.txt', + 'outfile.txt', + ], + 'action': [ + 'python', 'script.py', 'target2', '<(_outputs)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + { + 'action_name': 'shared_intermediate', + 'inputs': [], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/intermediate_out.txt', + 'shared_outfile.txt', + ], + 'action': [ + 'python', 'script.py', 'shared_target2', '<(_outputs)', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/lib/README.txt b/tools/gyp/test/lib/README.txt new file mode 100644 index 00000000000..b3d724574e6 --- /dev/null +++ b/tools/gyp/test/lib/README.txt @@ -0,0 +1,17 @@ +Supporting modules for GYP testing. + + TestCmd.py + TestCommon.py + + Modules for generic testing of command-line utilities, + specifically including the ability to copy a test configuration + to temporary directories (with default cleanup on exit) as part + of running test scripts that invoke commands, compare actual + against expected output, etc. + + Our copies of these come from the SCons project, + http://www.scons.org/. + + TestGyp.py + + Modules for GYP-specific tests, of course. diff --git a/tools/gyp/test/lib/TestCmd.py b/tools/gyp/test/lib/TestCmd.py new file mode 100644 index 00000000000..45d901ca294 --- /dev/null +++ b/tools/gyp/test/lib/TestCmd.py @@ -0,0 +1,1594 @@ +""" +TestCmd.py: a testing framework for commands and scripts. + +The TestCmd module provides a framework for portable automated testing +of executable commands and scripts (in any language, not just Python), +especially commands and scripts that require file system interaction. + +In addition to running tests and evaluating conditions, the TestCmd +module manages and cleans up one or more temporary workspace +directories, and provides methods for creating files and directories in +those workspace directories from in-line data, here-documents), allowing +tests to be completely self-contained. + +A TestCmd environment object is created via the usual invocation: + + import TestCmd + test = TestCmd.TestCmd() + +There are a bunch of keyword arguments available at instantiation: + + test = TestCmd.TestCmd(description = 'string', + program = 'program_or_script_to_test', + interpreter = 'script_interpreter', + workdir = 'prefix', + subdir = 'subdir', + verbose = Boolean, + match = default_match_function, + diff = default_diff_function, + combine = Boolean) + +There are a bunch of methods that let you do different things: + + test.verbose_set(1) + + test.description_set('string') + + test.program_set('program_or_script_to_test') + + test.interpreter_set('script_interpreter') + test.interpreter_set(['script_interpreter', 'arg']) + + test.workdir_set('prefix') + test.workdir_set('') + + test.workpath('file') + test.workpath('subdir', 'file') + + test.subdir('subdir', ...) + + test.rmdir('subdir', ...) + + test.write('file', "contents\n") + test.write(['subdir', 'file'], "contents\n") + + test.read('file') + test.read(['subdir', 'file']) + test.read('file', mode) + test.read(['subdir', 'file'], mode) + + test.writable('dir', 1) + test.writable('dir', None) + + test.preserve(condition, ...) + + test.cleanup(condition) + + test.command_args(program = 'program_or_script_to_run', + interpreter = 'script_interpreter', + arguments = 'arguments to pass to program') + + test.run(program = 'program_or_script_to_run', + interpreter = 'script_interpreter', + arguments = 'arguments to pass to program', + chdir = 'directory_to_chdir_to', + stdin = 'input to feed to the program\n') + universal_newlines = True) + + p = test.start(program = 'program_or_script_to_run', + interpreter = 'script_interpreter', + arguments = 'arguments to pass to program', + universal_newlines = None) + + test.finish(self, p) + + test.pass_test() + test.pass_test(condition) + test.pass_test(condition, function) + + test.fail_test() + test.fail_test(condition) + test.fail_test(condition, function) + test.fail_test(condition, function, skip) + + test.no_result() + test.no_result(condition) + test.no_result(condition, function) + test.no_result(condition, function, skip) + + test.stdout() + test.stdout(run) + + test.stderr() + test.stderr(run) + + test.symlink(target, link) + + test.banner(string) + test.banner(string, width) + + test.diff(actual, expected) + + test.match(actual, expected) + + test.match_exact("actual 1\nactual 2\n", "expected 1\nexpected 2\n") + test.match_exact(["actual 1\n", "actual 2\n"], + ["expected 1\n", "expected 2\n"]) + + test.match_re("actual 1\nactual 2\n", regex_string) + test.match_re(["actual 1\n", "actual 2\n"], list_of_regexes) + + test.match_re_dotall("actual 1\nactual 2\n", regex_string) + test.match_re_dotall(["actual 1\n", "actual 2\n"], list_of_regexes) + + test.tempdir() + test.tempdir('temporary-directory') + + test.sleep() + test.sleep(seconds) + + test.where_is('foo') + test.where_is('foo', 'PATH1:PATH2') + test.where_is('foo', 'PATH1;PATH2', '.suffix3;.suffix4') + + test.unlink('file') + test.unlink('subdir', 'file') + +The TestCmd module provides pass_test(), fail_test(), and no_result() +unbound functions that report test results for use with the Aegis change +management system. These methods terminate the test immediately, +reporting PASSED, FAILED, or NO RESULT respectively, and exiting with +status 0 (success), 1 or 2 respectively. This allows for a distinction +between an actual failed test and a test that could not be properly +evaluated because of an external condition (such as a full file system +or incorrect permissions). + + import TestCmd + + TestCmd.pass_test() + TestCmd.pass_test(condition) + TestCmd.pass_test(condition, function) + + TestCmd.fail_test() + TestCmd.fail_test(condition) + TestCmd.fail_test(condition, function) + TestCmd.fail_test(condition, function, skip) + + TestCmd.no_result() + TestCmd.no_result(condition) + TestCmd.no_result(condition, function) + TestCmd.no_result(condition, function, skip) + +The TestCmd module also provides unbound functions that handle matching +in the same way as the match_*() methods described above. + + import TestCmd + + test = TestCmd.TestCmd(match = TestCmd.match_exact) + + test = TestCmd.TestCmd(match = TestCmd.match_re) + + test = TestCmd.TestCmd(match = TestCmd.match_re_dotall) + +The TestCmd module provides unbound functions that can be used for the +"diff" argument to TestCmd.TestCmd instantiation: + + import TestCmd + + test = TestCmd.TestCmd(match = TestCmd.match_re, + diff = TestCmd.diff_re) + + test = TestCmd.TestCmd(diff = TestCmd.simple_diff) + +The "diff" argument can also be used with standard difflib functions: + + import difflib + + test = TestCmd.TestCmd(diff = difflib.context_diff) + + test = TestCmd.TestCmd(diff = difflib.unified_diff) + +Lastly, the where_is() method also exists in an unbound function +version. + + import TestCmd + + TestCmd.where_is('foo') + TestCmd.where_is('foo', 'PATH1:PATH2') + TestCmd.where_is('foo', 'PATH1;PATH2', '.suffix3;.suffix4') +""" + +# Copyright 2000-2010 Steven Knight +# This module is free software, and you may redistribute it and/or modify +# it under the same terms as Python itself, so long as this copyright message +# and disclaimer are retained in their original form. +# +# IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +# SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF +# THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +# DAMAGE. +# +# THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, +# AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, +# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +__author__ = "Steven Knight <knight at baldmt dot com>" +__revision__ = "TestCmd.py 0.37.D001 2010/01/11 16:55:50 knight" +__version__ = "0.37" + +import errno +import os +import os.path +import re +import shutil +import stat +import string +import sys +import tempfile +import time +import traceback +import types +import UserList + +__all__ = [ + 'diff_re', + 'fail_test', + 'no_result', + 'pass_test', + 'match_exact', + 'match_re', + 'match_re_dotall', + 'python_executable', + 'TestCmd' +] + +try: + import difflib +except ImportError: + __all__.append('simple_diff') + +def is_List(e): + return type(e) is types.ListType \ + or isinstance(e, UserList.UserList) + +try: + from UserString import UserString +except ImportError: + class UserString: + pass + +if hasattr(types, 'UnicodeType'): + def is_String(e): + return type(e) is types.StringType \ + or type(e) is types.UnicodeType \ + or isinstance(e, UserString) +else: + def is_String(e): + return type(e) is types.StringType or isinstance(e, UserString) + +tempfile.template = 'testcmd.' +if os.name in ('posix', 'nt'): + tempfile.template = 'testcmd.' + str(os.getpid()) + '.' +else: + tempfile.template = 'testcmd.' + +re_space = re.compile('\s') + +_Cleanup = [] + +_chain_to_exitfunc = None + +def _clean(): + global _Cleanup + cleanlist = filter(None, _Cleanup) + del _Cleanup[:] + cleanlist.reverse() + for test in cleanlist: + test.cleanup() + if _chain_to_exitfunc: + _chain_to_exitfunc() + +try: + import atexit +except ImportError: + # TODO(1.5): atexit requires python 2.0, so chain sys.exitfunc + try: + _chain_to_exitfunc = sys.exitfunc + except AttributeError: + pass + sys.exitfunc = _clean +else: + atexit.register(_clean) + +try: + zip +except NameError: + def zip(*lists): + result = [] + for i in xrange(min(map(len, lists))): + result.append(tuple(map(lambda l, i=i: l[i], lists))) + return result + +class Collector: + def __init__(self, top): + self.entries = [top] + def __call__(self, arg, dirname, names): + pathjoin = lambda n, d=dirname: os.path.join(d, n) + self.entries.extend(map(pathjoin, names)) + +def _caller(tblist, skip): + string = "" + arr = [] + for file, line, name, text in tblist: + if file[-10:] == "TestCmd.py": + break + arr = [(file, line, name, text)] + arr + atfrom = "at" + for file, line, name, text in arr[skip:]: + if name in ("?", "<module>"): + name = "" + else: + name = " (" + name + ")" + string = string + ("%s line %d of %s%s\n" % (atfrom, line, file, name)) + atfrom = "\tfrom" + return string + +def fail_test(self = None, condition = 1, function = None, skip = 0): + """Cause the test to fail. + + By default, the fail_test() method reports that the test FAILED + and exits with a status of 1. If a condition argument is supplied, + the test fails only if the condition is true. + """ + if not condition: + return + if not function is None: + function() + of = "" + desc = "" + sep = " " + if not self is None: + if self.program: + of = " of " + self.program + sep = "\n\t" + if self.description: + desc = " [" + self.description + "]" + sep = "\n\t" + + at = _caller(traceback.extract_stack(), skip) + sys.stderr.write("FAILED test" + of + desc + sep + at) + + sys.exit(1) + +def no_result(self = None, condition = 1, function = None, skip = 0): + """Causes a test to exit with no valid result. + + By default, the no_result() method reports NO RESULT for the test + and exits with a status of 2. If a condition argument is supplied, + the test fails only if the condition is true. + """ + if not condition: + return + if not function is None: + function() + of = "" + desc = "" + sep = " " + if not self is None: + if self.program: + of = " of " + self.program + sep = "\n\t" + if self.description: + desc = " [" + self.description + "]" + sep = "\n\t" + + at = _caller(traceback.extract_stack(), skip) + sys.stderr.write("NO RESULT for test" + of + desc + sep + at) + + sys.exit(2) + +def pass_test(self = None, condition = 1, function = None): + """Causes a test to pass. + + By default, the pass_test() method reports PASSED for the test + and exits with a status of 0. If a condition argument is supplied, + the test passes only if the condition is true. + """ + if not condition: + return + if not function is None: + function() + sys.stderr.write("PASSED\n") + sys.exit(0) + +def match_exact(lines = None, matches = None): + """ + """ + if not is_List(lines): + lines = string.split(lines, "\n") + if not is_List(matches): + matches = string.split(matches, "\n") + if len(lines) != len(matches): + return + for i in range(len(lines)): + if lines[i] != matches[i]: + return + return 1 + +def match_re(lines = None, res = None): + """ + """ + if not is_List(lines): + lines = string.split(lines, "\n") + if not is_List(res): + res = string.split(res, "\n") + if len(lines) != len(res): + return + for i in range(len(lines)): + s = "^" + res[i] + "$" + try: + expr = re.compile(s) + except re.error, e: + msg = "Regular expression error in %s: %s" + raise re.error, msg % (repr(s), e[0]) + if not expr.search(lines[i]): + return + return 1 + +def match_re_dotall(lines = None, res = None): + """ + """ + if not type(lines) is type(""): + lines = string.join(lines, "\n") + if not type(res) is type(""): + res = string.join(res, "\n") + s = "^" + res + "$" + try: + expr = re.compile(s, re.DOTALL) + except re.error, e: + msg = "Regular expression error in %s: %s" + raise re.error, msg % (repr(s), e[0]) + if expr.match(lines): + return 1 + +try: + import difflib +except ImportError: + pass +else: + def simple_diff(a, b, fromfile='', tofile='', + fromfiledate='', tofiledate='', n=3, lineterm='\n'): + """ + A function with the same calling signature as difflib.context_diff + (diff -c) and difflib.unified_diff (diff -u) but which prints + output like the simple, unadorned 'diff" command. + """ + sm = difflib.SequenceMatcher(None, a, b) + def comma(x1, x2): + return x1+1 == x2 and str(x2) or '%s,%s' % (x1+1, x2) + result = [] + for op, a1, a2, b1, b2 in sm.get_opcodes(): + if op == 'delete': + result.append("%sd%d" % (comma(a1, a2), b1)) + result.extend(map(lambda l: '< ' + l, a[a1:a2])) + elif op == 'insert': + result.append("%da%s" % (a1, comma(b1, b2))) + result.extend(map(lambda l: '> ' + l, b[b1:b2])) + elif op == 'replace': + result.append("%sc%s" % (comma(a1, a2), comma(b1, b2))) + result.extend(map(lambda l: '< ' + l, a[a1:a2])) + result.append('---') + result.extend(map(lambda l: '> ' + l, b[b1:b2])) + return result + +def diff_re(a, b, fromfile='', tofile='', + fromfiledate='', tofiledate='', n=3, lineterm='\n'): + """ + A simple "diff" of two sets of lines when the expected lines + are regular expressions. This is a really dumb thing that + just compares each line in turn, so it doesn't look for + chunks of matching lines and the like--but at least it lets + you know exactly which line first didn't compare correctl... + """ + result = [] + diff = len(a) - len(b) + if diff < 0: + a = a + ['']*(-diff) + elif diff > 0: + b = b + ['']*diff + i = 0 + for aline, bline in zip(a, b): + s = "^" + aline + "$" + try: + expr = re.compile(s) + except re.error, e: + msg = "Regular expression error in %s: %s" + raise re.error, msg % (repr(s), e[0]) + if not expr.search(bline): + result.append("%sc%s" % (i+1, i+1)) + result.append('< ' + repr(a[i])) + result.append('---') + result.append('> ' + repr(b[i])) + i = i+1 + return result + +if os.name == 'java': + + python_executable = os.path.join(sys.prefix, 'jython') + +else: + + python_executable = sys.executable + +if sys.platform == 'win32': + + default_sleep_seconds = 2 + + def where_is(file, path=None, pathext=None): + if path is None: + path = os.environ['PATH'] + if is_String(path): + path = string.split(path, os.pathsep) + if pathext is None: + pathext = os.environ['PATHEXT'] + if is_String(pathext): + pathext = string.split(pathext, os.pathsep) + for ext in pathext: + if string.lower(ext) == string.lower(file[-len(ext):]): + pathext = [''] + break + for dir in path: + f = os.path.join(dir, file) + for ext in pathext: + fext = f + ext + if os.path.isfile(fext): + return fext + return None + +else: + + def where_is(file, path=None, pathext=None): + if path is None: + path = os.environ['PATH'] + if is_String(path): + path = string.split(path, os.pathsep) + for dir in path: + f = os.path.join(dir, file) + if os.path.isfile(f): + try: + st = os.stat(f) + except OSError: + continue + if stat.S_IMODE(st[stat.ST_MODE]) & 0111: + return f + return None + + default_sleep_seconds = 1 + + + +try: + import subprocess +except ImportError: + # The subprocess module doesn't exist in this version of Python, + # so we're going to cobble up something that looks just enough + # like its API for our purposes below. + import new + + subprocess = new.module('subprocess') + + subprocess.PIPE = 'PIPE' + subprocess.STDOUT = 'STDOUT' + subprocess.mswindows = (sys.platform == 'win32') + + try: + import popen2 + popen2.Popen3 + except AttributeError: + class Popen3: + universal_newlines = 1 + def __init__(self, command, **kw): + if sys.platform == 'win32' and command[0] == '"': + command = '"' + command + '"' + (stdin, stdout, stderr) = os.popen3(' ' + command) + self.stdin = stdin + self.stdout = stdout + self.stderr = stderr + def close_output(self): + self.stdout.close() + self.resultcode = self.stderr.close() + def wait(self): + resultcode = self.resultcode + if os.WIFEXITED(resultcode): + return os.WEXITSTATUS(resultcode) + elif os.WIFSIGNALED(resultcode): + return os.WTERMSIG(resultcode) + else: + return None + + else: + try: + popen2.Popen4 + except AttributeError: + # A cribbed Popen4 class, with some retrofitted code from + # the Python 1.5 Popen3 class methods to do certain things + # by hand. + class Popen4(popen2.Popen3): + childerr = None + + def __init__(self, cmd, bufsize=-1): + p2cread, p2cwrite = os.pipe() + c2pread, c2pwrite = os.pipe() + self.pid = os.fork() + if self.pid == 0: + # Child + os.dup2(p2cread, 0) + os.dup2(c2pwrite, 1) + os.dup2(c2pwrite, 2) + for i in range(3, popen2.MAXFD): + try: + os.close(i) + except: pass + try: + os.execvp(cmd[0], cmd) + finally: + os._exit(1) + # Shouldn't come here, I guess + os._exit(1) + os.close(p2cread) + self.tochild = os.fdopen(p2cwrite, 'w', bufsize) + os.close(c2pwrite) + self.fromchild = os.fdopen(c2pread, 'r', bufsize) + popen2._active.append(self) + + popen2.Popen4 = Popen4 + + class Popen3(popen2.Popen3, popen2.Popen4): + universal_newlines = 1 + def __init__(self, command, **kw): + if kw.get('stderr') == 'STDOUT': + apply(popen2.Popen4.__init__, (self, command, 1)) + else: + apply(popen2.Popen3.__init__, (self, command, 1)) + self.stdin = self.tochild + self.stdout = self.fromchild + self.stderr = self.childerr + def wait(self, *args, **kw): + resultcode = apply(popen2.Popen3.wait, (self,)+args, kw) + if os.WIFEXITED(resultcode): + return os.WEXITSTATUS(resultcode) + elif os.WIFSIGNALED(resultcode): + return os.WTERMSIG(resultcode) + else: + return None + + subprocess.Popen = Popen3 + + + +# From Josiah Carlson, +# ASPN : Python Cookbook : Module to allow Asynchronous subprocess use on Windows and Posix platforms +# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440554 + +PIPE = subprocess.PIPE + +if subprocess.mswindows: + from win32file import ReadFile, WriteFile + from win32pipe import PeekNamedPipe + import msvcrt +else: + import select + import fcntl + + try: fcntl.F_GETFL + except AttributeError: fcntl.F_GETFL = 3 + + try: fcntl.F_SETFL + except AttributeError: fcntl.F_SETFL = 4 + +class Popen(subprocess.Popen): + def recv(self, maxsize=None): + return self._recv('stdout', maxsize) + + def recv_err(self, maxsize=None): + return self._recv('stderr', maxsize) + + def send_recv(self, input='', maxsize=None): + return self.send(input), self.recv(maxsize), self.recv_err(maxsize) + + def get_conn_maxsize(self, which, maxsize): + if maxsize is None: + maxsize = 1024 + elif maxsize < 1: + maxsize = 1 + return getattr(self, which), maxsize + + def _close(self, which): + getattr(self, which).close() + setattr(self, which, None) + + if subprocess.mswindows: + def send(self, input): + if not self.stdin: + return None + + try: + x = msvcrt.get_osfhandle(self.stdin.fileno()) + (errCode, written) = WriteFile(x, input) + except ValueError: + return self._close('stdin') + except (subprocess.pywintypes.error, Exception), why: + if why[0] in (109, errno.ESHUTDOWN): + return self._close('stdin') + raise + + return written + + def _recv(self, which, maxsize): + conn, maxsize = self.get_conn_maxsize(which, maxsize) + if conn is None: + return None + + try: + x = msvcrt.get_osfhandle(conn.fileno()) + (read, nAvail, nMessage) = PeekNamedPipe(x, 0) + if maxsize < nAvail: + nAvail = maxsize + if nAvail > 0: + (errCode, read) = ReadFile(x, nAvail, None) + except ValueError: + return self._close(which) + except (subprocess.pywintypes.error, Exception), why: + if why[0] in (109, errno.ESHUTDOWN): + return self._close(which) + raise + + #if self.universal_newlines: + # read = self._translate_newlines(read) + return read + + else: + def send(self, input): + if not self.stdin: + return None + + if not select.select([], [self.stdin], [], 0)[1]: + return 0 + + try: + written = os.write(self.stdin.fileno(), input) + except OSError, why: + if why[0] == errno.EPIPE: #broken pipe + return self._close('stdin') + raise + + return written + + def _recv(self, which, maxsize): + conn, maxsize = self.get_conn_maxsize(which, maxsize) + if conn is None: + return None + + try: + flags = fcntl.fcntl(conn, fcntl.F_GETFL) + except TypeError: + flags = None + else: + if not conn.closed: + fcntl.fcntl(conn, fcntl.F_SETFL, flags| os.O_NONBLOCK) + + try: + if not select.select([conn], [], [], 0)[0]: + return '' + + r = conn.read(maxsize) + if not r: + return self._close(which) + + #if self.universal_newlines: + # r = self._translate_newlines(r) + return r + finally: + if not conn.closed and not flags is None: + fcntl.fcntl(conn, fcntl.F_SETFL, flags) + +disconnect_message = "Other end disconnected!" + +def recv_some(p, t=.1, e=1, tr=5, stderr=0): + if tr < 1: + tr = 1 + x = time.time()+t + y = [] + r = '' + pr = p.recv + if stderr: + pr = p.recv_err + while time.time() < x or r: + r = pr() + if r is None: + if e: + raise Exception(disconnect_message) + else: + break + elif r: + y.append(r) + else: + time.sleep(max((x-time.time())/tr, 0)) + return ''.join(y) + +# TODO(3.0: rewrite to use memoryview() +def send_all(p, data): + while len(data): + sent = p.send(data) + if sent is None: + raise Exception(disconnect_message) + data = buffer(data, sent) + + + +try: + object +except NameError: + class object: + pass + + + +class TestCmd(object): + """Class TestCmd + """ + + def __init__(self, description = None, + program = None, + interpreter = None, + workdir = None, + subdir = None, + verbose = None, + match = None, + diff = None, + combine = 0, + universal_newlines = 1): + self._cwd = os.getcwd() + self.description_set(description) + self.program_set(program) + self.interpreter_set(interpreter) + if verbose is None: + try: + verbose = max( 0, int(os.environ.get('TESTCMD_VERBOSE', 0)) ) + except ValueError: + verbose = 0 + self.verbose_set(verbose) + self.combine = combine + self.universal_newlines = universal_newlines + if match is not None: + self.match_function = match + else: + self.match_function = match_re + if diff is not None: + self.diff_function = diff + else: + try: + difflib + except NameError: + pass + else: + self.diff_function = simple_diff + #self.diff_function = difflib.context_diff + #self.diff_function = difflib.unified_diff + self._dirlist = [] + self._preserve = {'pass_test': 0, 'fail_test': 0, 'no_result': 0} + if os.environ.has_key('PRESERVE') and not os.environ['PRESERVE'] is '': + self._preserve['pass_test'] = os.environ['PRESERVE'] + self._preserve['fail_test'] = os.environ['PRESERVE'] + self._preserve['no_result'] = os.environ['PRESERVE'] + else: + try: + self._preserve['pass_test'] = os.environ['PRESERVE_PASS'] + except KeyError: + pass + try: + self._preserve['fail_test'] = os.environ['PRESERVE_FAIL'] + except KeyError: + pass + try: + self._preserve['no_result'] = os.environ['PRESERVE_NO_RESULT'] + except KeyError: + pass + self._stdout = [] + self._stderr = [] + self.status = None + self.condition = 'no_result' + self.workdir_set(workdir) + self.subdir(subdir) + + def __del__(self): + self.cleanup() + + def __repr__(self): + return "%x" % id(self) + + banner_char = '=' + banner_width = 80 + + def banner(self, s, width=None): + if width is None: + width = self.banner_width + return s + self.banner_char * (width - len(s)) + + if os.name == 'posix': + + def escape(self, arg): + "escape shell special characters" + slash = '\\' + special = '"$' + + arg = string.replace(arg, slash, slash+slash) + for c in special: + arg = string.replace(arg, c, slash+c) + + if re_space.search(arg): + arg = '"' + arg + '"' + return arg + + else: + + # Windows does not allow special characters in file names + # anyway, so no need for an escape function, we will just quote + # the arg. + def escape(self, arg): + if re_space.search(arg): + arg = '"' + arg + '"' + return arg + + def canonicalize(self, path): + if is_List(path): + path = apply(os.path.join, tuple(path)) + if not os.path.isabs(path): + path = os.path.join(self.workdir, path) + return path + + def chmod(self, path, mode): + """Changes permissions on the specified file or directory + path name.""" + path = self.canonicalize(path) + os.chmod(path, mode) + + def cleanup(self, condition = None): + """Removes any temporary working directories for the specified + TestCmd environment. If the environment variable PRESERVE was + set when the TestCmd environment was created, temporary working + directories are not removed. If any of the environment variables + PRESERVE_PASS, PRESERVE_FAIL, or PRESERVE_NO_RESULT were set + when the TestCmd environment was created, then temporary working + directories are not removed if the test passed, failed, or had + no result, respectively. Temporary working directories are also + preserved for conditions specified via the preserve method. + + Typically, this method is not called directly, but is used when + the script exits to clean up temporary working directories as + appropriate for the exit status. + """ + if not self._dirlist: + return + os.chdir(self._cwd) + self.workdir = None + if condition is None: + condition = self.condition + if self._preserve[condition]: + for dir in self._dirlist: + print "Preserved directory", dir + else: + list = self._dirlist[:] + list.reverse() + for dir in list: + self.writable(dir, 1) + shutil.rmtree(dir, ignore_errors = 1) + self._dirlist = [] + + try: + global _Cleanup + _Cleanup.remove(self) + except (AttributeError, ValueError): + pass + + def command_args(self, program = None, + interpreter = None, + arguments = None): + if program: + if type(program) == type('') and not os.path.isabs(program): + program = os.path.join(self._cwd, program) + else: + program = self.program + if not interpreter: + interpreter = self.interpreter + if not type(program) in [type([]), type(())]: + program = [program] + cmd = list(program) + if interpreter: + if not type(interpreter) in [type([]), type(())]: + interpreter = [interpreter] + cmd = list(interpreter) + cmd + if arguments: + if type(arguments) == type(''): + arguments = string.split(arguments) + cmd.extend(arguments) + return cmd + + def description_set(self, description): + """Set the description of the functionality being tested. + """ + self.description = description + + try: + difflib + except NameError: + def diff(self, a, b, name, *args, **kw): + print self.banner('Expected %s' % name) + print a + print self.banner('Actual %s' % name) + print b + else: + def diff(self, a, b, name, *args, **kw): + print self.banner(name) + args = (a.splitlines(), b.splitlines()) + args + lines = apply(self.diff_function, args, kw) + for l in lines: + print l + + def fail_test(self, condition = 1, function = None, skip = 0): + """Cause the test to fail. + """ + if not condition: + return + self.condition = 'fail_test' + fail_test(self = self, + condition = condition, + function = function, + skip = skip) + + def interpreter_set(self, interpreter): + """Set the program to be used to interpret the program + under test as a script. + """ + self.interpreter = interpreter + + def match(self, lines, matches): + """Compare actual and expected file contents. + """ + return self.match_function(lines, matches) + + def match_exact(self, lines, matches): + """Compare actual and expected file contents. + """ + return match_exact(lines, matches) + + def match_re(self, lines, res): + """Compare actual and expected file contents. + """ + return match_re(lines, res) + + def match_re_dotall(self, lines, res): + """Compare actual and expected file contents. + """ + return match_re_dotall(lines, res) + + def no_result(self, condition = 1, function = None, skip = 0): + """Report that the test could not be run. + """ + if not condition: + return + self.condition = 'no_result' + no_result(self = self, + condition = condition, + function = function, + skip = skip) + + def pass_test(self, condition = 1, function = None): + """Cause the test to pass. + """ + if not condition: + return + self.condition = 'pass_test' + pass_test(self = self, condition = condition, function = function) + + def preserve(self, *conditions): + """Arrange for the temporary working directories for the + specified TestCmd environment to be preserved for one or more + conditions. If no conditions are specified, arranges for + the temporary working directories to be preserved for all + conditions. + """ + if conditions is (): + conditions = ('pass_test', 'fail_test', 'no_result') + for cond in conditions: + self._preserve[cond] = 1 + + def program_set(self, program): + """Set the executable program or script to be tested. + """ + if program and not os.path.isabs(program): + program = os.path.join(self._cwd, program) + self.program = program + + def read(self, file, mode = 'rb'): + """Reads and returns the contents of the specified file name. + The file name may be a list, in which case the elements are + concatenated with the os.path.join() method. The file is + assumed to be under the temporary working directory unless it + is an absolute path name. The I/O mode for the file may + be specified; it must begin with an 'r'. The default is + 'rb' (binary read). + """ + file = self.canonicalize(file) + if mode[0] != 'r': + raise ValueError, "mode must begin with 'r'" + with open(file, mode) as f: + result = f.read() + return result + + def rmdir(self, dir): + """Removes the specified dir name. + The dir name may be a list, in which case the elements are + concatenated with the os.path.join() method. The dir is + assumed to be under the temporary working directory unless it + is an absolute path name. + The dir must be empty. + """ + dir = self.canonicalize(dir) + os.rmdir(dir) + + def start(self, program = None, + interpreter = None, + arguments = None, + universal_newlines = None, + **kw): + """ + Starts a program or script for the test environment. + + The specified program will have the original directory + prepended unless it is enclosed in a [list]. + """ + cmd = self.command_args(program, interpreter, arguments) + cmd_string = string.join(map(self.escape, cmd), ' ') + if self.verbose: + sys.stderr.write(cmd_string + "\n") + if universal_newlines is None: + universal_newlines = self.universal_newlines + + # On Windows, if we make stdin a pipe when we plan to send + # no input, and the test program exits before + # Popen calls msvcrt.open_osfhandle, that call will fail. + # So don't use a pipe for stdin if we don't need one. + stdin = kw.get('stdin', None) + if stdin is not None: + stdin = subprocess.PIPE + + combine = kw.get('combine', self.combine) + if combine: + stderr_value = subprocess.STDOUT + else: + stderr_value = subprocess.PIPE + + return Popen(cmd, + stdin=stdin, + stdout=subprocess.PIPE, + stderr=stderr_value, + universal_newlines=universal_newlines) + + def finish(self, popen, **kw): + """ + Finishes and waits for the process being run under control of + the specified popen argument, recording the exit status, + standard output and error output. + """ + popen.stdin.close() + self.status = popen.wait() + if not self.status: + self.status = 0 + self._stdout.append(popen.stdout.read()) + if popen.stderr: + stderr = popen.stderr.read() + else: + stderr = '' + self._stderr.append(stderr) + + def run(self, program = None, + interpreter = None, + arguments = None, + chdir = None, + stdin = None, + universal_newlines = None): + """Runs a test of the program or script for the test + environment. Standard output and error output are saved for + future retrieval via the stdout() and stderr() methods. + + The specified program will have the original directory + prepended unless it is enclosed in a [list]. + """ + if chdir: + oldcwd = os.getcwd() + if not os.path.isabs(chdir): + chdir = os.path.join(self.workpath(chdir)) + if self.verbose: + sys.stderr.write("chdir(" + chdir + ")\n") + os.chdir(chdir) + p = self.start(program, + interpreter, + arguments, + universal_newlines, + stdin=stdin) + if stdin: + if is_List(stdin): + for line in stdin: + p.stdin.write(line) + else: + p.stdin.write(stdin) + p.stdin.close() + + out = p.stdout.read() + if p.stderr is None: + err = '' + else: + err = p.stderr.read() + try: + close_output = p.close_output + except AttributeError: + p.stdout.close() + if not p.stderr is None: + p.stderr.close() + else: + close_output() + + self._stdout.append(out) + self._stderr.append(err) + + self.status = p.wait() + if not self.status: + self.status = 0 + + if chdir: + os.chdir(oldcwd) + if self.verbose >= 2: + write = sys.stdout.write + write('============ STATUS: %d\n' % self.status) + out = self.stdout() + if out or self.verbose >= 3: + write('============ BEGIN STDOUT (len=%d):\n' % len(out)) + write(out) + write('============ END STDOUT\n') + err = self.stderr() + if err or self.verbose >= 3: + write('============ BEGIN STDERR (len=%d)\n' % len(err)) + write(err) + write('============ END STDERR\n') + + def sleep(self, seconds = default_sleep_seconds): + """Sleeps at least the specified number of seconds. If no + number is specified, sleeps at least the minimum number of + seconds necessary to advance file time stamps on the current + system. Sleeping more seconds is all right. + """ + time.sleep(seconds) + + def stderr(self, run = None): + """Returns the error output from the specified run number. + If there is no specified run number, then returns the error + output of the last run. If the run number is less than zero, + then returns the error output from that many runs back from the + current run. + """ + if not run: + run = len(self._stderr) + elif run < 0: + run = len(self._stderr) + run + run = run - 1 + return self._stderr[run] + + def stdout(self, run = None): + """Returns the standard output from the specified run number. + If there is no specified run number, then returns the standard + output of the last run. If the run number is less than zero, + then returns the standard output from that many runs back from + the current run. + """ + if not run: + run = len(self._stdout) + elif run < 0: + run = len(self._stdout) + run + run = run - 1 + return self._stdout[run] + + def subdir(self, *subdirs): + """Create new subdirectories under the temporary working + directory, one for each argument. An argument may be a list, + in which case the list elements are concatenated using the + os.path.join() method. Subdirectories multiple levels deep + must be created using a separate argument for each level: + + test.subdir('sub', ['sub', 'dir'], ['sub', 'dir', 'ectory']) + + Returns the number of subdirectories actually created. + """ + count = 0 + for sub in subdirs: + if sub is None: + continue + if is_List(sub): + sub = apply(os.path.join, tuple(sub)) + new = os.path.join(self.workdir, sub) + try: + os.mkdir(new) + except OSError: + pass + else: + count = count + 1 + return count + + def symlink(self, target, link): + """Creates a symlink to the specified target. + The link name may be a list, in which case the elements are + concatenated with the os.path.join() method. The link is + assumed to be under the temporary working directory unless it + is an absolute path name. The target is *not* assumed to be + under the temporary working directory. + """ + link = self.canonicalize(link) + os.symlink(target, link) + + def tempdir(self, path=None): + """Creates a temporary directory. + A unique directory name is generated if no path name is specified. + The directory is created, and will be removed when the TestCmd + object is destroyed. + """ + if path is None: + try: + path = tempfile.mktemp(prefix=tempfile.template) + except TypeError: + path = tempfile.mktemp() + os.mkdir(path) + + # Symlinks in the path will report things + # differently from os.getcwd(), so chdir there + # and back to fetch the canonical path. + cwd = os.getcwd() + try: + os.chdir(path) + path = os.getcwd() + finally: + os.chdir(cwd) + + # Uppercase the drive letter since the case of drive + # letters is pretty much random on win32: + drive,rest = os.path.splitdrive(path) + if drive: + path = string.upper(drive) + rest + + # + self._dirlist.append(path) + global _Cleanup + try: + _Cleanup.index(self) + except ValueError: + _Cleanup.append(self) + + return path + + def touch(self, path, mtime=None): + """Updates the modification time on the specified file or + directory path name. The default is to update to the + current time if no explicit modification time is specified. + """ + path = self.canonicalize(path) + atime = os.path.getatime(path) + if mtime is None: + mtime = time.time() + os.utime(path, (atime, mtime)) + + def unlink(self, file): + """Unlinks the specified file name. + The file name may be a list, in which case the elements are + concatenated with the os.path.join() method. The file is + assumed to be under the temporary working directory unless it + is an absolute path name. + """ + file = self.canonicalize(file) + os.unlink(file) + + def verbose_set(self, verbose): + """Set the verbose level. + """ + self.verbose = verbose + + def where_is(self, file, path=None, pathext=None): + """Find an executable file. + """ + if is_List(file): + file = apply(os.path.join, tuple(file)) + if not os.path.isabs(file): + file = where_is(file, path, pathext) + return file + + def workdir_set(self, path): + """Creates a temporary working directory with the specified + path name. If the path is a null string (''), a unique + directory name is created. + """ + if (path != None): + if path == '': + path = None + path = self.tempdir(path) + self.workdir = path + + def workpath(self, *args): + """Returns the absolute path name to a subdirectory or file + within the current temporary working directory. Concatenates + the temporary working directory name with the specified + arguments using the os.path.join() method. + """ + return apply(os.path.join, (self.workdir,) + tuple(args)) + + def readable(self, top, read=1): + """Make the specified directory tree readable (read == 1) + or not (read == None). + + This method has no effect on Windows systems, which use a + completely different mechanism to control file readability. + """ + + if sys.platform == 'win32': + return + + if read: + def do_chmod(fname): + try: st = os.stat(fname) + except OSError: pass + else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]|stat.S_IREAD)) + else: + def do_chmod(fname): + try: st = os.stat(fname) + except OSError: pass + else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]&~stat.S_IREAD)) + + if os.path.isfile(top): + # If it's a file, that's easy, just chmod it. + do_chmod(top) + elif read: + # It's a directory and we're trying to turn on read + # permission, so it's also pretty easy, just chmod the + # directory and then chmod every entry on our walk down the + # tree. Because os.path.walk() is top-down, we'll enable + # read permission on any directories that have it disabled + # before os.path.walk() tries to list their contents. + do_chmod(top) + + def chmod_entries(arg, dirname, names, do_chmod=do_chmod): + for n in names: + do_chmod(os.path.join(dirname, n)) + + os.path.walk(top, chmod_entries, None) + else: + # It's a directory and we're trying to turn off read + # permission, which means we have to chmod the directoreis + # in the tree bottom-up, lest disabling read permission from + # the top down get in the way of being able to get at lower + # parts of the tree. But os.path.walk() visits things top + # down, so we just use an object to collect a list of all + # of the entries in the tree, reverse the list, and then + # chmod the reversed (bottom-up) list. + col = Collector(top) + os.path.walk(top, col, None) + col.entries.reverse() + for d in col.entries: do_chmod(d) + + def writable(self, top, write=1): + """Make the specified directory tree writable (write == 1) + or not (write == None). + """ + + if sys.platform == 'win32': + + if write: + def do_chmod(fname): + try: os.chmod(fname, stat.S_IWRITE) + except OSError: pass + else: + def do_chmod(fname): + try: os.chmod(fname, stat.S_IREAD) + except OSError: pass + + else: + + if write: + def do_chmod(fname): + try: st = os.stat(fname) + except OSError: pass + else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]|0200)) + else: + def do_chmod(fname): + try: st = os.stat(fname) + except OSError: pass + else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]&~0200)) + + if os.path.isfile(top): + do_chmod(top) + else: + col = Collector(top) + os.path.walk(top, col, None) + for d in col.entries: do_chmod(d) + + def executable(self, top, execute=1): + """Make the specified directory tree executable (execute == 1) + or not (execute == None). + + This method has no effect on Windows systems, which use a + completely different mechanism to control file executability. + """ + + if sys.platform == 'win32': + return + + if execute: + def do_chmod(fname): + try: st = os.stat(fname) + except OSError: pass + else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]|stat.S_IEXEC)) + else: + def do_chmod(fname): + try: st = os.stat(fname) + except OSError: pass + else: os.chmod(fname, stat.S_IMODE(st[stat.ST_MODE]&~stat.S_IEXEC)) + + if os.path.isfile(top): + # If it's a file, that's easy, just chmod it. + do_chmod(top) + elif execute: + # It's a directory and we're trying to turn on execute + # permission, so it's also pretty easy, just chmod the + # directory and then chmod every entry on our walk down the + # tree. Because os.path.walk() is top-down, we'll enable + # execute permission on any directories that have it disabled + # before os.path.walk() tries to list their contents. + do_chmod(top) + + def chmod_entries(arg, dirname, names, do_chmod=do_chmod): + for n in names: + do_chmod(os.path.join(dirname, n)) + + os.path.walk(top, chmod_entries, None) + else: + # It's a directory and we're trying to turn off execute + # permission, which means we have to chmod the directories + # in the tree bottom-up, lest disabling execute permission from + # the top down get in the way of being able to get at lower + # parts of the tree. But os.path.walk() visits things top + # down, so we just use an object to collect a list of all + # of the entries in the tree, reverse the list, and then + # chmod the reversed (bottom-up) list. + col = Collector(top) + os.path.walk(top, col, None) + col.entries.reverse() + for d in col.entries: do_chmod(d) + + def write(self, file, content, mode = 'wb'): + """Writes the specified content text (second argument) to the + specified file name (first argument). The file name may be + a list, in which case the elements are concatenated with the + os.path.join() method. The file is created under the temporary + working directory. Any subdirectories in the path must already + exist. The I/O mode for the file may be specified; it must + begin with a 'w'. The default is 'wb' (binary write). + """ + file = self.canonicalize(file) + if mode[0] != 'w': + raise ValueError, "mode must begin with 'w'" + with open(file, mode) as f: + f.write(content) + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/tools/gyp/test/lib/TestCommon.py b/tools/gyp/test/lib/TestCommon.py new file mode 100644 index 00000000000..4aa7185a2ff --- /dev/null +++ b/tools/gyp/test/lib/TestCommon.py @@ -0,0 +1,581 @@ +""" +TestCommon.py: a testing framework for commands and scripts + with commonly useful error handling + +The TestCommon module provides a simple, high-level interface for writing +tests of executable commands and scripts, especially commands and scripts +that interact with the file system. All methods throw exceptions and +exit on failure, with useful error messages. This makes a number of +explicit checks unnecessary, making the test scripts themselves simpler +to write and easier to read. + +The TestCommon class is a subclass of the TestCmd class. In essence, +TestCommon is a wrapper that handles common TestCmd error conditions in +useful ways. You can use TestCommon directly, or subclass it for your +program and add additional (or override) methods to tailor it to your +program's specific needs. Alternatively, the TestCommon class serves +as a useful example of how to define your own TestCmd subclass. + +As a subclass of TestCmd, TestCommon provides access to all of the +variables and methods from the TestCmd module. Consequently, you can +use any variable or method documented in the TestCmd module without +having to explicitly import TestCmd. + +A TestCommon environment object is created via the usual invocation: + + import TestCommon + test = TestCommon.TestCommon() + +You can use all of the TestCmd keyword arguments when instantiating a +TestCommon object; see the TestCmd documentation for details. + +Here is an overview of the methods and keyword arguments that are +provided by the TestCommon class: + + test.must_be_writable('file1', ['file2', ...]) + + test.must_contain('file', 'required text\n') + + test.must_contain_all_lines(output, lines, ['title', find]) + + test.must_contain_any_line(output, lines, ['title', find]) + + test.must_exist('file1', ['file2', ...]) + + test.must_match('file', "expected contents\n") + + test.must_not_be_writable('file1', ['file2', ...]) + + test.must_not_contain('file', 'banned text\n') + + test.must_not_contain_any_line(output, lines, ['title', find]) + + test.must_not_exist('file1', ['file2', ...]) + + test.run(options = "options to be prepended to arguments", + stdout = "expected standard output from the program", + stderr = "expected error output from the program", + status = expected_status, + match = match_function) + +The TestCommon module also provides the following variables + + TestCommon.python_executable + TestCommon.exe_suffix + TestCommon.obj_suffix + TestCommon.shobj_prefix + TestCommon.shobj_suffix + TestCommon.lib_prefix + TestCommon.lib_suffix + TestCommon.dll_prefix + TestCommon.dll_suffix + +""" + +# Copyright 2000-2010 Steven Knight +# This module is free software, and you may redistribute it and/or modify +# it under the same terms as Python itself, so long as this copyright message +# and disclaimer are retained in their original form. +# +# IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +# SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF +# THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +# DAMAGE. +# +# THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, +# AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, +# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +__author__ = "Steven Knight <knight at baldmt dot com>" +__revision__ = "TestCommon.py 0.37.D001 2010/01/11 16:55:50 knight" +__version__ = "0.37" + +import copy +import os +import os.path +import stat +import string +import sys +import types +import UserList + +from TestCmd import * +from TestCmd import __all__ + +__all__.extend([ 'TestCommon', + 'exe_suffix', + 'obj_suffix', + 'shobj_prefix', + 'shobj_suffix', + 'lib_prefix', + 'lib_suffix', + 'dll_prefix', + 'dll_suffix', + ]) + +# Variables that describe the prefixes and suffixes on this system. +if sys.platform == 'win32': + exe_suffix = '.exe' + obj_suffix = '.obj' + shobj_suffix = '.obj' + shobj_prefix = '' + lib_prefix = '' + lib_suffix = '.lib' + dll_prefix = '' + dll_suffix = '.dll' +elif sys.platform == 'cygwin': + exe_suffix = '.exe' + obj_suffix = '.o' + shobj_suffix = '.os' + shobj_prefix = '' + lib_prefix = 'lib' + lib_suffix = '.a' + dll_prefix = '' + dll_suffix = '.dll' +elif string.find(sys.platform, 'irix') != -1: + exe_suffix = '' + obj_suffix = '.o' + shobj_suffix = '.o' + shobj_prefix = '' + lib_prefix = 'lib' + lib_suffix = '.a' + dll_prefix = 'lib' + dll_suffix = '.so' +elif string.find(sys.platform, 'darwin') != -1: + exe_suffix = '' + obj_suffix = '.o' + shobj_suffix = '.os' + shobj_prefix = '' + lib_prefix = 'lib' + lib_suffix = '.a' + dll_prefix = 'lib' + dll_suffix = '.dylib' +elif string.find(sys.platform, 'sunos') != -1: + exe_suffix = '' + obj_suffix = '.o' + shobj_suffix = '.os' + shobj_prefix = 'so_' + lib_prefix = 'lib' + lib_suffix = '.a' + dll_prefix = 'lib' + dll_suffix = '.dylib' +else: + exe_suffix = '' + obj_suffix = '.o' + shobj_suffix = '.os' + shobj_prefix = '' + lib_prefix = 'lib' + lib_suffix = '.a' + dll_prefix = 'lib' + dll_suffix = '.so' + +def is_List(e): + return type(e) is types.ListType \ + or isinstance(e, UserList.UserList) + +def is_writable(f): + mode = os.stat(f)[stat.ST_MODE] + return mode & stat.S_IWUSR + +def separate_files(flist): + existing = [] + missing = [] + for f in flist: + if os.path.exists(f): + existing.append(f) + else: + missing.append(f) + return existing, missing + +if os.name == 'posix': + def _failed(self, status = 0): + if self.status is None or status is None: + return None + return _status(self) != status + def _status(self): + return self.status +elif os.name == 'nt': + def _failed(self, status = 0): + return not (self.status is None or status is None) and \ + self.status != status + def _status(self): + return self.status + +class TestCommon(TestCmd): + + # Additional methods from the Perl Test::Cmd::Common module + # that we may wish to add in the future: + # + # $test->subdir('subdir', ...); + # + # $test->copy('src_file', 'dst_file'); + + def __init__(self, **kw): + """Initialize a new TestCommon instance. This involves just + calling the base class initialization, and then changing directory + to the workdir. + """ + apply(TestCmd.__init__, [self], kw) + os.chdir(self.workdir) + + def must_be_writable(self, *files): + """Ensures that the specified file(s) exist and are writable. + An individual file can be specified as a list of directory names, + in which case the pathname will be constructed by concatenating + them. Exits FAILED if any of the files does not exist or is + not writable. + """ + files = map(lambda x: is_List(x) and apply(os.path.join, x) or x, files) + existing, missing = separate_files(files) + unwritable = filter(lambda x, iw=is_writable: not iw(x), existing) + if missing: + print "Missing files: `%s'" % string.join(missing, "', `") + if unwritable: + print "Unwritable files: `%s'" % string.join(unwritable, "', `") + self.fail_test(missing + unwritable) + + def must_contain(self, file, required, mode = 'rb'): + """Ensures that the specified file contains the required text. + """ + file_contents = self.read(file, mode) + contains = (string.find(file_contents, required) != -1) + if not contains: + print "File `%s' does not contain required string." % file + print self.banner('Required string ') + print required + print self.banner('%s contents ' % file) + print file_contents + self.fail_test(not contains) + + def must_contain_all_lines(self, output, lines, title=None, find=None): + """Ensures that the specified output string (first argument) + contains all of the specified lines (second argument). + + An optional third argument can be used to describe the type + of output being searched, and only shows up in failure output. + + An optional fourth argument can be used to supply a different + function, of the form "find(line, output), to use when searching + for lines in the output. + """ + if find is None: + find = lambda o, l: string.find(o, l) != -1 + missing = [] + for line in lines: + if not find(output, line): + missing.append(line) + + if missing: + if title is None: + title = 'output' + sys.stdout.write("Missing expected lines from %s:\n" % title) + for line in missing: + sys.stdout.write(' ' + repr(line) + '\n') + sys.stdout.write(self.banner(title + ' ')) + sys.stdout.write(output) + self.fail_test() + + def must_contain_any_line(self, output, lines, title=None, find=None): + """Ensures that the specified output string (first argument) + contains at least one of the specified lines (second argument). + + An optional third argument can be used to describe the type + of output being searched, and only shows up in failure output. + + An optional fourth argument can be used to supply a different + function, of the form "find(line, output), to use when searching + for lines in the output. + """ + if find is None: + find = lambda o, l: string.find(o, l) != -1 + for line in lines: + if find(output, line): + return + + if title is None: + title = 'output' + sys.stdout.write("Missing any expected line from %s:\n" % title) + for line in lines: + sys.stdout.write(' ' + repr(line) + '\n') + sys.stdout.write(self.banner(title + ' ')) + sys.stdout.write(output) + self.fail_test() + + def must_contain_lines(self, lines, output, title=None): + # Deprecated; retain for backwards compatibility. + return self.must_contain_all_lines(output, lines, title) + + def must_exist(self, *files): + """Ensures that the specified file(s) must exist. An individual + file be specified as a list of directory names, in which case the + pathname will be constructed by concatenating them. Exits FAILED + if any of the files does not exist. + """ + files = map(lambda x: is_List(x) and apply(os.path.join, x) or x, files) + missing = filter(lambda x: not os.path.exists(x), files) + if missing: + print "Missing files: `%s'" % string.join(missing, "', `") + self.fail_test(missing) + + def must_match(self, file, expect, mode = 'rb'): + """Matches the contents of the specified file (first argument) + against the expected contents (second argument). The expected + contents are a list of lines or a string which will be split + on newlines. + """ + file_contents = self.read(file, mode) + try: + self.fail_test(not self.match(file_contents, expect)) + except KeyboardInterrupt: + raise + except: + print "Unexpected contents of `%s'" % file + self.diff(expect, file_contents, 'contents ') + raise + + def must_not_contain(self, file, banned, mode = 'rb'): + """Ensures that the specified file doesn't contain the banned text. + """ + file_contents = self.read(file, mode) + contains = (string.find(file_contents, banned) != -1) + if contains: + print "File `%s' contains banned string." % file + print self.banner('Banned string ') + print banned + print self.banner('%s contents ' % file) + print file_contents + self.fail_test(contains) + + def must_not_contain_any_line(self, output, lines, title=None, find=None): + """Ensures that the specified output string (first argument) + does not contain any of the specified lines (second argument). + + An optional third argument can be used to describe the type + of output being searched, and only shows up in failure output. + + An optional fourth argument can be used to supply a different + function, of the form "find(line, output), to use when searching + for lines in the output. + """ + if find is None: + find = lambda o, l: string.find(o, l) != -1 + unexpected = [] + for line in lines: + if find(output, line): + unexpected.append(line) + + if unexpected: + if title is None: + title = 'output' + sys.stdout.write("Unexpected lines in %s:\n" % title) + for line in unexpected: + sys.stdout.write(' ' + repr(line) + '\n') + sys.stdout.write(self.banner(title + ' ')) + sys.stdout.write(output) + self.fail_test() + + def must_not_contain_lines(self, lines, output, title=None): + return self.must_not_contain_any_line(output, lines, title) + + def must_not_exist(self, *files): + """Ensures that the specified file(s) must not exist. + An individual file be specified as a list of directory names, in + which case the pathname will be constructed by concatenating them. + Exits FAILED if any of the files exists. + """ + files = map(lambda x: is_List(x) and apply(os.path.join, x) or x, files) + existing = filter(os.path.exists, files) + if existing: + print "Unexpected files exist: `%s'" % string.join(existing, "', `") + self.fail_test(existing) + + + def must_not_be_writable(self, *files): + """Ensures that the specified file(s) exist and are not writable. + An individual file can be specified as a list of directory names, + in which case the pathname will be constructed by concatenating + them. Exits FAILED if any of the files does not exist or is + writable. + """ + files = map(lambda x: is_List(x) and apply(os.path.join, x) or x, files) + existing, missing = separate_files(files) + writable = filter(is_writable, existing) + if missing: + print "Missing files: `%s'" % string.join(missing, "', `") + if writable: + print "Writable files: `%s'" % string.join(writable, "', `") + self.fail_test(missing + writable) + + def _complete(self, actual_stdout, expected_stdout, + actual_stderr, expected_stderr, status, match): + """ + Post-processes running a subcommand, checking for failure + status and displaying output appropriately. + """ + if _failed(self, status): + expect = '' + if status != 0: + expect = " (expected %s)" % str(status) + print "%s returned %s%s" % (self.program, str(_status(self)), expect) + print self.banner('STDOUT ') + print actual_stdout + print self.banner('STDERR ') + print actual_stderr + self.fail_test() + if not expected_stdout is None and not match(actual_stdout, expected_stdout): + self.diff(expected_stdout, actual_stdout, 'STDOUT ') + if actual_stderr: + print self.banner('STDERR ') + print actual_stderr + self.fail_test() + if not expected_stderr is None and not match(actual_stderr, expected_stderr): + print self.banner('STDOUT ') + print actual_stdout + self.diff(expected_stderr, actual_stderr, 'STDERR ') + self.fail_test() + + def start(self, program = None, + interpreter = None, + arguments = None, + universal_newlines = None, + **kw): + """ + Starts a program or script for the test environment. + + This handles the "options" keyword argument and exceptions. + """ + try: + options = kw['options'] + del kw['options'] + except KeyError: + pass + else: + if options: + if arguments is None: + arguments = options + else: + arguments = options + " " + arguments + try: + return apply(TestCmd.start, + (self, program, interpreter, arguments, universal_newlines), + kw) + except KeyboardInterrupt: + raise + except Exception, e: + print self.banner('STDOUT ') + try: + print self.stdout() + except IndexError: + pass + print self.banner('STDERR ') + try: + print self.stderr() + except IndexError: + pass + cmd_args = self.command_args(program, interpreter, arguments) + sys.stderr.write('Exception trying to execute: %s\n' % cmd_args) + raise e + + def finish(self, popen, stdout = None, stderr = '', status = 0, **kw): + """ + Finishes and waits for the process being run under control of + the specified popen argument. Additional arguments are similar + to those of the run() method: + + stdout The expected standard output from + the command. A value of None means + don't test standard output. + + stderr The expected error output from + the command. A value of None means + don't test error output. + + status The expected exit status from the + command. A value of None means don't + test exit status. + """ + apply(TestCmd.finish, (self, popen,), kw) + match = kw.get('match', self.match) + self._complete(self.stdout(), stdout, + self.stderr(), stderr, status, match) + + def run(self, options = None, arguments = None, + stdout = None, stderr = '', status = 0, **kw): + """Runs the program under test, checking that the test succeeded. + + The arguments are the same as the base TestCmd.run() method, + with the addition of: + + options Extra options that get appended to the beginning + of the arguments. + + stdout The expected standard output from + the command. A value of None means + don't test standard output. + + stderr The expected error output from + the command. A value of None means + don't test error output. + + status The expected exit status from the + command. A value of None means don't + test exit status. + + By default, this expects a successful exit (status = 0), does + not test standard output (stdout = None), and expects that error + output is empty (stderr = ""). + """ + if options: + if arguments is None: + arguments = options + else: + arguments = options + " " + arguments + kw['arguments'] = arguments + try: + match = kw['match'] + del kw['match'] + except KeyError: + match = self.match + apply(TestCmd.run, [self], kw) + self._complete(self.stdout(), stdout, + self.stderr(), stderr, status, match) + + def skip_test(self, message="Skipping test.\n"): + """Skips a test. + + Proper test-skipping behavior is dependent on the external + TESTCOMMON_PASS_SKIPS environment variable. If set, we treat + the skip as a PASS (exit 0), and otherwise treat it as NO RESULT. + In either case, we print the specified message as an indication + that the substance of the test was skipped. + + (This was originally added to support development under Aegis. + Technically, skipping a test is a NO RESULT, but Aegis would + treat that as a test failure and prevent the change from going to + the next step. Since we ddn't want to force anyone using Aegis + to have to install absolutely every tool used by the tests, we + would actually report to Aegis that a skipped test has PASSED + so that the workflow isn't held up.) + """ + if message: + sys.stdout.write(message) + sys.stdout.flush() + pass_skips = os.environ.get('TESTCOMMON_PASS_SKIPS') + if pass_skips in [None, 0, '0']: + # skip=1 means skip this function when showing where this + # result came from. They only care about the line where the + # script called test.skip_test(), not the line number where + # we call test.no_result(). + self.no_result(skip=1) + else: + # We're under the development directory for this change, + # so this is an Aegis invocation; pass the test (exit 0). + self.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/tools/gyp/test/lib/TestGyp.py b/tools/gyp/test/lib/TestGyp.py new file mode 100644 index 00000000000..a65c3e24404 --- /dev/null +++ b/tools/gyp/test/lib/TestGyp.py @@ -0,0 +1,806 @@ +# 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. + +""" +TestGyp.py: a testing framework for GYP integration tests. +""" + +import os +import re +import shutil +import stat +import sys +import tempfile + +import TestCommon +from TestCommon import __all__ + +__all__.extend([ + 'TestGyp', +]) + + +class TestGypBase(TestCommon.TestCommon): + """ + Class for controlling end-to-end tests of gyp generators. + + Instantiating this class will create a temporary directory and + arrange for its destruction (via the TestCmd superclass) and + copy all of the non-gyptest files in the directory hierarchy of the + executing script. + + The default behavior is to test the 'gyp' or 'gyp.bat' file in the + current directory. An alternative may be specified explicitly on + instantiation, or by setting the TESTGYP_GYP environment variable. + + This class should be subclassed for each supported gyp generator + (format). Various abstract methods below define calling signatures + used by the test scripts to invoke builds on the generated build + configuration and to run executables generated by those builds. + """ + + build_tool = None + build_tool_list = [] + + _exe = TestCommon.exe_suffix + _obj = TestCommon.obj_suffix + shobj_ = TestCommon.shobj_prefix + _shobj = TestCommon.shobj_suffix + lib_ = TestCommon.lib_prefix + _lib = TestCommon.lib_suffix + dll_ = TestCommon.dll_prefix + _dll = TestCommon.dll_suffix + + # Constants to represent different targets. + ALL = '__all__' + DEFAULT = '__default__' + + # Constants for different target types. + EXECUTABLE = '__executable__' + STATIC_LIB = '__static_lib__' + SHARED_LIB = '__shared_lib__' + + def __init__(self, gyp=None, *args, **kw): + self.origin_cwd = os.path.abspath(os.path.dirname(sys.argv[0])) + + if not gyp: + gyp = os.environ.get('TESTGYP_GYP') + if not gyp: + if sys.platform == 'win32': + gyp = 'gyp.bat' + else: + gyp = 'gyp' + self.gyp = os.path.abspath(gyp) + + self.initialize_build_tool() + + if not kw.has_key('match'): + kw['match'] = TestCommon.match_exact + + # Put test output in out/testworkarea by default. + # Use temporary names so there are no collisions. + workdir = os.path.join('out', kw.get('workdir', 'testworkarea')) + # Create work area if it doesn't already exist. + try: + os.makedirs(workdir) + except OSError: + pass + kw['workdir'] = tempfile.mktemp(prefix='testgyp.', dir=workdir) + + formats = kw.get('formats', []) + if kw.has_key('formats'): + del kw['formats'] + + super(TestGypBase, self).__init__(*args, **kw) + + excluded_formats = set([f for f in formats if f[0] == '!']) + included_formats = set(formats) - excluded_formats + if ('!'+self.format in excluded_formats or + included_formats and self.format not in included_formats): + msg = 'Invalid test for %r format; skipping test.\n' + self.skip_test(msg % self.format) + + self.copy_test_configuration(self.origin_cwd, self.workdir) + self.set_configuration(None) + + # Set $HOME so that gyp doesn't read the user's actual + # ~/.gyp/include.gypi file, which may contain variables + # and other settings that would change the output. + os.environ['HOME'] = self.workpath() + # Clear $GYP_DEFINES for the same reason. + if 'GYP_DEFINES' in os.environ: + del os.environ['GYP_DEFINES'] + + def built_file_must_exist(self, name, type=None, **kw): + """ + Fails the test if the specified built file name does not exist. + """ + return self.must_exist(self.built_file_path(name, type, **kw)) + + def built_file_must_not_exist(self, name, type=None, **kw): + """ + Fails the test if the specified built file name exists. + """ + return self.must_not_exist(self.built_file_path(name, type, **kw)) + + def built_file_must_match(self, name, contents, **kw): + """ + Fails the test if the contents of the specified built file name + do not match the specified contents. + """ + return self.must_match(self.built_file_path(name, **kw), contents) + + def built_file_must_not_match(self, name, contents, **kw): + """ + Fails the test if the contents of the specified built file name + match the specified contents. + """ + return self.must_not_match(self.built_file_path(name, **kw), contents) + + def copy_test_configuration(self, source_dir, dest_dir): + """ + Copies the test configuration from the specified source_dir + (the directory in which the test script lives) to the + specified dest_dir (a temporary working directory). + + This ignores all files and directories that begin with + the string 'gyptest', and all '.svn' subdirectories. + """ + for root, dirs, files in os.walk(source_dir): + if '.svn' in dirs: + dirs.remove('.svn') + dirs = [ d for d in dirs if not d.startswith('gyptest') ] + files = [ f for f in files if not f.startswith('gyptest') ] + for dirname in dirs: + source = os.path.join(root, dirname) + destination = source.replace(source_dir, dest_dir) + os.mkdir(destination) + if sys.platform != 'win32': + shutil.copystat(source, destination) + for filename in files: + source = os.path.join(root, filename) + destination = source.replace(source_dir, dest_dir) + shutil.copy2(source, destination) + + def initialize_build_tool(self): + """ + Initializes the .build_tool attribute. + + Searches the .build_tool_list for an executable name on the user's + $PATH. The first tool on the list is used as-is if nothing is found + on the current $PATH. + """ + for build_tool in self.build_tool_list: + if not build_tool: + continue + if os.path.isabs(build_tool): + self.build_tool = build_tool + return + build_tool = self.where_is(build_tool) + if build_tool: + self.build_tool = build_tool + return + + if self.build_tool_list: + self.build_tool = self.build_tool_list[0] + + def relocate(self, source, destination): + """ + Renames (relocates) the specified source (usually a directory) + to the specified destination, creating the destination directory + first if necessary. + + Note: Don't use this as a generic "rename" operation. In the + future, "relocating" parts of a GYP tree may affect the state of + the test to modify the behavior of later method calls. + """ + destination_dir = os.path.dirname(destination) + if not os.path.exists(destination_dir): + self.subdir(destination_dir) + os.rename(source, destination) + + def report_not_up_to_date(self): + """ + Reports that a build is not up-to-date. + + This provides common reporting for formats that have complicated + conditions for checking whether a build is up-to-date. Formats + that expect exact output from the command (make, scons) can + just set stdout= when they call the run_build() method. + """ + print "Build is not up-to-date:" + print self.banner('STDOUT ') + print self.stdout() + stderr = self.stderr() + if stderr: + print self.banner('STDERR ') + print stderr + + def run_gyp(self, gyp_file, *args, **kw): + """ + Runs gyp against the specified gyp_file with the specified args. + """ + # TODO: --depth=. works around Chromium-specific tree climbing. + args = ('--depth=.', '--format='+self.format, gyp_file) + args + return self.run(program=self.gyp, arguments=args, **kw) + + def run(self, *args, **kw): + """ + Executes a program by calling the superclass .run() method. + + This exists to provide a common place to filter out keyword + arguments implemented in this layer, without having to update + the tool-specific subclasses or clutter the tests themselves + with platform-specific code. + """ + if kw.has_key('SYMROOT'): + del kw['SYMROOT'] + super(TestGypBase, self).run(*args, **kw) + + def set_configuration(self, configuration): + """ + Sets the configuration, to be used for invoking the build + tool and testing potential built output. + """ + self.configuration = configuration + + def configuration_dirname(self): + if self.configuration: + return self.configuration.split('|')[0] + else: + return 'Default' + + def configuration_buildname(self): + if self.configuration: + return self.configuration + else: + return 'Default' + + # + # Abstract methods to be defined by format-specific subclasses. + # + + def build(self, gyp_file, target=None, **kw): + """ + Runs a build of the specified target against the configuration + generated from the specified gyp_file. + + A 'target' argument of None or the special value TestGyp.DEFAULT + specifies the default argument for the underlying build tool. + A 'target' argument of TestGyp.ALL specifies the 'all' target + (if any) of the underlying build tool. + """ + raise NotImplementedError + + def built_file_path(self, name, type=None, **kw): + """ + Returns a path to the specified file name, of the specified type. + """ + raise NotImplementedError + + def built_file_basename(self, name, type=None, **kw): + """ + Returns the base name of the specified file name, of the specified type. + + A bare=True keyword argument specifies that prefixes and suffixes shouldn't + be applied. + """ + if not kw.get('bare'): + if type == self.EXECUTABLE: + name = name + self._exe + elif type == self.STATIC_LIB: + name = self.lib_ + name + self._lib + elif type == self.SHARED_LIB: + name = self.dll_ + name + self._dll + return name + + def run_built_executable(self, name, *args, **kw): + """ + Runs an executable program built from a gyp-generated configuration. + + The specified name should be independent of any particular generator. + Subclasses should find the output executable in the appropriate + output build directory, tack on any necessary executable suffix, etc. + """ + raise NotImplementedError + + def up_to_date(self, gyp_file, target=None, **kw): + """ + Verifies that a build of the specified target is up to date. + + The subclass should implement this by calling build() + (or a reasonable equivalent), checking whatever conditions + will tell it the build was an "up to date" null build, and + failing if it isn't. + """ + raise NotImplementedError + + +class TestGypGypd(TestGypBase): + """ + Subclass for testing the GYP 'gypd' generator (spit out the + internal data structure as pretty-printed Python). + """ + format = 'gypd' + + +class TestGypMake(TestGypBase): + """ + Subclass for testing the GYP Make generator. + """ + format = 'make' + build_tool_list = ['make'] + ALL = 'all' + def build(self, gyp_file, target=None, **kw): + """ + Runs a Make build using the Makefiles generated from the specified + gyp_file. + """ + arguments = kw.get('arguments', [])[:] + if self.configuration: + arguments.append('BUILDTYPE=' + self.configuration) + if target not in (None, self.DEFAULT): + arguments.append(target) + # Sub-directory builds provide per-gyp Makefiles (i.e. + # Makefile.gyp_filename), so use that if there is no Makefile. + chdir = kw.get('chdir', '') + if not os.path.exists(os.path.join(chdir, 'Makefile')): + print "NO Makefile in " + os.path.join(chdir, 'Makefile') + arguments.insert(0, '-f') + arguments.insert(1, os.path.splitext(gyp_file)[0] + '.Makefile') + kw['arguments'] = arguments + return self.run(program=self.build_tool, **kw) + def up_to_date(self, gyp_file, target=None, **kw): + """ + Verifies that a build of the specified Make target is up to date. + """ + if target in (None, self.DEFAULT): + message_target = 'all' + else: + message_target = target + kw['stdout'] = "make: Nothing to be done for `%s'.\n" % message_target + return self.build(gyp_file, target, **kw) + def run_built_executable(self, name, *args, **kw): + """ + Runs an executable built by Make. + """ + configuration = self.configuration_dirname() + libdir = os.path.join('out', configuration, 'lib') + # TODO(piman): when everything is cross-compile safe, remove lib.target + os.environ['LD_LIBRARY_PATH'] = libdir + '.host:' + libdir + '.target' + # Enclosing the name in a list avoids prepending the original dir. + program = [self.built_file_path(name, type=self.EXECUTABLE, **kw)] + return self.run(program=program, *args, **kw) + def built_file_path(self, name, type=None, **kw): + """ + Returns a path to the specified file name, of the specified type, + as built by Make. + + Built files are in the subdirectory 'out/{configuration}'. + The default is 'out/Default'. + + A chdir= keyword argument specifies the source directory + relative to which the output subdirectory can be found. + + "type" values of STATIC_LIB or SHARED_LIB append the necessary + prefixes and suffixes to a platform-independent library base name. + + A subdir= keyword argument specifies a library subdirectory within + the default 'obj.target'. + """ + result = [] + chdir = kw.get('chdir') + if chdir: + result.append(chdir) + configuration = self.configuration_dirname() + result.extend(['out', configuration]) + if type == self.STATIC_LIB and sys.platform != 'darwin': + result.append('obj.target') + elif type == self.SHARED_LIB and sys.platform != 'darwin': + result.append('lib.target') + subdir = kw.get('subdir') + if subdir: + result.append(subdir) + result.append(self.built_file_basename(name, type, **kw)) + return self.workpath(*result) + + +class TestGypNinja(TestGypBase): + """ + Subclass for testing the GYP Ninja generator. + """ + format = 'ninja' + build_tool_list = ['ninja'] + ALL = 'all' + DEFAULT = 'all' + + # The default library prefix is computed from TestCommon.lib_prefix, + # but ninja uses no prefix for static libraries. + lib_ = '' + + def run_gyp(self, gyp_file, *args, **kw): + # We must pass the desired configuration as a parameter. + if self.configuration: + args = list(args) + ['-Gconfig=' + self.configuration] + # Stash the gyp configuration we used to run gyp, so we can + # know whether we need to rerun it later. + self.last_gyp_configuration = self.configuration + TestGypBase.run_gyp(self, gyp_file, *args, **kw) + + def build(self, gyp_file, target=None, **kw): + if self.last_gyp_configuration != self.configuration: + # Rerun gyp if necessary. + self.run_gyp(gyp_file) + + arguments = kw.get('arguments', [])[:] + + # Add a -C output/path to the command line. + arguments.append('-C') + arguments.append(os.path.join('out', self.configuration_dirname())) + + if target is None: + target = 'all' + arguments.append(target) + + kw['arguments'] = arguments + return self.run(program=self.build_tool, **kw) + + def run_built_executable(self, name, *args, **kw): + # Enclosing the name in a list avoids prepending the original dir. + program = [self.built_file_path(name, type=self.EXECUTABLE, **kw)] + return self.run(program=program, *args, **kw) + + def built_file_path(self, name, type=None, **kw): + result = [] + chdir = kw.get('chdir') + if chdir: + result.append(chdir) + result.append('out') + result.append(self.configuration_dirname()) + if type in (self.STATIC_LIB,): + result.append('obj') + elif type in (self.SHARED_LIB,): + result.append('lib') + subdir = kw.get('subdir') + if subdir: + result.append(subdir) + result.append(self.built_file_basename(name, type, **kw)) + return self.workpath(*result) + + def up_to_date(self, gyp_file, target=None, **kw): + kw['stdout'] = "ninja: no work to do.\n" + return self.build(gyp_file, target, **kw) + + +class TestGypMSVS(TestGypBase): + """ + Subclass for testing the GYP Visual Studio generator. + """ + format = 'msvs' + + u = r'=== Build: 0 succeeded, 0 failed, (\d+) up-to-date, 0 skipped ===' + up_to_date_re = re.compile(u, re.M) + + # Initial None element will indicate to our .initialize_build_tool() + # method below that 'devenv' was not found on %PATH%. + # + # Note: we must use devenv.com to be able to capture build output. + # Directly executing devenv.exe only sends output to BuildLog.htm. + build_tool_list = [None, 'devenv.com'] + + def initialize_build_tool(self): + """ Initializes the Visual Studio .build_tool and .uses_msbuild parameters. + + We use the value specified by GYP_MSVS_VERSION. If not specified, we + search %PATH% and %PATHEXT% for a devenv.{exe,bat,...} executable. + Failing that, we search for likely deployment paths. + """ + super(TestGypMSVS, self).initialize_build_tool() + possible_roots = ['C:\\Program Files (x86)', 'C:\\Program Files', + 'E:\\Program Files (x86)', 'E:\\Program Files'] + possible_paths = { + '2010': r'Microsoft Visual Studio 10.0\Common7\IDE\devenv.com', + '2008': r'Microsoft Visual Studio 9.0\Common7\IDE\devenv.com', + '2005': r'Microsoft Visual Studio 8\Common7\IDE\devenv.com'} + msvs_version = os.environ.get('GYP_MSVS_VERSION', 'auto') + if msvs_version in possible_paths: + # Check that the path to the specified GYP_MSVS_VERSION exists. + path = possible_paths[msvs_version] + for r in possible_roots: + bt = os.path.join(r, path) + if os.path.exists(bt): + self.build_tool = bt + self.uses_msbuild = msvs_version >= '2010' + return + else: + print ('Warning: Environment variable GYP_MSVS_VERSION specifies "%s" ' + 'but corresponding "%s" was not found.' % (msvs_version, path)) + if self.build_tool: + # We found 'devenv' on the path, use that and try to guess the version. + for version, path in possible_paths.iteritems(): + if self.build_tool.find(path) >= 0: + self.uses_msbuild = version >= '2010' + return + else: + # If not, assume not MSBuild. + self.uses_msbuild = False + return + # Neither GYP_MSVS_VERSION nor the path help us out. Iterate through + # the choices looking for a match. + for version, path in possible_paths.iteritems(): + for r in possible_roots: + bt = os.path.join(r, path) + if os.path.exists(bt): + self.build_tool = bt + self.uses_msbuild = msvs_version >= '2010' + return + print 'Error: could not find devenv' + sys.exit(1) + def build(self, gyp_file, target=None, rebuild=False, **kw): + """ + Runs a Visual Studio build using the configuration generated + from the specified gyp_file. + """ + configuration = self.configuration_buildname() + if rebuild: + build = '/Rebuild' + else: + build = '/Build' + arguments = kw.get('arguments', [])[:] + arguments.extend([gyp_file.replace('.gyp', '.sln'), + build, configuration]) + # Note: the Visual Studio generator doesn't add an explicit 'all' + # target, so we just treat it the same as the default. + if target not in (None, self.ALL, self.DEFAULT): + arguments.extend(['/Project', target]) + if self.configuration: + arguments.extend(['/ProjectConfig', self.configuration]) + kw['arguments'] = arguments + return self.run(program=self.build_tool, **kw) + def up_to_date(self, gyp_file, target=None, **kw): + """ + Verifies that a build of the specified Visual Studio target is up to date. + + Beware that VS2010 will behave strangely if you build under + C:\USERS\yourname\AppData\Local. It will cause needless work. The ouptut + will be "1 succeeded and 0 up to date". MSBuild tracing reveals that: + "Project 'C:\Users\...\AppData\Local\...vcxproj' not up to date because + 'C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO 10.0\VC\BIN\1033\CLUI.DLL' + was modified at 02/21/2011 17:03:30, which is newer than '' which was + modified at 01/01/0001 00:00:00. + + The workaround is to specify a workdir when instantiating the test, e.g. + test = TestGyp.TestGyp(workdir='workarea') + """ + result = self.build(gyp_file, target, **kw) + if not result: + stdout = self.stdout() + + m = self.up_to_date_re.search(stdout) + up_to_date = m and m.group(1) == '1' + if not up_to_date: + self.report_not_up_to_date() + self.fail_test() + return result + def run_built_executable(self, name, *args, **kw): + """ + Runs an executable built by Visual Studio. + """ + configuration = self.configuration_dirname() + # Enclosing the name in a list avoids prepending the original dir. + program = [self.built_file_path(name, type=self.EXECUTABLE, **kw)] + return self.run(program=program, *args, **kw) + def built_file_path(self, name, type=None, **kw): + """ + Returns a path to the specified file name, of the specified type, + as built by Visual Studio. + + Built files are in a subdirectory that matches the configuration + name. The default is 'Default'. + + A chdir= keyword argument specifies the source directory + relative to which the output subdirectory can be found. + + "type" values of STATIC_LIB or SHARED_LIB append the necessary + prefixes and suffixes to a platform-independent library base name. + """ + result = [] + chdir = kw.get('chdir') + if chdir: + result.append(chdir) + result.append(self.configuration_dirname()) + if type == self.STATIC_LIB: + result.append('lib') + result.append(self.built_file_basename(name, type, **kw)) + return self.workpath(*result) + + +class TestGypSCons(TestGypBase): + """ + Subclass for testing the GYP SCons generator. + """ + format = 'scons' + build_tool_list = ['scons', 'scons.py'] + ALL = 'all' + def build(self, gyp_file, target=None, **kw): + """ + Runs a scons build using the SCons configuration generated from the + specified gyp_file. + """ + arguments = kw.get('arguments', [])[:] + dirname = os.path.dirname(gyp_file) + if dirname: + arguments.extend(['-C', dirname]) + if self.configuration: + arguments.append('--mode=' + self.configuration) + if target not in (None, self.DEFAULT): + arguments.append(target) + kw['arguments'] = arguments + return self.run(program=self.build_tool, **kw) + def up_to_date(self, gyp_file, target=None, **kw): + """ + Verifies that a build of the specified SCons target is up to date. + """ + if target in (None, self.DEFAULT): + up_to_date_targets = 'all' + else: + up_to_date_targets = target + up_to_date_lines = [] + for arg in up_to_date_targets.split(): + up_to_date_lines.append("scons: `%s' is up to date.\n" % arg) + kw['stdout'] = ''.join(up_to_date_lines) + arguments = kw.get('arguments', [])[:] + arguments.append('-Q') + kw['arguments'] = arguments + return self.build(gyp_file, target, **kw) + def run_built_executable(self, name, *args, **kw): + """ + Runs an executable built by scons. + """ + configuration = self.configuration_dirname() + os.environ['LD_LIBRARY_PATH'] = os.path.join(configuration, 'lib') + # Enclosing the name in a list avoids prepending the original dir. + program = [self.built_file_path(name, type=self.EXECUTABLE, **kw)] + return self.run(program=program, *args, **kw) + def built_file_path(self, name, type=None, **kw): + """ + Returns a path to the specified file name, of the specified type, + as built by Scons. + + Built files are in a subdirectory that matches the configuration + name. The default is 'Default'. + + A chdir= keyword argument specifies the source directory + relative to which the output subdirectory can be found. + + "type" values of STATIC_LIB or SHARED_LIB append the necessary + prefixes and suffixes to a platform-independent library base name. + """ + result = [] + chdir = kw.get('chdir') + if chdir: + result.append(chdir) + result.append(self.configuration_dirname()) + if type in (self.STATIC_LIB, self.SHARED_LIB): + result.append('lib') + result.append(self.built_file_basename(name, type, **kw)) + return self.workpath(*result) + + +class TestGypXcode(TestGypBase): + """ + Subclass for testing the GYP Xcode generator. + """ + format = 'xcode' + build_tool_list = ['xcodebuild'] + + phase_script_execution = ("\n" + "PhaseScriptExecution /\\S+/Script-[0-9A-F]+\\.sh\n" + " cd /\\S+\n" + " /bin/sh -c /\\S+/Script-[0-9A-F]+\\.sh\n" + "(make: Nothing to be done for `all'\\.\n)?") + + strip_up_to_date_expressions = [ + # Various actions or rules can run even when the overall build target + # is up to date. Strip those phases' GYP-generated output. + re.compile(phase_script_execution, re.S), + + # The message from distcc_pump can trail the "BUILD SUCCEEDED" + # message, so strip that, too. + re.compile('__________Shutting down distcc-pump include server\n', re.S), + ] + + up_to_date_endings = ( + 'Checking Dependencies...\n** BUILD SUCCEEDED **\n', # Xcode 3.0/3.1 + 'Check dependencies\n** BUILD SUCCEEDED **\n\n', # Xcode 3.2 + ) + + def build(self, gyp_file, target=None, **kw): + """ + Runs an xcodebuild using the .xcodeproj generated from the specified + gyp_file. + """ + # Be sure we're working with a copy of 'arguments' since we modify it. + # The caller may not be expecting it to be modified. + arguments = kw.get('arguments', [])[:] + arguments.extend(['-project', gyp_file.replace('.gyp', '.xcodeproj')]) + if target == self.ALL: + arguments.append('-alltargets',) + elif target not in (None, self.DEFAULT): + arguments.extend(['-target', target]) + if self.configuration: + arguments.extend(['-configuration', self.configuration]) + symroot = kw.get('SYMROOT', '$SRCROOT/build') + if symroot: + arguments.append('SYMROOT='+symroot) + kw['arguments'] = arguments + return self.run(program=self.build_tool, **kw) + def up_to_date(self, gyp_file, target=None, **kw): + """ + Verifies that a build of the specified Xcode target is up to date. + """ + result = self.build(gyp_file, target, **kw) + if not result: + output = self.stdout() + for expression in self.strip_up_to_date_expressions: + output = expression.sub('', output) + if not output.endswith(self.up_to_date_endings): + self.report_not_up_to_date() + self.fail_test() + return result + def run_built_executable(self, name, *args, **kw): + """ + Runs an executable built by xcodebuild. + """ + configuration = self.configuration_dirname() + os.environ['DYLD_LIBRARY_PATH'] = os.path.join('build', configuration) + # Enclosing the name in a list avoids prepending the original dir. + program = [self.built_file_path(name, type=self.EXECUTABLE, **kw)] + return self.run(program=program, *args, **kw) + def built_file_path(self, name, type=None, **kw): + """ + Returns a path to the specified file name, of the specified type, + as built by Xcode. + + Built files are in the subdirectory 'build/{configuration}'. + The default is 'build/Default'. + + A chdir= keyword argument specifies the source directory + relative to which the output subdirectory can be found. + + "type" values of STATIC_LIB or SHARED_LIB append the necessary + prefixes and suffixes to a platform-independent library base name. + """ + result = [] + chdir = kw.get('chdir') + if chdir: + result.append(chdir) + configuration = self.configuration_dirname() + result.extend(['build', configuration]) + result.append(self.built_file_basename(name, type, **kw)) + return self.workpath(*result) + + +format_class_list = [ + TestGypGypd, + TestGypMake, + TestGypMSVS, + TestGypNinja, + TestGypSCons, + TestGypXcode, +] + +def TestGyp(*args, **kw): + """ + Returns an appropriate TestGyp* instance for a specified GYP format. + """ + format = kw.get('format') + if format: + del kw['format'] + else: + format = os.environ.get('TESTGYP_FORMAT') + for format_class in format_class_list: + if format == format_class.format: + return format_class(*args, **kw) + raise Exception, "unknown format %r" % format diff --git a/tools/gyp/test/library/gyptest-shared-obj-install-path.py b/tools/gyp/test/library/gyptest-shared-obj-install-path.py new file mode 100755 index 00000000000..2cf1a28458f --- /dev/null +++ b/tools/gyp/test/library/gyptest-shared-obj-install-path.py @@ -0,0 +1,37 @@ +#!/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 that .so files that are order only dependencies are specified by +their install location rather than by their alias. +""" + +# Python 2.5 needs this for the with statement. +from __future__ import with_statement + +import os +import TestGyp + +test = TestGyp.TestGyp(formats=['make']) + +test.run_gyp('shared_dependency.gyp', + chdir='src') +test.relocate('src', 'relocate/src') + +test.build('shared_dependency.gyp', test.ALL, chdir='relocate/src') + +with open('relocate/src/Makefile') as makefile: + make_contents = makefile.read() + +# If we remove the code to generate lib1, Make should still be able +# to build lib2 since lib1.so already exists. +make_contents = make_contents.replace('include lib1.target.mk', '') +with open('relocate/src/Makefile', 'w') as makefile: + makefile.write(make_contents) + +test.build('shared_dependency.gyp', test.ALL, chdir='relocate/src') + +test.pass_test() diff --git a/tools/gyp/test/library/gyptest-shared.py b/tools/gyp/test/library/gyptest-shared.py new file mode 100755 index 00000000000..a1d2985d919 --- /dev/null +++ b/tools/gyp/test/library/gyptest-shared.py @@ -0,0 +1,84 @@ +#!/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 build of a "Hello, world!" program with shared libraries, +including verifying that libraries are rebuilt correctly when functions +move between libraries. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('library.gyp', + '-Dlibrary=shared_library', + '-Dmoveable_function=lib1', + chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('library.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello from program.c +Hello from lib1.c +Hello from lib2.c +Hello from lib1_moveable.c +""" +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + + +test.run_gyp('library.gyp', + '-Dlibrary=shared_library', + '-Dmoveable_function=lib2', + chdir='relocate/src') + +# Update program.c to force a rebuild. +test.sleep() +contents = test.read('relocate/src/program.c') +contents = contents.replace('Hello', 'Hello again') +test.write('relocate/src/program.c', contents) + +test.build('library.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello again from program.c +Hello from lib1.c +Hello from lib2.c +Hello from lib2_moveable.c +""" +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + + +test.run_gyp('library.gyp', + '-Dlibrary=shared_library', + '-Dmoveable_function=lib1', + chdir='relocate/src') + +# Update program.c to force a rebuild. +test.sleep() +contents = test.read('relocate/src/program.c') +contents = contents.replace('again', 'again again') +test.write('relocate/src/program.c', contents) + +# TODO(sgk): we have to force a rebuild of lib2 so that it weeds out +# the "moved" module. This should be done in gyp by adding a dependency +# on the generated .vcproj file itself. +test.touch('relocate/src/lib2.c') + +test.build('library.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello again again from program.c +Hello from lib1.c +Hello from lib2.c +Hello from lib1_moveable.c +""" +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + + +test.pass_test() diff --git a/tools/gyp/test/library/gyptest-static.py b/tools/gyp/test/library/gyptest-static.py new file mode 100755 index 00000000000..4bc71c4962a --- /dev/null +++ b/tools/gyp/test/library/gyptest-static.py @@ -0,0 +1,84 @@ +#!/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 build of a "Hello, world!" program with static libraries, +including verifying that libraries are rebuilt correctly when functions +move between libraries. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('library.gyp', + '-Dlibrary=static_library', + '-Dmoveable_function=lib1', + chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('library.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello from program.c +Hello from lib1.c +Hello from lib2.c +Hello from lib1_moveable.c +""" +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + + +test.run_gyp('library.gyp', + '-Dlibrary=static_library', + '-Dmoveable_function=lib2', + chdir='relocate/src') + +# Update program.c to force a rebuild. +test.sleep() +contents = test.read('relocate/src/program.c') +contents = contents.replace('Hello', 'Hello again') +test.write('relocate/src/program.c', contents) + +test.build('library.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello again from program.c +Hello from lib1.c +Hello from lib2.c +Hello from lib2_moveable.c +""" +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + + +test.run_gyp('library.gyp', + '-Dlibrary=static_library', + '-Dmoveable_function=lib1', + chdir='relocate/src') + +# Update program.c and lib2.c to force a rebuild. +test.sleep() +contents = test.read('relocate/src/program.c') +contents = contents.replace('again', 'again again') +test.write('relocate/src/program.c', contents) + +# TODO(sgk): we have to force a rebuild of lib2 so that it weeds out +# the "moved" module. This should be done in gyp by adding a dependency +# on the generated .vcproj file itself. +test.touch('relocate/src/lib2.c') + +test.build('library.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello again again from program.c +Hello from lib1.c +Hello from lib2.c +Hello from lib1_moveable.c +""" +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + + +test.pass_test() diff --git a/tools/gyp/test/library/src/lib1.c b/tools/gyp/test/library/src/lib1.c new file mode 100644 index 00000000000..3866b1b845f --- /dev/null +++ b/tools/gyp/test/library/src/lib1.c @@ -0,0 +1,10 @@ +#include <stdio.h> + +#ifdef _WIN32 +__declspec(dllexport) +#endif +void lib1_function(void) +{ + fprintf(stdout, "Hello from lib1.c\n"); + fflush(stdout); +} diff --git a/tools/gyp/test/library/src/lib1_moveable.c b/tools/gyp/test/library/src/lib1_moveable.c new file mode 100644 index 00000000000..5d3cc1d9aab --- /dev/null +++ b/tools/gyp/test/library/src/lib1_moveable.c @@ -0,0 +1,10 @@ +#include <stdio.h> + +#ifdef _WIN32 +__declspec(dllexport) +#endif +void moveable_function(void) +{ + fprintf(stdout, "Hello from lib1_moveable.c\n"); + fflush(stdout); +} diff --git a/tools/gyp/test/library/src/lib2.c b/tools/gyp/test/library/src/lib2.c new file mode 100644 index 00000000000..21dda726530 --- /dev/null +++ b/tools/gyp/test/library/src/lib2.c @@ -0,0 +1,10 @@ +#include <stdio.h> + +#ifdef _WIN32 +__declspec(dllexport) +#endif +void lib2_function(void) +{ + fprintf(stdout, "Hello from lib2.c\n"); + fflush(stdout); +} diff --git a/tools/gyp/test/library/src/lib2_moveable.c b/tools/gyp/test/library/src/lib2_moveable.c new file mode 100644 index 00000000000..f645071d1eb --- /dev/null +++ b/tools/gyp/test/library/src/lib2_moveable.c @@ -0,0 +1,10 @@ +#include <stdio.h> + +#ifdef _WIN32 +__declspec(dllexport) +#endif +void moveable_function(void) +{ + fprintf(stdout, "Hello from lib2_moveable.c\n"); + fflush(stdout); +} diff --git a/tools/gyp/test/library/src/library.gyp b/tools/gyp/test/library/src/library.gyp new file mode 100644 index 00000000000..bc355164260 --- /dev/null +++ b/tools/gyp/test/library/src/library.gyp @@ -0,0 +1,58 @@ +# 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. + +{ + 'variables': { + 'moveable_function%': 0, + }, + 'targets': [ + { + 'target_name': 'program', + 'type': 'executable', + 'dependencies': [ + 'lib1', + 'lib2', + ], + 'sources': [ + 'program.c', + ], + }, + { + 'target_name': 'lib1', + 'type': '<(library)', + 'sources': [ + 'lib1.c', + ], + 'conditions': [ + ['moveable_function=="lib1"', { + 'sources': [ + 'lib1_moveable.c', + ], + }], + ], + }, + { + 'target_name': 'lib2', + 'type': '<(library)', + 'sources': [ + 'lib2.c', + ], + 'conditions': [ + ['moveable_function=="lib2"', { + 'sources': [ + 'lib2_moveable.c', + ], + }], + ], + }, + ], + 'conditions': [ + ['OS=="linux"', { + 'target_defaults': { + # Support 64-bit shared libs (also works fine for 32-bit). + 'cflags': ['-fPIC'], + }, + }], + ], +} diff --git a/tools/gyp/test/library/src/program.c b/tools/gyp/test/library/src/program.c new file mode 100644 index 00000000000..d7712cced42 --- /dev/null +++ b/tools/gyp/test/library/src/program.c @@ -0,0 +1,15 @@ +#include <stdio.h> + +extern void lib1_function(void); +extern void lib2_function(void); +extern void moveable_function(void); + +int main(int argc, char *argv[]) +{ + fprintf(stdout, "Hello from program.c\n"); + fflush(stdout); + lib1_function(); + lib2_function(); + moveable_function(); + return 0; +} diff --git a/tools/gyp/test/library/src/shared_dependency.gyp b/tools/gyp/test/library/src/shared_dependency.gyp new file mode 100644 index 00000000000..7d29f5de598 --- /dev/null +++ b/tools/gyp/test/library/src/shared_dependency.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': 'lib1', + 'type': 'shared_library', + 'sources': [ + 'lib1.c', + ], + }, + { + 'target_name': 'lib2', + 'type': 'shared_library', + 'sources': [ + 'lib2.c', + ], + 'dependencies': [ + 'lib1', + ], + }, + ], + 'conditions': [ + ['OS=="linux"', { + 'target_defaults': { + # Support 64-bit shared libs (also works fine for 32-bit). + 'cflags': ['-fPIC'], + }, + }], + ], +} diff --git a/tools/gyp/test/link-objects/base.c b/tools/gyp/test/link-objects/base.c new file mode 100644 index 00000000000..2bc29a1b187 --- /dev/null +++ b/tools/gyp/test/link-objects/base.c @@ -0,0 +1,6 @@ +void extra(); + +int main(int argc, char** argv) { + extra(); + return 0; +} diff --git a/tools/gyp/test/link-objects/extra.c b/tools/gyp/test/link-objects/extra.c new file mode 100644 index 00000000000..1d7ee09b107 --- /dev/null +++ b/tools/gyp/test/link-objects/extra.c @@ -0,0 +1,5 @@ +#include <stdio.h> + +void extra() { + printf("PASS\n"); +} diff --git a/tools/gyp/test/link-objects/gyptest-all.py b/tools/gyp/test/link-objects/gyptest-all.py new file mode 100755 index 00000000000..45bd6e18913 --- /dev/null +++ b/tools/gyp/test/link-objects/gyptest-all.py @@ -0,0 +1,28 @@ +#!/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. + +""" +Put an object file on the sources list. +Expect the result to link ok. +""" + +import TestGyp + +import sys + +if sys.platform != 'darwin': + # Currently only works under the linux make build. + test = TestGyp.TestGyp(formats=['make']) + + test.run_gyp('link-objects.gyp') + + test.build('link-objects.gyp', test.ALL) + + test.run_built_executable('link-objects', stdout="PASS\n") + + test.up_to_date('link-objects.gyp', test.ALL) + + test.pass_test() diff --git a/tools/gyp/test/link-objects/link-objects.gyp b/tools/gyp/test/link-objects/link-objects.gyp new file mode 100644 index 00000000000..ab72855531a --- /dev/null +++ b/tools/gyp/test/link-objects/link-objects.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': 'link-objects', + 'type': 'executable', + 'actions': [ + { + 'action_name': 'build extra object', + 'inputs': ['extra.c'], + 'outputs': ['extra.o'], + 'action': ['gcc', '-o', 'extra.o', '-c', 'extra.c'], + 'process_outputs_as_sources': 1, + }, + ], + 'sources': [ + 'base.c', + ], + }, + ], +} diff --git a/tools/gyp/test/mac/app-bundle/TestApp/English.lproj/InfoPlist.strings b/tools/gyp/test/mac/app-bundle/TestApp/English.lproj/InfoPlist.strings new file mode 100644 index 00000000000..452e7fabf9d --- /dev/null +++ b/tools/gyp/test/mac/app-bundle/TestApp/English.lproj/InfoPlist.strings @@ -0,0 +1,3 @@ +/* Localized versions of Info.plist keys */ + +NSHumanReadableCopyright = "Copyright ©2011 Google Inc." diff --git a/tools/gyp/test/mac/app-bundle/TestApp/English.lproj/MainMenu.xib b/tools/gyp/test/mac/app-bundle/TestApp/English.lproj/MainMenu.xib new file mode 100644 index 00000000000..4524596787a --- /dev/null +++ b/tools/gyp/test/mac/app-bundle/TestApp/English.lproj/MainMenu.xib @@ -0,0 +1,4119 @@ +<?xml version="1.0" encoding="UTF-8"?> +<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10"> + <data> + <int key="IBDocument.SystemTarget">1060</int> + <string key="IBDocument.SystemVersion">10A324</string> + <string key="IBDocument.InterfaceBuilderVersion">719</string> + <string key="IBDocument.AppKitVersion">1015</string> + <string key="IBDocument.HIToolboxVersion">418.00</string> + <object class="NSMutableDictionary" key="IBDocument.PluginVersions"> + <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string> + <string key="NS.object.0">719</string> + </object> + <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> + <bool key="EncodedWithXMLCoder">YES</bool> + <integer value="371"/> + <integer value="29"/> + </object> + <object class="NSArray" key="IBDocument.PluginDependencies"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + </object> + <object class="NSMutableDictionary" key="IBDocument.Metadata"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSArray" key="dict.sortedKeys" id="0"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + </object> + <object class="NSMutableArray" key="IBDocument.RootObjects" id="1048"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSCustomObject" id="1021"> + <string key="NSClassName">NSApplication</string> + </object> + <object class="NSCustomObject" id="1014"> + <string key="NSClassName">FirstResponder</string> + </object> + <object class="NSCustomObject" id="1050"> + <string key="NSClassName">NSApplication</string> + </object> + <object class="NSMenu" id="649796088"> + <string key="NSTitle">AMainMenu</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="694149608"> + <reference key="NSMenu" ref="649796088"/> + <string key="NSTitle">TestApp</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <object class="NSCustomResource" key="NSOnImage" id="35465992"> + <string key="NSClassName">NSImage</string> + <string key="NSResourceName">NSMenuCheckmark</string> + </object> + <object class="NSCustomResource" key="NSMixedImage" id="502551668"> + <string key="NSClassName">NSImage</string> + <string key="NSResourceName">NSMenuMixedState</string> + </object> + <string key="NSAction">submenuAction:</string> + <object class="NSMenu" key="NSSubmenu" id="110575045"> + <string key="NSTitle">TestApp</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="238522557"> + <reference key="NSMenu" ref="110575045"/> + <string key="NSTitle">About TestApp</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="304266470"> + <reference key="NSMenu" ref="110575045"/> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="609285721"> + <reference key="NSMenu" ref="110575045"/> + <string key="NSTitle">Preferences…</string> + <string key="NSKeyEquiv">,</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="481834944"> + <reference key="NSMenu" ref="110575045"/> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="1046388886"> + <reference key="NSMenu" ref="110575045"/> + <string key="NSTitle">Services</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <string key="NSAction">submenuAction:</string> + <object class="NSMenu" key="NSSubmenu" id="752062318"> + <string key="NSTitle">Services</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + <string key="NSName">_NSServicesMenu</string> + </object> + </object> + <object class="NSMenuItem" id="646227648"> + <reference key="NSMenu" ref="110575045"/> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="755159360"> + <reference key="NSMenu" ref="110575045"/> + <string key="NSTitle">Hide TestApp</string> + <string key="NSKeyEquiv">h</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="342932134"> + <reference key="NSMenu" ref="110575045"/> + <string key="NSTitle">Hide Others</string> + <string key="NSKeyEquiv">h</string> + <int key="NSKeyEquivModMask">1572864</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="908899353"> + <reference key="NSMenu" ref="110575045"/> + <string key="NSTitle">Show All</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="1056857174"> + <reference key="NSMenu" ref="110575045"/> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="632727374"> + <reference key="NSMenu" ref="110575045"/> + <string key="NSTitle">Quit TestApp</string> + <string key="NSKeyEquiv">q</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + </object> + <string key="NSName">_NSAppleMenu</string> + </object> + </object> + <object class="NSMenuItem" id="379814623"> + <reference key="NSMenu" ref="649796088"/> + <string key="NSTitle">File</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <string key="NSAction">submenuAction:</string> + <object class="NSMenu" key="NSSubmenu" id="720053764"> + <string key="NSTitle">File</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="705341025"> + <reference key="NSMenu" ref="720053764"/> + <string key="NSTitle">New</string> + <string key="NSKeyEquiv">n</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="722745758"> + <reference key="NSMenu" ref="720053764"/> + <string key="NSTitle">Open…</string> + <string key="NSKeyEquiv">o</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="1025936716"> + <reference key="NSMenu" ref="720053764"/> + <string key="NSTitle">Open Recent</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <string key="NSAction">submenuAction:</string> + <object class="NSMenu" key="NSSubmenu" id="1065607017"> + <string key="NSTitle">Open Recent</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="759406840"> + <reference key="NSMenu" ref="1065607017"/> + <string key="NSTitle">Clear Menu</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + </object> + <string key="NSName">_NSRecentDocumentsMenu</string> + </object> + </object> + <object class="NSMenuItem" id="425164168"> + <reference key="NSMenu" ref="720053764"/> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="776162233"> + <reference key="NSMenu" ref="720053764"/> + <string key="NSTitle">Close</string> + <string key="NSKeyEquiv">w</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="1023925487"> + <reference key="NSMenu" ref="720053764"/> + <string key="NSTitle">Save</string> + <string key="NSKeyEquiv">s</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="117038363"> + <reference key="NSMenu" ref="720053764"/> + <string key="NSTitle">Save As…</string> + <string key="NSKeyEquiv">S</string> + <int key="NSKeyEquivModMask">1179648</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="579971712"> + <reference key="NSMenu" ref="720053764"/> + <string key="NSTitle">Revert to Saved</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="1010469920"> + <reference key="NSMenu" ref="720053764"/> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="294629803"> + <reference key="NSMenu" ref="720053764"/> + <string key="NSTitle">Page Setup...</string> + <string key="NSKeyEquiv">P</string> + <int key="NSKeyEquivModMask">1179648</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <string key="NSToolTip"/> + </object> + <object class="NSMenuItem" id="49223823"> + <reference key="NSMenu" ref="720053764"/> + <string key="NSTitle">Print…</string> + <string key="NSKeyEquiv">p</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + </object> + </object> + </object> + <object class="NSMenuItem" id="952259628"> + <reference key="NSMenu" ref="649796088"/> + <string key="NSTitle">Edit</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <string key="NSAction">submenuAction:</string> + <object class="NSMenu" key="NSSubmenu" id="789758025"> + <string key="NSTitle">Edit</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="1058277027"> + <reference key="NSMenu" ref="789758025"/> + <string key="NSTitle">Undo</string> + <string key="NSKeyEquiv">z</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="790794224"> + <reference key="NSMenu" ref="789758025"/> + <string key="NSTitle">Redo</string> + <string key="NSKeyEquiv">Z</string> + <int key="NSKeyEquivModMask">1179648</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="1040322652"> + <reference key="NSMenu" ref="789758025"/> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="296257095"> + <reference key="NSMenu" ref="789758025"/> + <string key="NSTitle">Cut</string> + <string key="NSKeyEquiv">x</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="860595796"> + <reference key="NSMenu" ref="789758025"/> + <string key="NSTitle">Copy</string> + <string key="NSKeyEquiv">c</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="29853731"> + <reference key="NSMenu" ref="789758025"/> + <string key="NSTitle">Paste</string> + <string key="NSKeyEquiv">v</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="82994268"> + <reference key="NSMenu" ref="789758025"/> + <string key="NSTitle">Paste and Match Style</string> + <string key="NSKeyEquiv">V</string> + <int key="NSKeyEquivModMask">1572864</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="437104165"> + <reference key="NSMenu" ref="789758025"/> + <string key="NSTitle">Delete</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="583158037"> + <reference key="NSMenu" ref="789758025"/> + <string key="NSTitle">Select All</string> + <string key="NSKeyEquiv">a</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="212016141"> + <reference key="NSMenu" ref="789758025"/> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="892235320"> + <reference key="NSMenu" ref="789758025"/> + <string key="NSTitle">Find</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <string key="NSAction">submenuAction:</string> + <object class="NSMenu" key="NSSubmenu" id="963351320"> + <string key="NSTitle">Find</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="447796847"> + <reference key="NSMenu" ref="963351320"/> + <string key="NSTitle">Find…</string> + <string key="NSKeyEquiv">f</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <int key="NSTag">1</int> + </object> + <object class="NSMenuItem" id="326711663"> + <reference key="NSMenu" ref="963351320"/> + <string key="NSTitle">Find Next</string> + <string key="NSKeyEquiv">g</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <int key="NSTag">2</int> + </object> + <object class="NSMenuItem" id="270902937"> + <reference key="NSMenu" ref="963351320"/> + <string key="NSTitle">Find Previous</string> + <string key="NSKeyEquiv">G</string> + <int key="NSKeyEquivModMask">1179648</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <int key="NSTag">3</int> + </object> + <object class="NSMenuItem" id="159080638"> + <reference key="NSMenu" ref="963351320"/> + <string key="NSTitle">Use Selection for Find</string> + <string key="NSKeyEquiv">e</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <int key="NSTag">7</int> + </object> + <object class="NSMenuItem" id="88285865"> + <reference key="NSMenu" ref="963351320"/> + <string key="NSTitle">Jump to Selection</string> + <string key="NSKeyEquiv">j</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + </object> + </object> + </object> + <object class="NSMenuItem" id="972420730"> + <reference key="NSMenu" ref="789758025"/> + <string key="NSTitle">Spelling and Grammar</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <string key="NSAction">submenuAction:</string> + <object class="NSMenu" key="NSSubmenu" id="769623530"> + <string key="NSTitle">Spelling and Grammar</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="679648819"> + <reference key="NSMenu" ref="769623530"/> + <string key="NSTitle">Show Spelling and Grammar</string> + <string key="NSKeyEquiv">:</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="96193923"> + <reference key="NSMenu" ref="769623530"/> + <string key="NSTitle">Check Document Now</string> + <string key="NSKeyEquiv">;</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="859480356"> + <reference key="NSMenu" ref="769623530"/> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="948374510"> + <reference key="NSMenu" ref="769623530"/> + <string key="NSTitle">Check Spelling While Typing</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="967646866"> + <reference key="NSMenu" ref="769623530"/> + <string key="NSTitle">Check Grammar With Spelling</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="795346622"> + <reference key="NSMenu" ref="769623530"/> + <string key="NSTitle">Correct Spelling Automatically</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + </object> + </object> + </object> + <object class="NSMenuItem" id="507821607"> + <reference key="NSMenu" ref="789758025"/> + <string key="NSTitle">Substitutions</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <string key="NSAction">submenuAction:</string> + <object class="NSMenu" key="NSSubmenu" id="698887838"> + <string key="NSTitle">Substitutions</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="65139061"> + <reference key="NSMenu" ref="698887838"/> + <string key="NSTitle">Show Substitutions</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="19036812"> + <reference key="NSMenu" ref="698887838"/> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="605118523"> + <reference key="NSMenu" ref="698887838"/> + <string key="NSTitle">Smart Copy/Paste</string> + <string key="NSKeyEquiv">f</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <int key="NSTag">1</int> + </object> + <object class="NSMenuItem" id="197661976"> + <reference key="NSMenu" ref="698887838"/> + <string key="NSTitle">Smart Quotes</string> + <string key="NSKeyEquiv">g</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <int key="NSTag">2</int> + </object> + <object class="NSMenuItem" id="672708820"> + <reference key="NSMenu" ref="698887838"/> + <string key="NSTitle">Smart Dashes</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="708854459"> + <reference key="NSMenu" ref="698887838"/> + <string key="NSTitle">Smart Links</string> + <string key="NSKeyEquiv">G</string> + <int key="NSKeyEquivModMask">1179648</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <int key="NSTag">3</int> + </object> + <object class="NSMenuItem" id="537092702"> + <reference key="NSMenu" ref="698887838"/> + <string key="NSTitle">Text Replacement</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + </object> + </object> + </object> + <object class="NSMenuItem" id="288088188"> + <reference key="NSMenu" ref="789758025"/> + <string key="NSTitle">Transformations</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <string key="NSAction">submenuAction:</string> + <object class="NSMenu" key="NSSubmenu" id="579392910"> + <string key="NSTitle">Transformations</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="1060694897"> + <reference key="NSMenu" ref="579392910"/> + <string key="NSTitle">Make Upper Case</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="879586729"> + <reference key="NSMenu" ref="579392910"/> + <string key="NSTitle">Make Lower Case</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="56570060"> + <reference key="NSMenu" ref="579392910"/> + <string key="NSTitle">Capitalize</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + </object> + </object> + </object> + <object class="NSMenuItem" id="676164635"> + <reference key="NSMenu" ref="789758025"/> + <string key="NSTitle">Speech</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <string key="NSAction">submenuAction:</string> + <object class="NSMenu" key="NSSubmenu" id="785027613"> + <string key="NSTitle">Speech</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="731782645"> + <reference key="NSMenu" ref="785027613"/> + <string key="NSTitle">Start Speaking</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="680220178"> + <reference key="NSMenu" ref="785027613"/> + <string key="NSTitle">Stop Speaking</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + </object> + </object> + </object> + </object> + </object> + </object> + <object class="NSMenuItem" id="302598603"> + <reference key="NSMenu" ref="649796088"/> + <string key="NSTitle">Format</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <string key="NSAction">submenuAction:</string> + <object class="NSMenu" key="NSSubmenu" id="941447902"> + <string key="NSTitle">Format</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="792887677"> + <reference key="NSMenu" ref="941447902"/> + <string key="NSTitle">Font</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <string key="NSAction">submenuAction:</string> + <object class="NSMenu" key="NSSubmenu" id="786677654"> + <string key="NSTitle">Font</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="159677712"> + <reference key="NSMenu" ref="786677654"/> + <string key="NSTitle">Show Fonts</string> + <string key="NSKeyEquiv">t</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="305399458"> + <reference key="NSMenu" ref="786677654"/> + <string key="NSTitle">Bold</string> + <string key="NSKeyEquiv">b</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <int key="NSTag">2</int> + </object> + <object class="NSMenuItem" id="814362025"> + <reference key="NSMenu" ref="786677654"/> + <string key="NSTitle">Italic</string> + <string key="NSKeyEquiv">i</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <int key="NSTag">1</int> + </object> + <object class="NSMenuItem" id="330926929"> + <reference key="NSMenu" ref="786677654"/> + <string key="NSTitle">Underline</string> + <string key="NSKeyEquiv">u</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="533507878"> + <reference key="NSMenu" ref="786677654"/> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="158063935"> + <reference key="NSMenu" ref="786677654"/> + <string key="NSTitle">Bigger</string> + <string key="NSKeyEquiv">+</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <int key="NSTag">3</int> + </object> + <object class="NSMenuItem" id="885547335"> + <reference key="NSMenu" ref="786677654"/> + <string key="NSTitle">Smaller</string> + <string key="NSKeyEquiv">-</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <int key="NSTag">4</int> + </object> + <object class="NSMenuItem" id="901062459"> + <reference key="NSMenu" ref="786677654"/> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="767671776"> + <reference key="NSMenu" ref="786677654"/> + <string key="NSTitle">Kern</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <string key="NSAction">submenuAction:</string> + <object class="NSMenu" key="NSSubmenu" id="175441468"> + <string key="NSTitle">Kern</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="252969304"> + <reference key="NSMenu" ref="175441468"/> + <string key="NSTitle">Use Default</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="766922938"> + <reference key="NSMenu" ref="175441468"/> + <string key="NSTitle">Use None</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="677519740"> + <reference key="NSMenu" ref="175441468"/> + <string key="NSTitle">Tighten</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="238351151"> + <reference key="NSMenu" ref="175441468"/> + <string key="NSTitle">Loosen</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + </object> + </object> + </object> + <object class="NSMenuItem" id="691570813"> + <reference key="NSMenu" ref="786677654"/> + <string key="NSTitle">Ligature</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <string key="NSAction">submenuAction:</string> + <object class="NSMenu" key="NSSubmenu" id="1058217995"> + <string key="NSTitle">Ligature</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="706297211"> + <reference key="NSMenu" ref="1058217995"/> + <string key="NSTitle">Use Default</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="568384683"> + <reference key="NSMenu" ref="1058217995"/> + <string key="NSTitle">Use None</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="663508465"> + <reference key="NSMenu" ref="1058217995"/> + <string key="NSTitle">Use All</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + </object> + </object> + </object> + <object class="NSMenuItem" id="769124883"> + <reference key="NSMenu" ref="786677654"/> + <string key="NSTitle">Baseline</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <string key="NSAction">submenuAction:</string> + <object class="NSMenu" key="NSSubmenu" id="18263474"> + <string key="NSTitle">Baseline</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="257962622"> + <reference key="NSMenu" ref="18263474"/> + <string key="NSTitle">Use Default</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="644725453"> + <reference key="NSMenu" ref="18263474"/> + <string key="NSTitle">Superscript</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="1037576581"> + <reference key="NSMenu" ref="18263474"/> + <string key="NSTitle">Subscript</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="941806246"> + <reference key="NSMenu" ref="18263474"/> + <string key="NSTitle">Raise</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="1045724900"> + <reference key="NSMenu" ref="18263474"/> + <string key="NSTitle">Lower</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + </object> + </object> + </object> + <object class="NSMenuItem" id="739652853"> + <reference key="NSMenu" ref="786677654"/> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="1012600125"> + <reference key="NSMenu" ref="786677654"/> + <string key="NSTitle">Show Colors</string> + <string key="NSKeyEquiv">C</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="214559597"> + <reference key="NSMenu" ref="786677654"/> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="596732606"> + <reference key="NSMenu" ref="786677654"/> + <string key="NSTitle">Copy Style</string> + <string key="NSKeyEquiv">c</string> + <int key="NSKeyEquivModMask">1572864</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="393423671"> + <reference key="NSMenu" ref="786677654"/> + <string key="NSTitle">Paste Style</string> + <string key="NSKeyEquiv">v</string> + <int key="NSKeyEquivModMask">1572864</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + </object> + <string key="NSName">_NSFontMenu</string> + </object> + </object> + <object class="NSMenuItem" id="215659978"> + <reference key="NSMenu" ref="941447902"/> + <string key="NSTitle">Text</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <string key="NSAction">submenuAction:</string> + <object class="NSMenu" key="NSSubmenu" id="446991534"> + <string key="NSTitle">Text</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="875092757"> + <reference key="NSMenu" ref="446991534"/> + <string key="NSTitle">Align Left</string> + <string key="NSKeyEquiv">{</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="630155264"> + <reference key="NSMenu" ref="446991534"/> + <string key="NSTitle">Center</string> + <string key="NSKeyEquiv">|</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="945678886"> + <reference key="NSMenu" ref="446991534"/> + <string key="NSTitle">Justify</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="512868991"> + <reference key="NSMenu" ref="446991534"/> + <string key="NSTitle">Align Right</string> + <string key="NSKeyEquiv">}</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="163117631"> + <reference key="NSMenu" ref="446991534"/> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="31516759"> + <reference key="NSMenu" ref="446991534"/> + <string key="NSTitle">Writing Direction</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <string key="NSAction">submenuAction:</string> + <object class="NSMenu" key="NSSubmenu" id="956096989"> + <string key="NSTitle">Writing Direction</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="257099033"> + <reference key="NSMenu" ref="956096989"/> + <bool key="NSIsDisabled">YES</bool> + <string key="NSTitle">Paragraph</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="551969625"> + <reference key="NSMenu" ref="956096989"/> + <string type="base64-UTF8" key="NSTitle">CURlZmF1bHQ</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="249532473"> + <reference key="NSMenu" ref="956096989"/> + <string type="base64-UTF8" key="NSTitle">CUxlZnQgdG8gUmlnaHQ</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="607364498"> + <reference key="NSMenu" ref="956096989"/> + <string type="base64-UTF8" key="NSTitle">CVJpZ2h0IHRvIExlZnQ</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="508151438"> + <reference key="NSMenu" ref="956096989"/> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="981751889"> + <reference key="NSMenu" ref="956096989"/> + <bool key="NSIsDisabled">YES</bool> + <string key="NSTitle">Selection</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="380031999"> + <reference key="NSMenu" ref="956096989"/> + <string type="base64-UTF8" key="NSTitle">CURlZmF1bHQ</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="825984362"> + <reference key="NSMenu" ref="956096989"/> + <string type="base64-UTF8" key="NSTitle">CUxlZnQgdG8gUmlnaHQ</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="560145579"> + <reference key="NSMenu" ref="956096989"/> + <string type="base64-UTF8" key="NSTitle">CVJpZ2h0IHRvIExlZnQ</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + </object> + </object> + </object> + <object class="NSMenuItem" id="908105787"> + <reference key="NSMenu" ref="446991534"/> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="644046920"> + <reference key="NSMenu" ref="446991534"/> + <string key="NSTitle">Show Ruler</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="231811626"> + <reference key="NSMenu" ref="446991534"/> + <string key="NSTitle">Copy Ruler</string> + <string key="NSKeyEquiv">c</string> + <int key="NSKeyEquivModMask">1310720</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="883618387"> + <reference key="NSMenu" ref="446991534"/> + <string key="NSTitle">Paste Ruler</string> + <string key="NSKeyEquiv">v</string> + <int key="NSKeyEquivModMask">1310720</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + </object> + </object> + </object> + </object> + </object> + </object> + <object class="NSMenuItem" id="586577488"> + <reference key="NSMenu" ref="649796088"/> + <string key="NSTitle">View</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <string key="NSAction">submenuAction:</string> + <object class="NSMenu" key="NSSubmenu" id="466310130"> + <string key="NSTitle">View</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="102151532"> + <reference key="NSMenu" ref="466310130"/> + <string key="NSTitle">Show Toolbar</string> + <string key="NSKeyEquiv">t</string> + <int key="NSKeyEquivModMask">1572864</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="237841660"> + <reference key="NSMenu" ref="466310130"/> + <string key="NSTitle">Customize Toolbar…</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + </object> + </object> + </object> + <object class="NSMenuItem" id="713487014"> + <reference key="NSMenu" ref="649796088"/> + <string key="NSTitle">Window</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <string key="NSAction">submenuAction:</string> + <object class="NSMenu" key="NSSubmenu" id="835318025"> + <string key="NSTitle">Window</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="1011231497"> + <reference key="NSMenu" ref="835318025"/> + <string key="NSTitle">Minimize</string> + <string key="NSKeyEquiv">m</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="575023229"> + <reference key="NSMenu" ref="835318025"/> + <string key="NSTitle">Zoom</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="299356726"> + <reference key="NSMenu" ref="835318025"/> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + <object class="NSMenuItem" id="625202149"> + <reference key="NSMenu" ref="835318025"/> + <string key="NSTitle">Bring All to Front</string> + <string key="NSKeyEquiv"/> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + </object> + <string key="NSName">_NSWindowsMenu</string> + </object> + </object> + <object class="NSMenuItem" id="448692316"> + <reference key="NSMenu" ref="649796088"/> + <string key="NSTitle">Help</string> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + <string key="NSAction">submenuAction:</string> + <object class="NSMenu" key="NSSubmenu" id="992780483"> + <string key="NSTitle">Help</string> + <object class="NSMutableArray" key="NSMenuItems"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSMenuItem" id="105068016"> + <reference key="NSMenu" ref="992780483"/> + <string key="NSTitle">TestApp Help</string> + <string key="NSKeyEquiv">?</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="35465992"/> + <reference key="NSMixedImage" ref="502551668"/> + </object> + </object> + <string key="NSName">_NSHelpMenu</string> + </object> + </object> + </object> + <string key="NSName">_NSMainMenu</string> + </object> + <object class="NSWindowTemplate" id="972006081"> + <int key="NSWindowStyleMask">15</int> + <int key="NSWindowBacking">2</int> + <string key="NSWindowRect">{{335, 390}, {480, 360}}</string> + <int key="NSWTFlags">1954021376</int> + <string key="NSWindowTitle">TestApp</string> + <string key="NSWindowClass">NSWindow</string> + <nil key="NSViewClass"/> + <string key="NSWindowContentMaxSize">{1.79769e+308, 1.79769e+308}</string> + <object class="NSView" key="NSWindowView" id="439893737"> + <reference key="NSNextResponder"/> + <int key="NSvFlags">256</int> + <string key="NSFrameSize">{480, 360}</string> + <reference key="NSSuperview"/> + </object> + <string key="NSScreenRect">{{0, 0}, {1920, 1178}}</string> + <string key="NSMaxSize">{1.79769e+308, 1.79769e+308}</string> + </object> + <object class="NSCustomObject" id="976324537"> + <string key="NSClassName">TestAppAppDelegate</string> + </object> + <object class="NSCustomObject" id="755631768"> + <string key="NSClassName">NSFontManager</string> + </object> + </object> + <object class="IBObjectContainer" key="IBDocument.Objects"> + <object class="NSMutableArray" key="connectionRecords"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">performMiniaturize:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="1011231497"/> + </object> + <int key="connectionID">37</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">arrangeInFront:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="625202149"/> + </object> + <int key="connectionID">39</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">print:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="49223823"/> + </object> + <int key="connectionID">86</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">runPageLayout:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="294629803"/> + </object> + <int key="connectionID">87</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">clearRecentDocuments:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="759406840"/> + </object> + <int key="connectionID">127</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">orderFrontStandardAboutPanel:</string> + <reference key="source" ref="1021"/> + <reference key="destination" ref="238522557"/> + </object> + <int key="connectionID">142</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">performClose:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="776162233"/> + </object> + <int key="connectionID">193</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">toggleContinuousSpellChecking:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="948374510"/> + </object> + <int key="connectionID">222</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">undo:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="1058277027"/> + </object> + <int key="connectionID">223</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">copy:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="860595796"/> + </object> + <int key="connectionID">224</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">checkSpelling:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="96193923"/> + </object> + <int key="connectionID">225</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">paste:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="29853731"/> + </object> + <int key="connectionID">226</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">stopSpeaking:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="680220178"/> + </object> + <int key="connectionID">227</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">cut:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="296257095"/> + </object> + <int key="connectionID">228</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">showGuessPanel:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="679648819"/> + </object> + <int key="connectionID">230</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">redo:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="790794224"/> + </object> + <int key="connectionID">231</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">selectAll:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="583158037"/> + </object> + <int key="connectionID">232</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">startSpeaking:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="731782645"/> + </object> + <int key="connectionID">233</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">delete:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="437104165"/> + </object> + <int key="connectionID">235</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">performZoom:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="575023229"/> + </object> + <int key="connectionID">240</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">performFindPanelAction:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="447796847"/> + </object> + <int key="connectionID">241</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">centerSelectionInVisibleArea:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="88285865"/> + </object> + <int key="connectionID">245</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">toggleGrammarChecking:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="967646866"/> + </object> + <int key="connectionID">347</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">toggleSmartInsertDelete:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="605118523"/> + </object> + <int key="connectionID">355</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">toggleAutomaticQuoteSubstitution:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="197661976"/> + </object> + <int key="connectionID">356</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">toggleAutomaticLinkDetection:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="708854459"/> + </object> + <int key="connectionID">357</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">saveDocument:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="1023925487"/> + </object> + <int key="connectionID">362</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">saveDocumentAs:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="117038363"/> + </object> + <int key="connectionID">363</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">revertDocumentToSaved:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="579971712"/> + </object> + <int key="connectionID">364</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">runToolbarCustomizationPalette:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="237841660"/> + </object> + <int key="connectionID">365</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">toggleToolbarShown:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="102151532"/> + </object> + <int key="connectionID">366</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">hide:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="755159360"/> + </object> + <int key="connectionID">367</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">hideOtherApplications:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="342932134"/> + </object> + <int key="connectionID">368</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">unhideAllApplications:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="908899353"/> + </object> + <int key="connectionID">370</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">newDocument:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="705341025"/> + </object> + <int key="connectionID">373</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">openDocument:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="722745758"/> + </object> + <int key="connectionID">374</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">addFontTrait:</string> + <reference key="source" ref="755631768"/> + <reference key="destination" ref="305399458"/> + </object> + <int key="connectionID">421</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">addFontTrait:</string> + <reference key="source" ref="755631768"/> + <reference key="destination" ref="814362025"/> + </object> + <int key="connectionID">422</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">modifyFont:</string> + <reference key="source" ref="755631768"/> + <reference key="destination" ref="885547335"/> + </object> + <int key="connectionID">423</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">orderFrontFontPanel:</string> + <reference key="source" ref="755631768"/> + <reference key="destination" ref="159677712"/> + </object> + <int key="connectionID">424</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">modifyFont:</string> + <reference key="source" ref="755631768"/> + <reference key="destination" ref="158063935"/> + </object> + <int key="connectionID">425</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">raiseBaseline:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="941806246"/> + </object> + <int key="connectionID">426</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">lowerBaseline:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="1045724900"/> + </object> + <int key="connectionID">427</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">copyFont:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="596732606"/> + </object> + <int key="connectionID">428</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">subscript:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="1037576581"/> + </object> + <int key="connectionID">429</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">superscript:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="644725453"/> + </object> + <int key="connectionID">430</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">tightenKerning:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="677519740"/> + </object> + <int key="connectionID">431</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">underline:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="330926929"/> + </object> + <int key="connectionID">432</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">orderFrontColorPanel:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="1012600125"/> + </object> + <int key="connectionID">433</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">useAllLigatures:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="663508465"/> + </object> + <int key="connectionID">434</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">loosenKerning:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="238351151"/> + </object> + <int key="connectionID">435</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">pasteFont:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="393423671"/> + </object> + <int key="connectionID">436</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">unscript:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="257962622"/> + </object> + <int key="connectionID">437</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">useStandardKerning:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="252969304"/> + </object> + <int key="connectionID">438</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">useStandardLigatures:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="706297211"/> + </object> + <int key="connectionID">439</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">turnOffLigatures:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="568384683"/> + </object> + <int key="connectionID">440</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">turnOffKerning:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="766922938"/> + </object> + <int key="connectionID">441</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">terminate:</string> + <reference key="source" ref="1050"/> + <reference key="destination" ref="632727374"/> + </object> + <int key="connectionID">449</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">toggleAutomaticSpellingCorrection:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="795346622"/> + </object> + <int key="connectionID">456</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">orderFrontSubstitutionsPanel:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="65139061"/> + </object> + <int key="connectionID">458</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">toggleAutomaticDashSubstitution:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="672708820"/> + </object> + <int key="connectionID">461</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">toggleAutomaticTextReplacement:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="537092702"/> + </object> + <int key="connectionID">463</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">uppercaseWord:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="1060694897"/> + </object> + <int key="connectionID">464</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">capitalizeWord:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="56570060"/> + </object> + <int key="connectionID">467</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">lowercaseWord:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="879586729"/> + </object> + <int key="connectionID">468</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">pasteAsPlainText:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="82994268"/> + </object> + <int key="connectionID">486</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">performFindPanelAction:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="326711663"/> + </object> + <int key="connectionID">487</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">performFindPanelAction:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="270902937"/> + </object> + <int key="connectionID">488</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">performFindPanelAction:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="159080638"/> + </object> + <int key="connectionID">489</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">showHelp:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="105068016"/> + </object> + <int key="connectionID">493</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">delegate</string> + <reference key="source" ref="1021"/> + <reference key="destination" ref="976324537"/> + </object> + <int key="connectionID">495</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">alignCenter:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="630155264"/> + </object> + <int key="connectionID">518</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">pasteRuler:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="883618387"/> + </object> + <int key="connectionID">519</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">toggleRuler:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="644046920"/> + </object> + <int key="connectionID">520</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">alignRight:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="512868991"/> + </object> + <int key="connectionID">521</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">copyRuler:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="231811626"/> + </object> + <int key="connectionID">522</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">alignJustified:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="945678886"/> + </object> + <int key="connectionID">523</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">alignLeft:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="875092757"/> + </object> + <int key="connectionID">524</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">makeBaseWritingDirectionNatural:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="551969625"/> + </object> + <int key="connectionID">525</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">makeBaseWritingDirectionLeftToRight:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="249532473"/> + </object> + <int key="connectionID">526</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">makeBaseWritingDirectionRightToLeft:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="607364498"/> + </object> + <int key="connectionID">527</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">makeTextWritingDirectionNatural:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="380031999"/> + </object> + <int key="connectionID">528</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">makeTextWritingDirectionLeftToRight:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="825984362"/> + </object> + <int key="connectionID">529</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">makeTextWritingDirectionRightToLeft:</string> + <reference key="source" ref="1014"/> + <reference key="destination" ref="560145579"/> + </object> + <int key="connectionID">530</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">window</string> + <reference key="source" ref="976324537"/> + <reference key="destination" ref="972006081"/> + </object> + <int key="connectionID">532</int> + </object> + </object> + <object class="IBMutableOrderedSet" key="objectRecords"> + <object class="NSArray" key="orderedObjects"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBObjectRecord"> + <int key="objectID">0</int> + <reference key="object" ref="0"/> + <reference key="children" ref="1048"/> + <nil key="parent"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">-2</int> + <reference key="object" ref="1021"/> + <reference key="parent" ref="0"/> + <string key="objectName">File's Owner</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">-1</int> + <reference key="object" ref="1014"/> + <reference key="parent" ref="0"/> + <string key="objectName">First Responder</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">-3</int> + <reference key="object" ref="1050"/> + <reference key="parent" ref="0"/> + <string key="objectName">Application</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">29</int> + <reference key="object" ref="649796088"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="713487014"/> + <reference ref="694149608"/> + <reference ref="952259628"/> + <reference ref="379814623"/> + <reference ref="586577488"/> + <reference ref="302598603"/> + <reference ref="448692316"/> + </object> + <reference key="parent" ref="0"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">19</int> + <reference key="object" ref="713487014"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="835318025"/> + </object> + <reference key="parent" ref="649796088"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">56</int> + <reference key="object" ref="694149608"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="110575045"/> + </object> + <reference key="parent" ref="649796088"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">217</int> + <reference key="object" ref="952259628"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="789758025"/> + </object> + <reference key="parent" ref="649796088"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">83</int> + <reference key="object" ref="379814623"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="720053764"/> + </object> + <reference key="parent" ref="649796088"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">81</int> + <reference key="object" ref="720053764"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="1023925487"/> + <reference ref="117038363"/> + <reference ref="49223823"/> + <reference ref="722745758"/> + <reference ref="705341025"/> + <reference ref="1025936716"/> + <reference ref="294629803"/> + <reference ref="776162233"/> + <reference ref="425164168"/> + <reference ref="579971712"/> + <reference ref="1010469920"/> + </object> + <reference key="parent" ref="379814623"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">75</int> + <reference key="object" ref="1023925487"/> + <reference key="parent" ref="720053764"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">80</int> + <reference key="object" ref="117038363"/> + <reference key="parent" ref="720053764"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">78</int> + <reference key="object" ref="49223823"/> + <reference key="parent" ref="720053764"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">72</int> + <reference key="object" ref="722745758"/> + <reference key="parent" ref="720053764"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">82</int> + <reference key="object" ref="705341025"/> + <reference key="parent" ref="720053764"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">124</int> + <reference key="object" ref="1025936716"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="1065607017"/> + </object> + <reference key="parent" ref="720053764"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">77</int> + <reference key="object" ref="294629803"/> + <reference key="parent" ref="720053764"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">73</int> + <reference key="object" ref="776162233"/> + <reference key="parent" ref="720053764"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">79</int> + <reference key="object" ref="425164168"/> + <reference key="parent" ref="720053764"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">112</int> + <reference key="object" ref="579971712"/> + <reference key="parent" ref="720053764"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">74</int> + <reference key="object" ref="1010469920"/> + <reference key="parent" ref="720053764"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">125</int> + <reference key="object" ref="1065607017"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="759406840"/> + </object> + <reference key="parent" ref="1025936716"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">126</int> + <reference key="object" ref="759406840"/> + <reference key="parent" ref="1065607017"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">205</int> + <reference key="object" ref="789758025"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="437104165"/> + <reference ref="583158037"/> + <reference ref="1058277027"/> + <reference ref="212016141"/> + <reference ref="296257095"/> + <reference ref="29853731"/> + <reference ref="860595796"/> + <reference ref="1040322652"/> + <reference ref="790794224"/> + <reference ref="892235320"/> + <reference ref="972420730"/> + <reference ref="676164635"/> + <reference ref="507821607"/> + <reference ref="288088188"/> + <reference ref="82994268"/> + </object> + <reference key="parent" ref="952259628"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">202</int> + <reference key="object" ref="437104165"/> + <reference key="parent" ref="789758025"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">198</int> + <reference key="object" ref="583158037"/> + <reference key="parent" ref="789758025"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">207</int> + <reference key="object" ref="1058277027"/> + <reference key="parent" ref="789758025"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">214</int> + <reference key="object" ref="212016141"/> + <reference key="parent" ref="789758025"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">199</int> + <reference key="object" ref="296257095"/> + <reference key="parent" ref="789758025"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">203</int> + <reference key="object" ref="29853731"/> + <reference key="parent" ref="789758025"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">197</int> + <reference key="object" ref="860595796"/> + <reference key="parent" ref="789758025"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">206</int> + <reference key="object" ref="1040322652"/> + <reference key="parent" ref="789758025"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">215</int> + <reference key="object" ref="790794224"/> + <reference key="parent" ref="789758025"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">218</int> + <reference key="object" ref="892235320"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="963351320"/> + </object> + <reference key="parent" ref="789758025"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">216</int> + <reference key="object" ref="972420730"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="769623530"/> + </object> + <reference key="parent" ref="789758025"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">200</int> + <reference key="object" ref="769623530"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="948374510"/> + <reference ref="96193923"/> + <reference ref="679648819"/> + <reference ref="967646866"/> + <reference ref="859480356"/> + <reference ref="795346622"/> + </object> + <reference key="parent" ref="972420730"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">219</int> + <reference key="object" ref="948374510"/> + <reference key="parent" ref="769623530"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">201</int> + <reference key="object" ref="96193923"/> + <reference key="parent" ref="769623530"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">204</int> + <reference key="object" ref="679648819"/> + <reference key="parent" ref="769623530"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">220</int> + <reference key="object" ref="963351320"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="270902937"/> + <reference ref="88285865"/> + <reference ref="159080638"/> + <reference ref="326711663"/> + <reference ref="447796847"/> + </object> + <reference key="parent" ref="892235320"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">213</int> + <reference key="object" ref="270902937"/> + <reference key="parent" ref="963351320"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">210</int> + <reference key="object" ref="88285865"/> + <reference key="parent" ref="963351320"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">221</int> + <reference key="object" ref="159080638"/> + <reference key="parent" ref="963351320"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">208</int> + <reference key="object" ref="326711663"/> + <reference key="parent" ref="963351320"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">209</int> + <reference key="object" ref="447796847"/> + <reference key="parent" ref="963351320"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">57</int> + <reference key="object" ref="110575045"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="238522557"/> + <reference ref="755159360"/> + <reference ref="908899353"/> + <reference ref="632727374"/> + <reference ref="646227648"/> + <reference ref="609285721"/> + <reference ref="481834944"/> + <reference ref="304266470"/> + <reference ref="1046388886"/> + <reference ref="1056857174"/> + <reference ref="342932134"/> + </object> + <reference key="parent" ref="694149608"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">58</int> + <reference key="object" ref="238522557"/> + <reference key="parent" ref="110575045"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">134</int> + <reference key="object" ref="755159360"/> + <reference key="parent" ref="110575045"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">150</int> + <reference key="object" ref="908899353"/> + <reference key="parent" ref="110575045"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">136</int> + <reference key="object" ref="632727374"/> + <reference key="parent" ref="110575045"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">144</int> + <reference key="object" ref="646227648"/> + <reference key="parent" ref="110575045"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">129</int> + <reference key="object" ref="609285721"/> + <reference key="parent" ref="110575045"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">143</int> + <reference key="object" ref="481834944"/> + <reference key="parent" ref="110575045"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">236</int> + <reference key="object" ref="304266470"/> + <reference key="parent" ref="110575045"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">131</int> + <reference key="object" ref="1046388886"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="752062318"/> + </object> + <reference key="parent" ref="110575045"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">149</int> + <reference key="object" ref="1056857174"/> + <reference key="parent" ref="110575045"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">145</int> + <reference key="object" ref="342932134"/> + <reference key="parent" ref="110575045"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">130</int> + <reference key="object" ref="752062318"/> + <reference key="parent" ref="1046388886"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">24</int> + <reference key="object" ref="835318025"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="299356726"/> + <reference ref="625202149"/> + <reference ref="575023229"/> + <reference ref="1011231497"/> + </object> + <reference key="parent" ref="713487014"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">92</int> + <reference key="object" ref="299356726"/> + <reference key="parent" ref="835318025"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">5</int> + <reference key="object" ref="625202149"/> + <reference key="parent" ref="835318025"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">239</int> + <reference key="object" ref="575023229"/> + <reference key="parent" ref="835318025"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">23</int> + <reference key="object" ref="1011231497"/> + <reference key="parent" ref="835318025"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">295</int> + <reference key="object" ref="586577488"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="466310130"/> + </object> + <reference key="parent" ref="649796088"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">296</int> + <reference key="object" ref="466310130"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="102151532"/> + <reference ref="237841660"/> + </object> + <reference key="parent" ref="586577488"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">297</int> + <reference key="object" ref="102151532"/> + <reference key="parent" ref="466310130"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">298</int> + <reference key="object" ref="237841660"/> + <reference key="parent" ref="466310130"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">211</int> + <reference key="object" ref="676164635"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="785027613"/> + </object> + <reference key="parent" ref="789758025"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">212</int> + <reference key="object" ref="785027613"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="680220178"/> + <reference ref="731782645"/> + </object> + <reference key="parent" ref="676164635"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">195</int> + <reference key="object" ref="680220178"/> + <reference key="parent" ref="785027613"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">196</int> + <reference key="object" ref="731782645"/> + <reference key="parent" ref="785027613"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">346</int> + <reference key="object" ref="967646866"/> + <reference key="parent" ref="769623530"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">348</int> + <reference key="object" ref="507821607"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="698887838"/> + </object> + <reference key="parent" ref="789758025"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">349</int> + <reference key="object" ref="698887838"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="605118523"/> + <reference ref="197661976"/> + <reference ref="708854459"/> + <reference ref="65139061"/> + <reference ref="19036812"/> + <reference ref="672708820"/> + <reference ref="537092702"/> + </object> + <reference key="parent" ref="507821607"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">350</int> + <reference key="object" ref="605118523"/> + <reference key="parent" ref="698887838"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">351</int> + <reference key="object" ref="197661976"/> + <reference key="parent" ref="698887838"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">354</int> + <reference key="object" ref="708854459"/> + <reference key="parent" ref="698887838"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">371</int> + <reference key="object" ref="972006081"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="439893737"/> + </object> + <reference key="parent" ref="0"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">372</int> + <reference key="object" ref="439893737"/> + <reference key="parent" ref="972006081"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">375</int> + <reference key="object" ref="302598603"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="941447902"/> + </object> + <reference key="parent" ref="649796088"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">376</int> + <reference key="object" ref="941447902"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="792887677"/> + <reference ref="215659978"/> + </object> + <reference key="parent" ref="302598603"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">377</int> + <reference key="object" ref="792887677"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="786677654"/> + </object> + <reference key="parent" ref="941447902"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">388</int> + <reference key="object" ref="786677654"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="159677712"/> + <reference ref="305399458"/> + <reference ref="814362025"/> + <reference ref="330926929"/> + <reference ref="533507878"/> + <reference ref="158063935"/> + <reference ref="885547335"/> + <reference ref="901062459"/> + <reference ref="767671776"/> + <reference ref="691570813"/> + <reference ref="769124883"/> + <reference ref="739652853"/> + <reference ref="1012600125"/> + <reference ref="214559597"/> + <reference ref="596732606"/> + <reference ref="393423671"/> + </object> + <reference key="parent" ref="792887677"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">389</int> + <reference key="object" ref="159677712"/> + <reference key="parent" ref="786677654"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">390</int> + <reference key="object" ref="305399458"/> + <reference key="parent" ref="786677654"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">391</int> + <reference key="object" ref="814362025"/> + <reference key="parent" ref="786677654"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">392</int> + <reference key="object" ref="330926929"/> + <reference key="parent" ref="786677654"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">393</int> + <reference key="object" ref="533507878"/> + <reference key="parent" ref="786677654"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">394</int> + <reference key="object" ref="158063935"/> + <reference key="parent" ref="786677654"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">395</int> + <reference key="object" ref="885547335"/> + <reference key="parent" ref="786677654"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">396</int> + <reference key="object" ref="901062459"/> + <reference key="parent" ref="786677654"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">397</int> + <reference key="object" ref="767671776"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="175441468"/> + </object> + <reference key="parent" ref="786677654"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">398</int> + <reference key="object" ref="691570813"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="1058217995"/> + </object> + <reference key="parent" ref="786677654"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">399</int> + <reference key="object" ref="769124883"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="18263474"/> + </object> + <reference key="parent" ref="786677654"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">400</int> + <reference key="object" ref="739652853"/> + <reference key="parent" ref="786677654"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">401</int> + <reference key="object" ref="1012600125"/> + <reference key="parent" ref="786677654"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">402</int> + <reference key="object" ref="214559597"/> + <reference key="parent" ref="786677654"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">403</int> + <reference key="object" ref="596732606"/> + <reference key="parent" ref="786677654"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">404</int> + <reference key="object" ref="393423671"/> + <reference key="parent" ref="786677654"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">405</int> + <reference key="object" ref="18263474"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="257962622"/> + <reference ref="644725453"/> + <reference ref="1037576581"/> + <reference ref="941806246"/> + <reference ref="1045724900"/> + </object> + <reference key="parent" ref="769124883"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">406</int> + <reference key="object" ref="257962622"/> + <reference key="parent" ref="18263474"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">407</int> + <reference key="object" ref="644725453"/> + <reference key="parent" ref="18263474"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">408</int> + <reference key="object" ref="1037576581"/> + <reference key="parent" ref="18263474"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">409</int> + <reference key="object" ref="941806246"/> + <reference key="parent" ref="18263474"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">410</int> + <reference key="object" ref="1045724900"/> + <reference key="parent" ref="18263474"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">411</int> + <reference key="object" ref="1058217995"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="706297211"/> + <reference ref="568384683"/> + <reference ref="663508465"/> + </object> + <reference key="parent" ref="691570813"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">412</int> + <reference key="object" ref="706297211"/> + <reference key="parent" ref="1058217995"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">413</int> + <reference key="object" ref="568384683"/> + <reference key="parent" ref="1058217995"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">414</int> + <reference key="object" ref="663508465"/> + <reference key="parent" ref="1058217995"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">415</int> + <reference key="object" ref="175441468"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="252969304"/> + <reference ref="766922938"/> + <reference ref="677519740"/> + <reference ref="238351151"/> + </object> + <reference key="parent" ref="767671776"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">416</int> + <reference key="object" ref="252969304"/> + <reference key="parent" ref="175441468"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">417</int> + <reference key="object" ref="766922938"/> + <reference key="parent" ref="175441468"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">418</int> + <reference key="object" ref="677519740"/> + <reference key="parent" ref="175441468"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">419</int> + <reference key="object" ref="238351151"/> + <reference key="parent" ref="175441468"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">420</int> + <reference key="object" ref="755631768"/> + <reference key="parent" ref="0"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">450</int> + <reference key="object" ref="288088188"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="579392910"/> + </object> + <reference key="parent" ref="789758025"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">451</int> + <reference key="object" ref="579392910"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="1060694897"/> + <reference ref="879586729"/> + <reference ref="56570060"/> + </object> + <reference key="parent" ref="288088188"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">452</int> + <reference key="object" ref="1060694897"/> + <reference key="parent" ref="579392910"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">453</int> + <reference key="object" ref="859480356"/> + <reference key="parent" ref="769623530"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">454</int> + <reference key="object" ref="795346622"/> + <reference key="parent" ref="769623530"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">457</int> + <reference key="object" ref="65139061"/> + <reference key="parent" ref="698887838"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">459</int> + <reference key="object" ref="19036812"/> + <reference key="parent" ref="698887838"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">460</int> + <reference key="object" ref="672708820"/> + <reference key="parent" ref="698887838"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">462</int> + <reference key="object" ref="537092702"/> + <reference key="parent" ref="698887838"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">465</int> + <reference key="object" ref="879586729"/> + <reference key="parent" ref="579392910"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">466</int> + <reference key="object" ref="56570060"/> + <reference key="parent" ref="579392910"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">485</int> + <reference key="object" ref="82994268"/> + <reference key="parent" ref="789758025"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">490</int> + <reference key="object" ref="448692316"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="992780483"/> + </object> + <reference key="parent" ref="649796088"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">491</int> + <reference key="object" ref="992780483"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="105068016"/> + </object> + <reference key="parent" ref="448692316"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">492</int> + <reference key="object" ref="105068016"/> + <reference key="parent" ref="992780483"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">494</int> + <reference key="object" ref="976324537"/> + <reference key="parent" ref="0"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">496</int> + <reference key="object" ref="215659978"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="446991534"/> + </object> + <reference key="parent" ref="941447902"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">497</int> + <reference key="object" ref="446991534"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="875092757"/> + <reference ref="630155264"/> + <reference ref="945678886"/> + <reference ref="512868991"/> + <reference ref="163117631"/> + <reference ref="31516759"/> + <reference ref="908105787"/> + <reference ref="644046920"/> + <reference ref="231811626"/> + <reference ref="883618387"/> + </object> + <reference key="parent" ref="215659978"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">498</int> + <reference key="object" ref="875092757"/> + <reference key="parent" ref="446991534"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">499</int> + <reference key="object" ref="630155264"/> + <reference key="parent" ref="446991534"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">500</int> + <reference key="object" ref="945678886"/> + <reference key="parent" ref="446991534"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">501</int> + <reference key="object" ref="512868991"/> + <reference key="parent" ref="446991534"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">502</int> + <reference key="object" ref="163117631"/> + <reference key="parent" ref="446991534"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">503</int> + <reference key="object" ref="31516759"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="956096989"/> + </object> + <reference key="parent" ref="446991534"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">504</int> + <reference key="object" ref="908105787"/> + <reference key="parent" ref="446991534"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">505</int> + <reference key="object" ref="644046920"/> + <reference key="parent" ref="446991534"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">506</int> + <reference key="object" ref="231811626"/> + <reference key="parent" ref="446991534"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">507</int> + <reference key="object" ref="883618387"/> + <reference key="parent" ref="446991534"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">508</int> + <reference key="object" ref="956096989"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="257099033"/> + <reference ref="551969625"/> + <reference ref="249532473"/> + <reference ref="607364498"/> + <reference ref="508151438"/> + <reference ref="981751889"/> + <reference ref="380031999"/> + <reference ref="825984362"/> + <reference ref="560145579"/> + </object> + <reference key="parent" ref="31516759"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">509</int> + <reference key="object" ref="257099033"/> + <reference key="parent" ref="956096989"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">510</int> + <reference key="object" ref="551969625"/> + <reference key="parent" ref="956096989"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">511</int> + <reference key="object" ref="249532473"/> + <reference key="parent" ref="956096989"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">512</int> + <reference key="object" ref="607364498"/> + <reference key="parent" ref="956096989"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">513</int> + <reference key="object" ref="508151438"/> + <reference key="parent" ref="956096989"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">514</int> + <reference key="object" ref="981751889"/> + <reference key="parent" ref="956096989"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">515</int> + <reference key="object" ref="380031999"/> + <reference key="parent" ref="956096989"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">516</int> + <reference key="object" ref="825984362"/> + <reference key="parent" ref="956096989"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">517</int> + <reference key="object" ref="560145579"/> + <reference key="parent" ref="956096989"/> + </object> + </object> + </object> + <object class="NSMutableDictionary" key="flattenedProperties"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>-3.IBPluginDependency</string> + <string>112.IBPluginDependency</string> + <string>112.ImportedFromIB2</string> + <string>124.IBPluginDependency</string> + <string>124.ImportedFromIB2</string> + <string>125.IBPluginDependency</string> + <string>125.ImportedFromIB2</string> + <string>125.editorWindowContentRectSynchronizationRect</string> + <string>126.IBPluginDependency</string> + <string>126.ImportedFromIB2</string> + <string>129.IBPluginDependency</string> + <string>129.ImportedFromIB2</string> + <string>130.IBPluginDependency</string> + <string>130.ImportedFromIB2</string> + <string>130.editorWindowContentRectSynchronizationRect</string> + <string>131.IBPluginDependency</string> + <string>131.ImportedFromIB2</string> + <string>134.IBPluginDependency</string> + <string>134.ImportedFromIB2</string> + <string>136.IBPluginDependency</string> + <string>136.ImportedFromIB2</string> + <string>143.IBPluginDependency</string> + <string>143.ImportedFromIB2</string> + <string>144.IBPluginDependency</string> + <string>144.ImportedFromIB2</string> + <string>145.IBPluginDependency</string> + <string>145.ImportedFromIB2</string> + <string>149.IBPluginDependency</string> + <string>149.ImportedFromIB2</string> + <string>150.IBPluginDependency</string> + <string>150.ImportedFromIB2</string> + <string>19.IBPluginDependency</string> + <string>19.ImportedFromIB2</string> + <string>195.IBPluginDependency</string> + <string>195.ImportedFromIB2</string> + <string>196.IBPluginDependency</string> + <string>196.ImportedFromIB2</string> + <string>197.IBPluginDependency</string> + <string>197.ImportedFromIB2</string> + <string>198.IBPluginDependency</string> + <string>198.ImportedFromIB2</string> + <string>199.IBPluginDependency</string> + <string>199.ImportedFromIB2</string> + <string>200.IBEditorWindowLastContentRect</string> + <string>200.IBPluginDependency</string> + <string>200.ImportedFromIB2</string> + <string>200.editorWindowContentRectSynchronizationRect</string> + <string>201.IBPluginDependency</string> + <string>201.ImportedFromIB2</string> + <string>202.IBPluginDependency</string> + <string>202.ImportedFromIB2</string> + <string>203.IBPluginDependency</string> + <string>203.ImportedFromIB2</string> + <string>204.IBPluginDependency</string> + <string>204.ImportedFromIB2</string> + <string>205.IBEditorWindowLastContentRect</string> + <string>205.IBPluginDependency</string> + <string>205.ImportedFromIB2</string> + <string>205.editorWindowContentRectSynchronizationRect</string> + <string>206.IBPluginDependency</string> + <string>206.ImportedFromIB2</string> + <string>207.IBPluginDependency</string> + <string>207.ImportedFromIB2</string> + <string>208.IBPluginDependency</string> + <string>208.ImportedFromIB2</string> + <string>209.IBPluginDependency</string> + <string>209.ImportedFromIB2</string> + <string>210.IBPluginDependency</string> + <string>210.ImportedFromIB2</string> + <string>211.IBPluginDependency</string> + <string>211.ImportedFromIB2</string> + <string>212.IBPluginDependency</string> + <string>212.ImportedFromIB2</string> + <string>212.editorWindowContentRectSynchronizationRect</string> + <string>213.IBPluginDependency</string> + <string>213.ImportedFromIB2</string> + <string>214.IBPluginDependency</string> + <string>214.ImportedFromIB2</string> + <string>215.IBPluginDependency</string> + <string>215.ImportedFromIB2</string> + <string>216.IBPluginDependency</string> + <string>216.ImportedFromIB2</string> + <string>217.IBPluginDependency</string> + <string>217.ImportedFromIB2</string> + <string>218.IBPluginDependency</string> + <string>218.ImportedFromIB2</string> + <string>219.IBPluginDependency</string> + <string>219.ImportedFromIB2</string> + <string>220.IBEditorWindowLastContentRect</string> + <string>220.IBPluginDependency</string> + <string>220.ImportedFromIB2</string> + <string>220.editorWindowContentRectSynchronizationRect</string> + <string>221.IBPluginDependency</string> + <string>221.ImportedFromIB2</string> + <string>23.IBPluginDependency</string> + <string>23.ImportedFromIB2</string> + <string>236.IBPluginDependency</string> + <string>236.ImportedFromIB2</string> + <string>239.IBPluginDependency</string> + <string>239.ImportedFromIB2</string> + <string>24.IBEditorWindowLastContentRect</string> + <string>24.IBPluginDependency</string> + <string>24.ImportedFromIB2</string> + <string>24.editorWindowContentRectSynchronizationRect</string> + <string>29.IBEditorWindowLastContentRect</string> + <string>29.IBPluginDependency</string> + <string>29.ImportedFromIB2</string> + <string>29.WindowOrigin</string> + <string>29.editorWindowContentRectSynchronizationRect</string> + <string>295.IBPluginDependency</string> + <string>296.IBEditorWindowLastContentRect</string> + <string>296.IBPluginDependency</string> + <string>296.editorWindowContentRectSynchronizationRect</string> + <string>297.IBPluginDependency</string> + <string>298.IBPluginDependency</string> + <string>346.IBPluginDependency</string> + <string>346.ImportedFromIB2</string> + <string>348.IBPluginDependency</string> + <string>348.ImportedFromIB2</string> + <string>349.IBEditorWindowLastContentRect</string> + <string>349.IBPluginDependency</string> + <string>349.ImportedFromIB2</string> + <string>349.editorWindowContentRectSynchronizationRect</string> + <string>350.IBPluginDependency</string> + <string>350.ImportedFromIB2</string> + <string>351.IBPluginDependency</string> + <string>351.ImportedFromIB2</string> + <string>354.IBPluginDependency</string> + <string>354.ImportedFromIB2</string> + <string>371.IBEditorWindowLastContentRect</string> + <string>371.IBPluginDependency</string> + <string>371.IBWindowTemplateEditedContentRect</string> + <string>371.NSWindowTemplate.visibleAtLaunch</string> + <string>371.editorWindowContentRectSynchronizationRect</string> + <string>371.windowTemplate.maxSize</string> + <string>372.IBPluginDependency</string> + <string>375.IBPluginDependency</string> + <string>376.IBEditorWindowLastContentRect</string> + <string>376.IBPluginDependency</string> + <string>377.IBPluginDependency</string> + <string>388.IBEditorWindowLastContentRect</string> + <string>388.IBPluginDependency</string> + <string>389.IBPluginDependency</string> + <string>390.IBPluginDependency</string> + <string>391.IBPluginDependency</string> + <string>392.IBPluginDependency</string> + <string>393.IBPluginDependency</string> + <string>394.IBPluginDependency</string> + <string>395.IBPluginDependency</string> + <string>396.IBPluginDependency</string> + <string>397.IBPluginDependency</string> + <string>398.IBPluginDependency</string> + <string>399.IBPluginDependency</string> + <string>400.IBPluginDependency</string> + <string>401.IBPluginDependency</string> + <string>402.IBPluginDependency</string> + <string>403.IBPluginDependency</string> + <string>404.IBPluginDependency</string> + <string>405.IBPluginDependency</string> + <string>406.IBPluginDependency</string> + <string>407.IBPluginDependency</string> + <string>408.IBPluginDependency</string> + <string>409.IBPluginDependency</string> + <string>410.IBPluginDependency</string> + <string>411.IBPluginDependency</string> + <string>412.IBPluginDependency</string> + <string>413.IBPluginDependency</string> + <string>414.IBPluginDependency</string> + <string>415.IBPluginDependency</string> + <string>416.IBPluginDependency</string> + <string>417.IBPluginDependency</string> + <string>418.IBPluginDependency</string> + <string>419.IBPluginDependency</string> + <string>450.IBPluginDependency</string> + <string>451.IBEditorWindowLastContentRect</string> + <string>451.IBPluginDependency</string> + <string>452.IBPluginDependency</string> + <string>453.IBPluginDependency</string> + <string>454.IBPluginDependency</string> + <string>457.IBPluginDependency</string> + <string>459.IBPluginDependency</string> + <string>460.IBPluginDependency</string> + <string>462.IBPluginDependency</string> + <string>465.IBPluginDependency</string> + <string>466.IBPluginDependency</string> + <string>485.IBPluginDependency</string> + <string>490.IBPluginDependency</string> + <string>491.IBEditorWindowLastContentRect</string> + <string>491.IBPluginDependency</string> + <string>492.IBPluginDependency</string> + <string>496.IBPluginDependency</string> + <string>497.IBEditorWindowLastContentRect</string> + <string>497.IBPluginDependency</string> + <string>498.IBPluginDependency</string> + <string>499.IBPluginDependency</string> + <string>5.IBPluginDependency</string> + <string>5.ImportedFromIB2</string> + <string>500.IBPluginDependency</string> + <string>501.IBPluginDependency</string> + <string>502.IBPluginDependency</string> + <string>503.IBPluginDependency</string> + <string>504.IBPluginDependency</string> + <string>505.IBPluginDependency</string> + <string>506.IBPluginDependency</string> + <string>507.IBPluginDependency</string> + <string>508.IBEditorWindowLastContentRect</string> + <string>508.IBPluginDependency</string> + <string>509.IBPluginDependency</string> + <string>510.IBPluginDependency</string> + <string>511.IBPluginDependency</string> + <string>512.IBPluginDependency</string> + <string>513.IBPluginDependency</string> + <string>514.IBPluginDependency</string> + <string>515.IBPluginDependency</string> + <string>516.IBPluginDependency</string> + <string>517.IBPluginDependency</string> + <string>56.IBPluginDependency</string> + <string>56.ImportedFromIB2</string> + <string>57.IBEditorWindowLastContentRect</string> + <string>57.IBPluginDependency</string> + <string>57.ImportedFromIB2</string> + <string>57.editorWindowContentRectSynchronizationRect</string> + <string>58.IBPluginDependency</string> + <string>58.ImportedFromIB2</string> + <string>72.IBPluginDependency</string> + <string>72.ImportedFromIB2</string> + <string>73.IBPluginDependency</string> + <string>73.ImportedFromIB2</string> + <string>74.IBPluginDependency</string> + <string>74.ImportedFromIB2</string> + <string>75.IBPluginDependency</string> + <string>75.ImportedFromIB2</string> + <string>77.IBPluginDependency</string> + <string>77.ImportedFromIB2</string> + <string>78.IBPluginDependency</string> + <string>78.ImportedFromIB2</string> + <string>79.IBPluginDependency</string> + <string>79.ImportedFromIB2</string> + <string>80.IBPluginDependency</string> + <string>80.ImportedFromIB2</string> + <string>81.IBEditorWindowLastContentRect</string> + <string>81.IBPluginDependency</string> + <string>81.ImportedFromIB2</string> + <string>81.editorWindowContentRectSynchronizationRect</string> + <string>82.IBPluginDependency</string> + <string>82.ImportedFromIB2</string> + <string>83.IBPluginDependency</string> + <string>83.ImportedFromIB2</string> + <string>92.IBPluginDependency</string> + <string>92.ImportedFromIB2</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>{{522, 812}, {146, 23}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>{{436, 809}, {64, 6}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>{{753, 187}, {275, 113}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>{{608, 612}, {275, 83}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>{{547, 180}, {254, 283}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>{{187, 434}, {243, 243}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>{{608, 612}, {167, 43}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>{{753, 217}, {238, 103}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>{{608, 612}, {241, 103}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>{{654, 239}, {194, 73}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>{{525, 802}, {197, 73}}</string> + <string>{{380, 836}, {512, 20}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>{74, 862}</string> + <string>{{6, 978}, {478, 20}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>{{604, 269}, {231, 43}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>{{475, 832}, {234, 43}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>{{746, 287}, {220, 133}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>{{608, 612}, {215, 63}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>{{380, 496}, {480, 360}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>{{380, 496}, {480, 360}}</string> + <integer value="1"/> + <string>{{33, 99}, {480, 360}}</string> + <string>{3.40282e+38, 3.40282e+38}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>{{591, 420}, {83, 43}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>{{523, 2}, {178, 283}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>{{753, 197}, {170, 63}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>{{725, 289}, {246, 23}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>{{674, 260}, {204, 183}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>{{878, 180}, {164, 173}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>{{286, 129}, {275, 183}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>{{23, 794}, {245, 183}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>{{452, 109}, {196, 203}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>{{145, 474}, {199, 203}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <integer value="1"/> + </object> + </object> + <object class="NSMutableDictionary" key="unlocalizedProperties"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference key="dict.sortedKeys" ref="0"/> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + </object> + <nil key="activeLocalization"/> + <object class="NSMutableDictionary" key="localizations"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference key="dict.sortedKeys" ref="0"/> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + </object> + <nil key="sourceID"/> + <int key="maxID">532</int> + </object> + <object class="IBClassDescriber" key="IBDocument.Classes"> + <object class="NSMutableArray" key="referencedPartialClassDescriptions"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBPartialClassDescription"> + <string key="className">TestAppAppDelegate</string> + <string key="superclassName">NSObject</string> + <object class="NSMutableDictionary" key="outlets"> + <string key="NS.key.0">window</string> + <string key="NS.object.0">NSWindow</string> + </object> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">TestAppAppDelegate.h</string> + </object> + </object> + </object> + <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBPartialClassDescription"> + <string key="className">NSApplication</string> + <string key="superclassName">NSResponder</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier" id="822405504"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSApplication.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSApplication</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier" id="850738725"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSApplicationScripting.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSApplication</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier" id="624831158"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSColorPanel.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSApplication</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSHelpManager.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSApplication</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSPageLayout.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSApplication</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSUserInterfaceItemSearching.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSBrowser</string> + <string key="superclassName">NSControl</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSBrowser.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSControl</string> + <string key="superclassName">NSView</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier" id="310914472"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSControl.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSDocument</string> + <string key="superclassName">NSObject</string> + <object class="NSMutableDictionary" key="actions"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>printDocument:</string> + <string>revertDocumentToSaved:</string> + <string>runPageLayout:</string> + <string>saveDocument:</string> + <string>saveDocumentAs:</string> + <string>saveDocumentTo:</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>id</string> + <string>id</string> + <string>id</string> + <string>id</string> + <string>id</string> + <string>id</string> + </object> + </object> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSDocument.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSDocument</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSDocumentScripting.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSDocumentController</string> + <string key="superclassName">NSObject</string> + <object class="NSMutableDictionary" key="actions"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>clearRecentDocuments:</string> + <string>newDocument:</string> + <string>openDocument:</string> + <string>saveAllDocuments:</string> + </object> + <object class="NSMutableArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>id</string> + <string>id</string> + <string>id</string> + <string>id</string> + </object> + </object> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSDocumentController.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSFontManager</string> + <string key="superclassName">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier" id="946436764"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSFontManager.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSFormatter</string> + <string key="superclassName">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSFormatter.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSMatrix</string> + <string key="superclassName">NSControl</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSMatrix.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSMenu</string> + <string key="superclassName">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier" id="1056362899"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSMenu.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSMenuItem</string> + <string key="superclassName">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier" id="472958451"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSMenuItem.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSMovieView</string> + <string key="superclassName">NSView</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSMovieView.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSAccessibility.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <reference key="sourceIdentifier" ref="822405504"/> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <reference key="sourceIdentifier" ref="850738725"/> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <reference key="sourceIdentifier" ref="624831158"/> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <reference key="sourceIdentifier" ref="310914472"/> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSDictionaryController.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSDragging.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <reference key="sourceIdentifier" ref="946436764"/> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSFontPanel.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSKeyValueBinding.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <reference key="sourceIdentifier" ref="1056362899"/> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSNibLoading.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSOutlineView.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSPasteboard.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSSavePanel.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier" id="809545482"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSTableView.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSToolbarItem.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier" id="260078765"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSView.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSArchiver.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSClassDescription.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSError.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSObject.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSObjectScripting.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSPortCoder.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSScriptClassDescription.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSScriptKeyValueCoding.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSScriptObjectSpecifiers.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSScriptWhoseTests.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSThread.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSURL.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">Foundation.framework/Headers/NSURLDownload.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSResponder</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSInterfaceStyle.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSResponder</string> + <string key="superclassName">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSResponder.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSTableView</string> + <string key="superclassName">NSControl</string> + <reference key="sourceIdentifier" ref="809545482"/> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSText</string> + <string key="superclassName">NSView</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSText.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSTextView</string> + <string key="superclassName">NSText</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSTextView.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSView</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSClipView.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSView</string> + <reference key="sourceIdentifier" ref="472958451"/> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSView</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSRulerView.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSView</string> + <string key="superclassName">NSResponder</string> + <reference key="sourceIdentifier" ref="260078765"/> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSWindow</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSDrawer.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSWindow</string> + <string key="superclassName">NSResponder</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSWindow.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSWindow</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBFrameworkSource</string> + <string key="minorKey">AppKit.framework/Headers/NSWindowScripting.h</string> + </object> + </object> + </object> + </object> + <int key="IBDocument.localizationMode">0</int> + <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults"> + <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string> + <integer value="1060" key="NS.object.0"/> + </object> + <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies"> + <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string> + <integer value="3000" key="NS.object.0"/> + </object> + <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool> + <string key="IBDocument.LastKnownRelativeProjectPath">../TestApp.xcodeproj</string> + <int key="IBDocument.defaultPropertyAccessControl">3</int> + </data> +</archive> diff --git a/tools/gyp/test/mac/app-bundle/TestApp/TestApp-Info.plist b/tools/gyp/test/mac/app-bundle/TestApp/TestApp-Info.plist new file mode 100644 index 00000000000..98fd5152000 --- /dev/null +++ b/tools/gyp/test/mac/app-bundle/TestApp/TestApp-Info.plist @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIconFile</key> + <string></string> + <key>CFBundleIdentifier</key> + <string>com.google.${PRODUCT_NAME}</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1</string> + <key>LSMinimumSystemVersion</key> + <string>${MACOSX_DEPLOYMENT_TARGET}</string> + <key>NSMainNibFile</key> + <string>MainMenu</string> + <key>NSPrincipalClass</key> + <string>NSApplication</string> +</dict> +</plist> diff --git a/tools/gyp/test/mac/app-bundle/TestApp/TestAppAppDelegate.h b/tools/gyp/test/mac/app-bundle/TestApp/TestAppAppDelegate.h new file mode 100644 index 00000000000..518645eae9d --- /dev/null +++ b/tools/gyp/test/mac/app-bundle/TestApp/TestAppAppDelegate.h @@ -0,0 +1,13 @@ +// 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 <Cocoa/Cocoa.h> + +@interface TestAppAppDelegate : NSObject <NSApplicationDelegate> { + NSWindow *window; +} + +@property (assign) IBOutlet NSWindow *window; + +@end diff --git a/tools/gyp/test/mac/app-bundle/TestApp/TestAppAppDelegate.m b/tools/gyp/test/mac/app-bundle/TestApp/TestAppAppDelegate.m new file mode 100644 index 00000000000..9aafa420008 --- /dev/null +++ b/tools/gyp/test/mac/app-bundle/TestApp/TestAppAppDelegate.m @@ -0,0 +1,15 @@ +// 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 "TestAppAppDelegate.h" + +@implementation TestAppAppDelegate + +@synthesize window; + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +@end diff --git a/tools/gyp/test/mac/app-bundle/TestApp/main.m b/tools/gyp/test/mac/app-bundle/TestApp/main.m new file mode 100644 index 00000000000..df6a12d065b --- /dev/null +++ b/tools/gyp/test/mac/app-bundle/TestApp/main.m @@ -0,0 +1,10 @@ +// 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 <Cocoa/Cocoa.h> + +int main(int argc, char *argv[]) +{ + return NSApplicationMain(argc, (const char **) argv); +} diff --git a/tools/gyp/test/mac/app-bundle/empty.c b/tools/gyp/test/mac/app-bundle/empty.c new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/tools/gyp/test/mac/app-bundle/empty.c diff --git a/tools/gyp/test/mac/app-bundle/test.gyp b/tools/gyp/test/mac/app-bundle/test.gyp new file mode 100644 index 00000000000..f51c7b4b677 --- /dev/null +++ b/tools/gyp/test/mac/app-bundle/test.gyp @@ -0,0 +1,39 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'targets': [ + { + 'target_name': 'dep_framework', + 'product_name': 'Dependency Framework', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'empty.c', ], + }, + { + 'target_name': 'test_app', + 'product_name': 'Test App Gyp', + 'type': 'executable', + 'mac_bundle': 1, + 'dependencies': [ 'dep_framework', ], + 'sources': [ + 'TestApp/main.m', + 'TestApp/TestApp_Prefix.pch', + 'TestApp/TestAppAppDelegate.h', + 'TestApp/TestAppAppDelegate.m', + ], + 'mac_bundle_resources': [ + 'TestApp/English.lproj/InfoPlist.strings', + 'TestApp/English.lproj/MainMenu.xib', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Cocoa.framework', + ], + }, + 'xcode_settings': { + 'INFOPLIST_FILE': 'TestApp/TestApp-Info.plist', + }, + }, + ], +} diff --git a/tools/gyp/test/mac/debuginfo/file.c b/tools/gyp/test/mac/debuginfo/file.c new file mode 100644 index 00000000000..9cddaf1b0b4 --- /dev/null +++ b/tools/gyp/test/mac/debuginfo/file.c @@ -0,0 +1,6 @@ +// 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. + +void f() {} +int main() {} diff --git a/tools/gyp/test/mac/debuginfo/test.gyp b/tools/gyp/test/mac/debuginfo/test.gyp new file mode 100644 index 00000000000..3faf6b5c76e --- /dev/null +++ b/tools/gyp/test/mac/debuginfo/test.gyp @@ -0,0 +1,82 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'targets': [ + { + 'target_name': 'nonbundle_static_library', + 'type': 'static_library', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym', + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + }, + }, + { + 'target_name': 'nonbundle_shared_library', + 'type': 'shared_library', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym', + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + }, + }, + { + 'target_name': 'nonbundle_loadable_module', + 'type': 'loadable_module', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym', + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + }, + }, + { + 'target_name': 'nonbundle_executable', + 'type': 'executable', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym', + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + }, + }, + + { + 'target_name': 'bundle_shared_library', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym', + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + }, + }, + { + 'target_name': 'bundle_loadable_module', + 'type': 'loadable_module', + 'mac_bundle': 1, + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym', + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + }, + }, + { + 'target_name': 'my_app', + 'product_name': 'My App', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym', + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + }, + }, + ], +} diff --git a/tools/gyp/test/mac/framework/TestFramework/English.lproj/InfoPlist.strings b/tools/gyp/test/mac/framework/TestFramework/English.lproj/InfoPlist.strings new file mode 100644 index 00000000000..88f65cf6eab --- /dev/null +++ b/tools/gyp/test/mac/framework/TestFramework/English.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/tools/gyp/test/mac/framework/TestFramework/Info.plist b/tools/gyp/test/mac/framework/TestFramework/Info.plist new file mode 100644 index 00000000000..5e05a5190c8 --- /dev/null +++ b/tools/gyp/test/mac/framework/TestFramework/Info.plist @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIconFile</key> + <string></string> + <key>CFBundleIdentifier</key> + <string>com.yourcompany.${PRODUCT_NAME}</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>FMWK</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1</string> + <key>NSPrincipalClass</key> + <string></string> +</dict> +</plist> diff --git a/tools/gyp/test/mac/framework/TestFramework/ObjCVector.h b/tools/gyp/test/mac/framework/TestFramework/ObjCVector.h new file mode 100644 index 00000000000..c2450960cd2 --- /dev/null +++ b/tools/gyp/test/mac/framework/TestFramework/ObjCVector.h @@ -0,0 +1,28 @@ +// 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 <Cocoa/Cocoa.h> + +#ifdef __cplusplus +struct ObjCVectorImp; +#else +typedef struct _ObjCVectorImpT ObjCVectorImp; +#endif + +@interface ObjCVector : NSObject { + @private + ObjCVectorImp* imp_; +} + +- (id)init; + +- (void)addObject:(id)obj; +- (void)addObject:(id)obj atIndex:(NSUInteger)index; + +- (void)removeObject:(id)obj; +- (void)removeObjectAtIndex:(NSUInteger)index; + +- (id)objectAtIndex:(NSUInteger)index; + +@end diff --git a/tools/gyp/test/mac/framework/TestFramework/ObjCVector.mm b/tools/gyp/test/mac/framework/TestFramework/ObjCVector.mm new file mode 100644 index 00000000000..cbf431f28d4 --- /dev/null +++ b/tools/gyp/test/mac/framework/TestFramework/ObjCVector.mm @@ -0,0 +1,63 @@ +// 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 "ObjCVectorInternal.h" +#import "ObjCVector.h" + +#include <vector> + +@interface ObjCVector (Private) +- (std::vector<id>::iterator)makeIterator:(NSUInteger)index; +@end + +@implementation ObjCVector + +- (id)init { + if ((self = [super init])) { + imp_ = new ObjCVectorImp(); + } + return self; +} + +- (void)dealloc { + delete imp_; + [super dealloc]; +} + +- (void)addObject:(id)obj { + imp_->v.push_back([obj retain]); +} + +- (void)addObject:(id)obj atIndex:(NSUInteger)index { + imp_->v.insert([self makeIterator:index], [obj retain]); +} + +- (void)removeObject:(id)obj { + for (std::vector<id>::iterator it = imp_->v.begin(); + it != imp_->v.end(); + ++it) { + if ([*it isEqual:obj]) { + [*it autorelease]; + imp_->v.erase(it); + return; + } + } +} + +- (void)removeObjectAtIndex:(NSUInteger)index { + [imp_->v[index] autorelease]; + imp_->v.erase([self makeIterator:index]); +} + +- (id)objectAtIndex:(NSUInteger)index { + return imp_->v[index]; +} + +- (std::vector<id>::iterator)makeIterator:(NSUInteger)index { + std::vector<id>::iterator it = imp_->v.begin(); + it += index; + return it; +} + +@end diff --git a/tools/gyp/test/mac/framework/TestFramework/ObjCVectorInternal.h b/tools/gyp/test/mac/framework/TestFramework/ObjCVectorInternal.h new file mode 100644 index 00000000000..fb6c98258b5 --- /dev/null +++ b/tools/gyp/test/mac/framework/TestFramework/ObjCVectorInternal.h @@ -0,0 +1,9 @@ +// 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 <vector> + +struct ObjCVectorImp { + std::vector<id> v; +}; diff --git a/tools/gyp/test/mac/framework/TestFramework/TestFramework_Prefix.pch b/tools/gyp/test/mac/framework/TestFramework/TestFramework_Prefix.pch new file mode 100644 index 00000000000..394f41d9576 --- /dev/null +++ b/tools/gyp/test/mac/framework/TestFramework/TestFramework_Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'TestFramework' target in the 'TestFramework' project. +// + +#ifdef __OBJC__ + #import <Cocoa/Cocoa.h> +#endif diff --git a/tools/gyp/test/mac/framework/empty.c b/tools/gyp/test/mac/framework/empty.c new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/tools/gyp/test/mac/framework/empty.c diff --git a/tools/gyp/test/mac/framework/framework.gyp b/tools/gyp/test/mac/framework/framework.gyp new file mode 100644 index 00000000000..7480e526c6b --- /dev/null +++ b/tools/gyp/test/mac/framework/framework.gyp @@ -0,0 +1,74 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'targets': [ + { + 'target_name': 'dep_framework', + 'product_name': 'Dependency Bundle', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'empty.c', ], + }, + { + 'target_name': 'test_framework', + 'product_name': 'Test Framework', + 'type': 'shared_library', + 'mac_bundle': 1, + 'dependencies': [ 'dep_framework', ], + 'sources': [ + 'TestFramework/ObjCVector.h', + 'TestFramework/ObjCVectorInternal.h', + 'TestFramework/ObjCVector.mm', + ], + 'mac_framework_headers': [ + 'TestFramework/ObjCVector.h', + ], + 'mac_bundle_resources': [ + 'TestFramework/English.lproj/InfoPlist.strings', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Cocoa.framework', + ], + }, + 'xcode_settings': { + 'INFOPLIST_FILE': 'TestFramework/Info.plist', + 'GCC_DYNAMIC_NO_PIC': 'NO', + }, + 'copies': [ + # Test copying to a file that has envvars in its dest path. + # Needs to be in a mac_bundle target, else CONTENTS_FOLDER_PATH isn't + # set. + { + 'destination': '<(PRODUCT_DIR)/$(CONTENTS_FOLDER_PATH)/Libraries', + 'files': [ + 'empty.c', + ], + }, + ], + }, + { + 'target_name': 'copy_target', + 'type': 'none', + 'dependencies': [ 'test_framework', 'dep_framework', ], + 'copies': [ + # Test copying directories with spaces in src and dest paths. + { + 'destination': '<(PRODUCT_DIR)/Test Framework.framework/foo', + 'files': [ + '<(PRODUCT_DIR)/Dependency Bundle.framework', + ], + }, + ], + 'actions': [ + { + 'action_name': 'aektschn', + 'inputs': [], + 'outputs': ['<(PRODUCT_DIR)/touched_file'], + 'action': ['touch', '${BUILT_PRODUCTS_DIR}/action_file'], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/mac/gyptest-app.py b/tools/gyp/test/mac/gyptest-app.py new file mode 100755 index 00000000000..5e772f8144e --- /dev/null +++ b/tools/gyp/test/mac/gyptest-app.py @@ -0,0 +1,44 @@ +#!/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 that app bundles are built correctly. +""" + +import TestGyp + +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['make', 'xcode']) + + test.run_gyp('test.gyp', chdir='app-bundle') + + test.build('test.gyp', test.ALL, chdir='app-bundle') + + # Binary + test.built_file_must_exist('Test App Gyp.app/Contents/MacOS/Test App Gyp', + chdir='app-bundle') + + # Info.plist + info_plist = test.built_file_path('Test App Gyp.app/Contents/Info.plist', + chdir='app-bundle') + test.must_exist(info_plist) + test.must_contain(info_plist, 'com.google.Test App Gyp') # Variable expansion + + # Resources + test.built_file_must_exist( + 'Test App Gyp.app/Contents/Resources/English.lproj/InfoPlist.strings', + chdir='app-bundle') + test.built_file_must_exist( + 'Test App Gyp.app/Contents/Resources/English.lproj/MainMenu.nib', + chdir='app-bundle') + + # Packaging + test.built_file_must_exist('Test App Gyp.app/Contents/PkgInfo', + chdir='app-bundle') + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-copies.py b/tools/gyp/test/mac/gyptest-copies.py new file mode 100755 index 00000000000..091b1dec5b6 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-copies.py @@ -0,0 +1,49 @@ +#!/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 that 'copies' with app bundles are handled correctly. +""" + +import TestGyp + +import os +import sys +import time + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['make', 'xcode']) + + test.run_gyp('framework.gyp', chdir='framework') + + test.build('framework.gyp', 'copy_target', chdir='framework') + + # Check that the copy succeeded. + test.built_file_must_exist( + 'Test Framework.framework/foo/Dependency Bundle.framework', + chdir='framework') + test.built_file_must_exist( + 'Test Framework.framework/foo/Dependency Bundle.framework/Versions/A', + chdir='framework') + test.built_file_must_exist( + 'Test Framework.framework/Versions/A/Libraries/empty.c', + chdir='framework') + + + # Check that rebuilding the target a few times works. + dep_bundle = test.built_file_path('Dependency Bundle.framework', + chdir='framework') + mtime = os.path.getmtime(dep_bundle) + atime = os.path.getatime(dep_bundle) + for i in range(3): + os.utime(dep_bundle, (atime + i * 1000, mtime + i * 1000)) + test.build('framework.gyp', 'copy_target', chdir='framework') + + + # Check that actions ran. + test.built_file_must_exist('action_file', chdir='framework') + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-debuginfo.py b/tools/gyp/test/mac/gyptest-debuginfo.py new file mode 100755 index 00000000000..1ec2d1da101 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-debuginfo.py @@ -0,0 +1,36 @@ +#!/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. + +""" +Tests things related to debug information generation. +""" + +import TestGyp + +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['make', 'xcode']) + + test.run_gyp('test.gyp', chdir='debuginfo') + + test.build('test.gyp', test.ALL, chdir='debuginfo') + + test.built_file_must_exist('libnonbundle_shared_library.dylib.dSYM', + chdir='debuginfo') + test.built_file_must_exist('nonbundle_loadable_module.so.dSYM', + chdir='debuginfo') + test.built_file_must_exist('nonbundle_executable.dSYM', + chdir='debuginfo') + + test.built_file_must_exist('bundle_shared_library.framework.dSYM', + chdir='debuginfo') + test.built_file_must_exist('bundle_loadable_module.bundle.dSYM', + chdir='debuginfo') + test.built_file_must_exist('My App.app.dSYM', + chdir='debuginfo') + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-framework.py b/tools/gyp/test/mac/gyptest-framework.py new file mode 100755 index 00000000000..6c19e40b33c --- /dev/null +++ b/tools/gyp/test/mac/gyptest-framework.py @@ -0,0 +1,50 @@ +#!/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 that app bundles are built correctly. +""" + +import TestGyp + +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['make', 'xcode']) + + test.run_gyp('framework.gyp', chdir='framework') + + test.build('framework.gyp', 'test_framework', chdir='framework') + + # Binary + test.built_file_must_exist( + 'Test Framework.framework/Versions/A/Test Framework', + chdir='framework') + + # Info.plist + test.built_file_must_exist( + 'Test Framework.framework/Versions/A/Resources/Info.plist', + chdir='framework') + + # Resources + test.built_file_must_exist( + 'Test Framework.framework/Versions/A/Resources/English.lproj/' + 'InfoPlist.strings', + chdir='framework') + + # Symlinks created by packaging process + test.built_file_must_exist('Test Framework.framework/Versions/Current', + chdir='framework') + test.built_file_must_exist('Test Framework.framework/Resources', + chdir='framework') + test.built_file_must_exist('Test Framework.framework/Test Framework', + chdir='framework') + # PkgInfo. + test.built_file_must_not_exist( + 'Test Framework.framework/Versions/A/Resources/PkgInfo', + chdir='framework') + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-infoplist-process.py b/tools/gyp/test/mac/gyptest-infoplist-process.py new file mode 100755 index 00000000000..9a2b140d315 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-infoplist-process.py @@ -0,0 +1,51 @@ +#!/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 the Info.plist preprocessor functionality. +""" + +import TestGyp + +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['make', 'xcode']) + + CHDIR = 'infoplist-process' + INFO_PLIST_PATH = 'Test.app/Contents/Info.plist' + + # First process both keys. + test.set_configuration('One') + test.run_gyp('test1.gyp', chdir=CHDIR) + test.build('test1.gyp', test.ALL, chdir=CHDIR) + info_plist = test.built_file_path(INFO_PLIST_PATH, chdir=CHDIR) + test.must_exist(info_plist) + test.must_contain(info_plist, 'Foo') + test.must_contain(info_plist, 'Bar') + + # Then process a single key. + test.set_configuration('Two') + test.run_gyp('test2.gyp', chdir=CHDIR) + test.build('test2.gyp', chdir=CHDIR) + info_plist = test.built_file_path(INFO_PLIST_PATH, chdir=CHDIR) + test.must_exist(info_plist) + test.must_contain(info_plist, 'com.google.Test') # Normal expansion works. + test.must_contain(info_plist, 'Foo (Bar)') + test.must_contain(info_plist, 'PROCESSED_KEY2') + + # Then turn off the processor. + test.set_configuration('Three') + test.run_gyp('test3.gyp', chdir=CHDIR) + test.build('test3.gyp', chdir=CHDIR) + info_plist = test.built_file_path('Test App.app/Contents/Info.plist', + chdir=CHDIR) + test.must_exist(info_plist) + test.must_contain(info_plist, 'com.google.Test') # Normal expansion works. + test.must_contain(info_plist, 'PROCESSED_KEY1') + test.must_contain(info_plist, 'PROCESSED_KEY2') + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-loadable-module.py b/tools/gyp/test/mac/gyptest-loadable-module.py new file mode 100755 index 00000000000..39e87f06059 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-loadable-module.py @@ -0,0 +1,45 @@ +#!/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. + +""" +Tests that a loadable_module target is built correctly. +""" + +import TestGyp + +import os +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['make', 'xcode']) + + test.run_gyp('test.gyp', chdir='loadable-module') + test.build('test.gyp', test.ALL, chdir='loadable-module') + + # Binary. + test.built_file_must_exist( + 'test_loadable_module.plugin/Contents/MacOS/test_loadable_module', + chdir='loadable-module') + + # Info.plist. + info_plist = test.built_file_path( + 'test_loadable_module.plugin/Contents/Info.plist', + chdir='loadable-module') + test.must_exist(info_plist) + test.must_contain(info_plist, """ + <key>CFBundleExecutable</key> + <string>test_loadable_module</string> +""") + + # PkgInfo. + test.built_file_must_not_exist( + 'test_loadable_module.plugin/Contents/PkgInfo', + chdir='loadable-module') + test.built_file_must_not_exist( + 'test_loadable_module.plugin/Contents/Resources', + chdir='loadable-module') + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-postbuild-fail.py b/tools/gyp/test/mac/gyptest-postbuild-fail.py new file mode 100755 index 00000000000..28b1a8061f0 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-postbuild-fail.py @@ -0,0 +1,53 @@ +#!/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 that a failing postbuild step lets the build fail. +""" + +import TestGyp + +import sys + +if sys.platform == 'darwin': + # set |match| to ignore build stderr output. + test = TestGyp.TestGyp(formats=['make', 'xcode'], match = lambda a, b: True) + + test.run_gyp('test.gyp', chdir='postbuild-fail') + + build_error_code = { + 'xcode': 1, + 'make': 2, + }[test.format] + + + # If a postbuild fails, all postbuilds should be re-run on the next build. + # However, even if the first postbuild fails the other postbuilds are still + # executed. + + + # Non-bundles + test.build('test.gyp', 'nonbundle', chdir='postbuild-fail', + status=build_error_code) + test.built_file_must_exist('static_touch', + chdir='postbuild-fail') + # Check for non-up-to-date-ness by checking if building again produces an + # error. + test.build('test.gyp', 'nonbundle', chdir='postbuild-fail', + status=build_error_code) + + + # Bundles + test.build('test.gyp', 'bundle', chdir='postbuild-fail', + status=build_error_code) + test.built_file_must_exist('dynamic_touch', + chdir='postbuild-fail') + # Check for non-up-to-date-ness by checking if building again produces an + # error. + test.build('test.gyp', 'bundle', chdir='postbuild-fail', + status=build_error_code) + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-postbuild.py b/tools/gyp/test/mac/gyptest-postbuild.py new file mode 100755 index 00000000000..b69a0bdfea6 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-postbuild.py @@ -0,0 +1,51 @@ +#!/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 that postbuild steps work. +""" + +import TestGyp + +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['make', 'xcode']) + + test.run_gyp('test.gyp', chdir='postbuilds') + + test.build('test.gyp', test.ALL, chdir='postbuilds') + + # See comment in test/subdirectory/gyptest-subdir-default.py + if test.format == 'xcode': + chdir = 'postbuilds/subdirectory' + else: + chdir = 'postbuilds' + + # Created by the postbuild scripts + test.built_file_must_exist('el.a_touch', + type=test.STATIC_LIB, + chdir='postbuilds') + test.built_file_must_exist('el.a_gyp_touch', + type=test.STATIC_LIB, + chdir='postbuilds') + test.built_file_must_exist('nest_el.a_touch', + type=test.STATIC_LIB, + chdir=chdir) + test.built_file_must_exist( + 'dyna.framework/Versions/A/dyna_touch', + chdir='postbuilds') + test.built_file_must_exist( + 'dyna.framework/Versions/A/dyna_gyp_touch', + chdir='postbuilds') + test.built_file_must_exist( + 'nest_dyna.framework/Versions/A/nest_dyna_touch', + chdir=chdir) + test.built_file_must_exist('dyna_standalone.dylib_gyp_touch', + type=test.SHARED_LIB, + chdir='postbuilds') + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-prefixheader.py b/tools/gyp/test/mac/gyptest-prefixheader.py new file mode 100755 index 00000000000..04b00f6b13b --- /dev/null +++ b/tools/gyp/test/mac/gyptest-prefixheader.py @@ -0,0 +1,19 @@ +#!/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 that GCC_PREFIX_HEADER works. +""" + +import TestGyp + +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['make', 'xcode']) + test.run_gyp('test.gyp', chdir='prefixheader') + test.build('test.gyp', test.ALL, chdir='prefixheader') + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-rebuild.py b/tools/gyp/test/mac/gyptest-rebuild.py new file mode 100755 index 00000000000..f88dcb94b2d --- /dev/null +++ b/tools/gyp/test/mac/gyptest-rebuild.py @@ -0,0 +1,29 @@ +#!/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 that app bundles are rebuilt correctly. +""" + +import TestGyp + +import os +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['make', 'xcode']) + + test.run_gyp('test.gyp', chdir='app-bundle') + + test.build('test.gyp', test.ALL, chdir='app-bundle') + + # Touch a source file, rebuild, and check that the app target is up-to-date. + os.utime('app-bundle/TestApp/main.m', None) + test.build('test.gyp', test.ALL, chdir='app-bundle') + + test.up_to_date('test.gyp', test.ALL, chdir='app-bundle') + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-strip.py b/tools/gyp/test/mac/gyptest-strip.py new file mode 100755 index 00000000000..2e4c3b03555 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-strip.py @@ -0,0 +1,53 @@ +#!/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 that stripping works. +""" + +import TestGyp + +import os +import re +import subprocess +import sys +import time + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['make', 'xcode']) + + test.run_gyp('test.gyp', chdir='strip') + + test.build('test.gyp', test.ALL, chdir='strip') + + # Lightweight check if stripping was done. + def OutPath(s): + return test.built_file_path(s, type=test.SHARED_LIB, chdir='strip') + + def CheckNsyms(p, n_expected): + r = re.compile(r'nsyms\s+(\d+)') + proc = subprocess.Popen(['otool', '-l', p], stdout=subprocess.PIPE) + o = proc.communicate()[0] + assert not proc.returncode + m = r.search(o, re.MULTILINE) + n = int(m.group(1)) + if n != n_expected: + print 'Stripping: Expected %d symbols, got %d' % (n_expected, n) + test.fail_test() + + # The actual numbers here are not interesting, they just need to be the same + # in both the xcode and the make build. + CheckNsyms(OutPath('no_postprocess'), 11) + CheckNsyms(OutPath('no_strip'), 11) + CheckNsyms(OutPath('strip_all'), 0) + CheckNsyms(OutPath('strip_nonglobal'), 2) + CheckNsyms(OutPath('strip_debugging'), 3) + CheckNsyms(OutPath('strip_all_custom_flags'), 0) + CheckNsyms(test.built_file_path( + 'strip_all_bundle.framework/Versions/A/strip_all_bundle', chdir='strip'), + 0) + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-type-envvars.py b/tools/gyp/test/mac/gyptest-type-envvars.py new file mode 100755 index 00000000000..1ef677319fb --- /dev/null +++ b/tools/gyp/test/mac/gyptest-type-envvars.py @@ -0,0 +1,24 @@ +#!/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. + +""" +Test that MACH_O_TYPE etc are set correctly. +""" + +import TestGyp + +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['make', 'xcode']) + + test.run_gyp('test.gyp', chdir='type_envvars') + + test.build('test.gyp', test.ALL, chdir='type_envvars') + + # The actual test is done by postbuild scripts during |test.build()|. + + test.pass_test() diff --git a/tools/gyp/test/mac/gyptest-xcode-env-order.py b/tools/gyp/test/mac/gyptest-xcode-env-order.py new file mode 100755 index 00000000000..64593732473 --- /dev/null +++ b/tools/gyp/test/mac/gyptest-xcode-env-order.py @@ -0,0 +1,30 @@ +#!/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 that dependent Xcode settings are processed correctly. +""" + +import TestGyp + +import sys + +if sys.platform == 'darwin': + test = TestGyp.TestGyp(formats=['make', 'xcode']) + + CHDIR = 'xcode-env-order' + INFO_PLIST_PATH = 'Test.app/Contents/Info.plist' + + test.run_gyp('test.gyp', chdir=CHDIR) + test.build('test.gyp', test.ALL, chdir=CHDIR) + info_plist = test.built_file_path(INFO_PLIST_PATH, chdir=CHDIR) + test.must_exist(info_plist) + test.must_contain(info_plist, '>/Source/Project/Test') + test.must_contain(info_plist, '>DEP:/Source/Project/Test') + test.must_contain(info_plist, + '>com.apple.product-type.application:DEP:/Source/Project/Test') + + test.pass_test() diff --git a/tools/gyp/test/mac/infoplist-process/Info.plist b/tools/gyp/test/mac/infoplist-process/Info.plist new file mode 100644 index 00000000000..cb65721f43b --- /dev/null +++ b/tools/gyp/test/mac/infoplist-process/Info.plist @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIconFile</key> + <string></string> + <key>CFBundleIdentifier</key> + <string>com.google.${PRODUCT_NAME}</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1</string> + <key>LSMinimumSystemVersion</key> + <string>${MACOSX_DEPLOYMENT_TARGET}</string> + <key>NSMainNibFile</key> + <string>MainMenu</string> + <key>NSPrincipalClass</key> + <string>NSApplication</string> + <key>ProcessedKey1</key> + <string>PROCESSED_KEY1</string> + <key>ProcessedKey2</key> + <string>PROCESSED_KEY2</string> +</dict> +</plist> diff --git a/tools/gyp/test/mac/infoplist-process/main.c b/tools/gyp/test/mac/infoplist-process/main.c new file mode 100644 index 00000000000..1bf4b2a11ab --- /dev/null +++ b/tools/gyp/test/mac/infoplist-process/main.c @@ -0,0 +1,7 @@ +// 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. + +int main() { + return 0; +} diff --git a/tools/gyp/test/mac/infoplist-process/test1.gyp b/tools/gyp/test/mac/infoplist-process/test1.gyp new file mode 100644 index 00000000000..bc625a968be --- /dev/null +++ b/tools/gyp/test/mac/infoplist-process/test1.gyp @@ -0,0 +1,25 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'targets': [ + { + 'target_name': 'test_app', + 'product_name': 'Test', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ + 'main.c', + ], + 'configurations': { + 'One': { + }, + }, + 'xcode_settings': { + 'INFOPLIST_FILE': 'Info.plist', + 'INFOPLIST_PREPROCESS': 'YES', + 'INFOPLIST_PREPROCESSOR_DEFINITIONS': 'PROCESSED_KEY1=Foo PROCESSED_KEY2=Bar', + }, + }, + ], +} diff --git a/tools/gyp/test/mac/infoplist-process/test2.gyp b/tools/gyp/test/mac/infoplist-process/test2.gyp new file mode 100644 index 00000000000..ecfbc9f64c9 --- /dev/null +++ b/tools/gyp/test/mac/infoplist-process/test2.gyp @@ -0,0 +1,25 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'targets': [ + { + 'target_name': 'test_app', + 'product_name': 'Test', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ + 'main.c', + ], + 'configurations': { + 'Two': { + }, + }, + 'xcode_settings': { + 'INFOPLIST_FILE': 'Info.plist', + 'INFOPLIST_PREPROCESS': 'YES', + 'INFOPLIST_PREPROCESSOR_DEFINITIONS': 'PROCESSED_KEY1="Foo (Bar)"', + }, + }, + ], +} diff --git a/tools/gyp/test/mac/infoplist-process/test3.gyp b/tools/gyp/test/mac/infoplist-process/test3.gyp new file mode 100644 index 00000000000..be8fe75a53e --- /dev/null +++ b/tools/gyp/test/mac/infoplist-process/test3.gyp @@ -0,0 +1,25 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'targets': [ + { + 'target_name': 'test_app', + 'product_name': 'Test App', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ + 'main.c', + ], + 'configurations': { + 'Three': { + }, + }, + 'xcode_settings': { + 'INFOPLIST_FILE': 'Info.plist', + 'INFOPLIST_PREPROCESS': 'NO', + 'INFOPLIST_PREPROCESSOR_DEFINITIONS': 'PROCESSED_KEY1=Foo', + }, + }, + ], +} diff --git a/tools/gyp/test/mac/loadable-module/Info.plist b/tools/gyp/test/mac/loadable-module/Info.plist new file mode 100644 index 00000000000..f6607aebd91 --- /dev/null +++ b/tools/gyp/test/mac/loadable-module/Info.plist @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIdentifier</key> + <string>com.google.test_loadable_module</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>BRPL</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1.0</string> + <key>CFPlugInDynamicRegisterFunction</key> + <string></string> + <key>CFPlugInDynamicRegistration</key> + <string>NO</string> +</dict> +</plist> diff --git a/tools/gyp/test/mac/loadable-module/module.c b/tools/gyp/test/mac/loadable-module/module.c new file mode 100644 index 00000000000..95845383474 --- /dev/null +++ b/tools/gyp/test/mac/loadable-module/module.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. + +int SuperFly() { + return 42; +} + +const char* SuperFoo() { + return "Hello World"; +} diff --git a/tools/gyp/test/mac/loadable-module/test.gyp b/tools/gyp/test/mac/loadable-module/test.gyp new file mode 100644 index 00000000000..3c8a5309d25 --- /dev/null +++ b/tools/gyp/test/mac/loadable-module/test.gyp @@ -0,0 +1,18 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'test_loadable_module', + 'type': 'loadable_module', + 'mac_bundle': 1, + 'sources': [ 'module.c' ], + 'product_extension': 'plugin', + 'xcode_settings': { + 'INFOPLIST_FILE': 'Info.plist', + }, + }, + ], +} diff --git a/tools/gyp/test/mac/postbuild-fail/file.c b/tools/gyp/test/mac/postbuild-fail/file.c new file mode 100644 index 00000000000..91695b10c6f --- /dev/null +++ b/tools/gyp/test/mac/postbuild-fail/file.c @@ -0,0 +1,6 @@ +// 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. + +// That's right, this is copyrighted. +void f() {} diff --git a/tools/gyp/test/mac/postbuild-fail/postbuild-fail.sh b/tools/gyp/test/mac/postbuild-fail/postbuild-fail.sh new file mode 100755 index 00000000000..d4113d059ee --- /dev/null +++ b/tools/gyp/test/mac/postbuild-fail/postbuild-fail.sh @@ -0,0 +1,6 @@ +#!/usr/bash +# 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. + +exit 1 diff --git a/tools/gyp/test/mac/postbuild-fail/test.gyp b/tools/gyp/test/mac/postbuild-fail/test.gyp new file mode 100644 index 00000000000..e63283db036 --- /dev/null +++ b/tools/gyp/test/mac/postbuild-fail/test.gyp @@ -0,0 +1,38 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'targets': [ + { + 'target_name': 'nonbundle', + 'type': 'static_library', + 'sources': [ 'file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'Postbuild Fail', + 'action': [ './postbuild-fail.sh', ], + }, + { + 'postbuild_name': 'Runs after failing postbuild', + 'action': [ './touch-static.sh', ], + }, + ], + }, + { + 'target_name': 'bundle', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'Postbuild Fail', + 'action': [ './postbuild-fail.sh', ], + }, + { + 'postbuild_name': 'Runs after failing postbuild', + 'action': [ './touch-dynamic.sh', ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/mac/postbuild-fail/touch-dynamic.sh b/tools/gyp/test/mac/postbuild-fail/touch-dynamic.sh new file mode 100755 index 00000000000..a388a64102b --- /dev/null +++ b/tools/gyp/test/mac/postbuild-fail/touch-dynamic.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# 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. + +set -e +touch "${BUILT_PRODUCTS_DIR}/dynamic_touch" diff --git a/tools/gyp/test/mac/postbuild-fail/touch-static.sh b/tools/gyp/test/mac/postbuild-fail/touch-static.sh new file mode 100755 index 00000000000..97ecaa68682 --- /dev/null +++ b/tools/gyp/test/mac/postbuild-fail/touch-static.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# 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. + +set -e +touch "${BUILT_PRODUCTS_DIR}/static_touch" diff --git a/tools/gyp/test/mac/postbuilds/file.c b/tools/gyp/test/mac/postbuilds/file.c new file mode 100644 index 00000000000..653e71ff7ec --- /dev/null +++ b/tools/gyp/test/mac/postbuilds/file.c @@ -0,0 +1,4 @@ +// 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. +void f() {} diff --git a/tools/gyp/test/mac/postbuilds/script/shared_library_postbuild.sh b/tools/gyp/test/mac/postbuilds/script/shared_library_postbuild.sh new file mode 100755 index 00000000000..c623c8bf218 --- /dev/null +++ b/tools/gyp/test/mac/postbuilds/script/shared_library_postbuild.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# 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. + +set -e + +lib="${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}" +nm ${lib} > /dev/null # Just make sure this works. + +pattern="${1}" + +if [ $pattern != "a|b" ]; then + echo "Parameter quoting is broken" + exit 1 +fi + +if [ "${2}" != "arg with spaces" ]; then + echo "Parameter space escaping is broken" + exit 1 +fi + +touch "${lib}"_touch diff --git a/tools/gyp/test/mac/postbuilds/script/static_library_postbuild.sh b/tools/gyp/test/mac/postbuilds/script/static_library_postbuild.sh new file mode 100755 index 00000000000..2bf09b34e1c --- /dev/null +++ b/tools/gyp/test/mac/postbuilds/script/static_library_postbuild.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# 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. + +set -e + +lib="${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}" +nm ${lib} > /dev/null # Just make sure this works. + +pattern="${1}" + +if [ $pattern != "a|b" ]; then + echo "Parameter quote escaping is broken" + exit 1 +fi + +if [ "${2}" != "arg with spaces" ]; then + echo "Parameter space escaping is broken" + exit 1 +fi + +touch "${lib}"_touch.a diff --git a/tools/gyp/test/mac/postbuilds/subdirectory/nested_target.gyp b/tools/gyp/test/mac/postbuilds/subdirectory/nested_target.gyp new file mode 100644 index 00000000000..f7ca9a6bf03 --- /dev/null +++ b/tools/gyp/test/mac/postbuilds/subdirectory/nested_target.gyp @@ -0,0 +1,45 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'targets': [ + { + 'target_name': 'nest_el', + 'type': 'static_library', + 'sources': [ '../file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'Static library postbuild', + 'variables': { + 'some_regex': 'a|b', + }, + 'action': [ + '../script/static_library_postbuild.sh', + '<(some_regex)', + 'arg with spaces', + ], + }, + ], + }, + { + 'target_name': 'nest_dyna', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ '../file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'Dynamic library postbuild', + 'variables': { + 'some_regex': 'a|b', + }, + 'action': [ + '../script/shared_library_postbuild.sh', + '<(some_regex)', + 'arg with spaces', + ], + }, + ], + }, + ], +} + diff --git a/tools/gyp/test/mac/postbuilds/test.gyp b/tools/gyp/test/mac/postbuilds/test.gyp new file mode 100644 index 00000000000..a9a05cb2d6d --- /dev/null +++ b/tools/gyp/test/mac/postbuilds/test.gyp @@ -0,0 +1,79 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'targets': [ + { + 'target_name': 'el', + 'type': 'static_library', + 'sources': [ 'file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'Static library postbuild', + 'variables': { + 'some_regex': 'a|b', + }, + 'action': [ + 'script/static_library_postbuild.sh', + '<(some_regex)', + 'arg with spaces', + ], + }, + { + 'postbuild_name': 'Test variable in gyp file', + 'action': [ + 'cp', + '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}', + '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}_gyp_touch.a', + ], + }, + ], + }, + { + 'target_name': 'dyna', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'file.c', ], + 'dependencies': [ + 'subdirectory/nested_target.gyp:nest_dyna', + 'subdirectory/nested_target.gyp:nest_el', + ], + 'postbuilds': [ + { + 'postbuild_name': 'Dynamic library postbuild', + 'variables': { + 'some_regex': 'a|b', + }, + 'action': [ + 'script/shared_library_postbuild.sh', + '<(some_regex)', + 'arg with spaces', + ], + }, + { + 'postbuild_name': 'Test variable in gyp file', + 'action': [ + 'cp', + '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}', + '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}_gyp_touch', + ], + }, + ], + }, + { + 'target_name': 'dyna_standalone', + 'type': 'shared_library', + 'sources': [ 'file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'Test variable in gyp file', + 'action': [ + 'cp', + '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}', + '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}_gyp_touch.dylib', + ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/mac/prefixheader/file.c b/tools/gyp/test/mac/prefixheader/file.c new file mode 100644 index 00000000000..d0b39d1f6d8 --- /dev/null +++ b/tools/gyp/test/mac/prefixheader/file.c @@ -0,0 +1 @@ +MyInt f() { return 0; } diff --git a/tools/gyp/test/mac/prefixheader/header.h b/tools/gyp/test/mac/prefixheader/header.h new file mode 100644 index 00000000000..0716e500c5a --- /dev/null +++ b/tools/gyp/test/mac/prefixheader/header.h @@ -0,0 +1 @@ +typedef int MyInt; diff --git a/tools/gyp/test/mac/prefixheader/test.gyp b/tools/gyp/test/mac/prefixheader/test.gyp new file mode 100644 index 00000000000..ce318dfc711 --- /dev/null +++ b/tools/gyp/test/mac/prefixheader/test.gyp @@ -0,0 +1,25 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'targets': [ + { + 'target_name': 'prefix_header', + 'type': 'static_library', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'GCC_PREFIX_HEADER': 'header.h', + }, + }, + { + 'target_name': 'precompiled_prefix_header', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'GCC_PREFIX_HEADER': 'header.h', + 'GCC_PRECOMPILE_PREFIX_HEADER': 'YES', + }, + }, + ], +} diff --git a/tools/gyp/test/mac/strip/file.c b/tools/gyp/test/mac/strip/file.c new file mode 100644 index 00000000000..421f0405f53 --- /dev/null +++ b/tools/gyp/test/mac/strip/file.c @@ -0,0 +1,9 @@ +// 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. + +static void the_static_function() {} + +void the_function() { + the_static_function(); +} diff --git a/tools/gyp/test/mac/strip/test.gyp b/tools/gyp/test/mac/strip/test.gyp new file mode 100644 index 00000000000..4eb5447d7d4 --- /dev/null +++ b/tools/gyp/test/mac/strip/test.gyp @@ -0,0 +1,104 @@ +# 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 xcode_settings affect stripping: +# "Deployment postprocessing involves stripping the binary, and setting +# its file mode, owner, and group." +#'DEPLOYMENT_POSTPROCESSING': 'YES', + +# "Specifies whether to strip symbol information from the binary. +# Prerequisite: $DEPLOYMENT_POSTPROCESSING = YES" "Default Value: 'NO'" +#'STRIP_INSTALLED_PRODUCT': 'YES', + +# "Values: +# * all: Strips the binary completely, removing the symbol table and +# relocation information +# * non-global: Strips nonglobal symbols but saves external symbols. +# * debugging: Strips debugging symbols but saves local and global +# symbols." +# (maps to no flag, -x, -S in that order) +#'STRIP_STYLE': 'non-global', + +# "Additional strip flags" +#'STRIPFLAGS': '-c', + +# "YES: Copied binaries are stripped of debugging symbols. This does +# not cause the binary produced by the linker to be stripped. Use +# 'STRIP_INSTALLED_PRODUCT (Strip Linked Product)' to have the linker +# strip the binary." +#'COPY_PHASE_STRIP': 'NO', +{ + 'targets': [ + { + 'target_name': 'no_postprocess', + 'type': 'shared_library', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEPLOYMENT_POSTPROCESSING': 'NO', + 'STRIP_INSTALLED_PRODUCT': 'YES', + }, + }, + { + 'target_name': 'no_strip', + 'type': 'shared_library', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'NO', + }, + }, + { + 'target_name': 'strip_all', + 'type': 'shared_library', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + 'STRIP_STYLE': 'all', + }, + }, + { + 'target_name': 'strip_nonglobal', + 'type': 'shared_library', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + 'STRIP_STYLE': 'non-global', + }, + }, + { + 'target_name': 'strip_debugging', + 'type': 'shared_library', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + 'STRIP_STYLE': 'debugging', + }, + }, + { + 'target_name': 'strip_all_custom_flags', + 'type': 'shared_library', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + 'STRIP_STYLE': 'all', + 'STRIPFLAGS': '-c', + }, + }, + { + 'target_name': 'strip_all_bundle', + 'type': 'shared_library', + 'mac_bundle': '1', + 'sources': [ 'file.c', ], + 'xcode_settings': { + 'DEPLOYMENT_POSTPROCESSING': 'YES', + 'STRIP_INSTALLED_PRODUCT': 'YES', + 'STRIP_STYLE': 'all', + }, + }, + ], +} diff --git a/tools/gyp/test/mac/type_envvars/file.c b/tools/gyp/test/mac/type_envvars/file.c new file mode 100644 index 00000000000..9cddaf1b0b4 --- /dev/null +++ b/tools/gyp/test/mac/type_envvars/file.c @@ -0,0 +1,6 @@ +// 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. + +void f() {} +int main() {} diff --git a/tools/gyp/test/mac/type_envvars/test.gyp b/tools/gyp/test/mac/type_envvars/test.gyp new file mode 100644 index 00000000000..4827957f673 --- /dev/null +++ b/tools/gyp/test/mac/type_envvars/test.gyp @@ -0,0 +1,89 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'targets': [ + { + 'target_name': 'my_app', + 'product_name': 'My App', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ 'file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'envtest', + 'action': [ './test_bundle_executable.sh', ], + }, + ], + }, + { + 'target_name': 'bundle_loadable_module', + 'type': 'loadable_module', + 'mac_bundle': 1, + 'sources': [ 'file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'envtest', + 'action': [ './test_bundle_loadable_module.sh', ], + }, + ], + }, + { + 'target_name': 'bundle_shared_library', + 'type': 'shared_library', + 'mac_bundle': 1, + 'sources': [ 'file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'envtest', + 'action': [ './test_bundle_shared_library.sh', ], + }, + ], + }, + + { + 'target_name': 'nonbundle_executable', + 'type': 'executable', + 'sources': [ 'file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'envtest', + 'action': [ './test_nonbundle_executable.sh', ], + }, + ], + }, + { + 'target_name': 'nonbundle_loadable_module', + 'type': 'loadable_module', + 'sources': [ 'file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'envtest', + 'action': [ './test_nonbundle_loadable_module.sh', ], + }, + ], + }, + { + 'target_name': 'nonbundle_shared_library', + 'type': 'shared_library', + 'sources': [ 'file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'envtest', + 'action': [ './test_nonbundle_shared_library.sh', ], + }, + ], + }, + { + 'target_name': 'nonbundle_static_library', + 'type': 'static_library', + 'sources': [ 'file.c', ], + 'postbuilds': [ + { + 'postbuild_name': 'envtest', + 'action': [ './test_nonbundle_static_library.sh', ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/mac/type_envvars/test_bundle_executable.sh b/tools/gyp/test/mac/type_envvars/test_bundle_executable.sh new file mode 100755 index 00000000000..4d3a084f073 --- /dev/null +++ b/tools/gyp/test/mac/type_envvars/test_bundle_executable.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# 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. + +set -e + +test $MACH_O_TYPE = mh_execute +test $PRODUCT_TYPE = com.apple.product-type.application diff --git a/tools/gyp/test/mac/type_envvars/test_bundle_loadable_module.sh b/tools/gyp/test/mac/type_envvars/test_bundle_loadable_module.sh new file mode 100755 index 00000000000..c74c8e435ea --- /dev/null +++ b/tools/gyp/test/mac/type_envvars/test_bundle_loadable_module.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# 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. + +set -e + +test $MACH_O_TYPE = mh_bundle +test $PRODUCT_TYPE = com.apple.product-type.bundle diff --git a/tools/gyp/test/mac/type_envvars/test_bundle_shared_library.sh b/tools/gyp/test/mac/type_envvars/test_bundle_shared_library.sh new file mode 100755 index 00000000000..08ad4fb7f6c --- /dev/null +++ b/tools/gyp/test/mac/type_envvars/test_bundle_shared_library.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# 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. + +set -e + +test $MACH_O_TYPE = mh_dylib +test $PRODUCT_TYPE = com.apple.product-type.framework diff --git a/tools/gyp/test/mac/type_envvars/test_nonbundle_executable.sh b/tools/gyp/test/mac/type_envvars/test_nonbundle_executable.sh new file mode 100755 index 00000000000..02d373de867 --- /dev/null +++ b/tools/gyp/test/mac/type_envvars/test_nonbundle_executable.sh @@ -0,0 +1,10 @@ +#!/bin/bash +# 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. + +set -e +# For some reason, Xcode doesn't set MACH_O_TYPE for non-bundle executables. +# Check for "not set", not just "empty": +[[ ! $MACH_O_TYPE && ${MACH_O_TYPE-_} ]] +test $PRODUCT_TYPE = com.apple.product-type.tool diff --git a/tools/gyp/test/mac/type_envvars/test_nonbundle_loadable_module.sh b/tools/gyp/test/mac/type_envvars/test_nonbundle_loadable_module.sh new file mode 100755 index 00000000000..aa67df3531a --- /dev/null +++ b/tools/gyp/test/mac/type_envvars/test_nonbundle_loadable_module.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# 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. + +set -e + +test $MACH_O_TYPE = mh_bundle +test $PRODUCT_TYPE = com.apple.product-type.library.dynamic diff --git a/tools/gyp/test/mac/type_envvars/test_nonbundle_shared_library.sh b/tools/gyp/test/mac/type_envvars/test_nonbundle_shared_library.sh new file mode 100755 index 00000000000..937a50c4aa6 --- /dev/null +++ b/tools/gyp/test/mac/type_envvars/test_nonbundle_shared_library.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# 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. + +set -e + +test $MACH_O_TYPE = mh_dylib +test $PRODUCT_TYPE = com.apple.product-type.library.dynamic diff --git a/tools/gyp/test/mac/type_envvars/test_nonbundle_static_library.sh b/tools/gyp/test/mac/type_envvars/test_nonbundle_static_library.sh new file mode 100755 index 00000000000..892f0d9f114 --- /dev/null +++ b/tools/gyp/test/mac/type_envvars/test_nonbundle_static_library.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# 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. + +set -e + +test $MACH_O_TYPE = staticlib +test $PRODUCT_TYPE = com.apple.product-type.library.static diff --git a/tools/gyp/test/mac/xcode-env-order/Info.plist b/tools/gyp/test/mac/xcode-env-order/Info.plist new file mode 100644 index 00000000000..55db30dba68 --- /dev/null +++ b/tools/gyp/test/mac/xcode-env-order/Info.plist @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIconFile</key> + <string></string> + <key>CFBundleIdentifier</key> + <string>com.google.${PRODUCT_NAME}</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1</string> + <key>LSMinimumSystemVersion</key> + <string>${MACOSX_DEPLOYMENT_TARGET}</string> + <key>NSMainNibFile</key> + <string>MainMenu</string> + <key>NSPrincipalClass</key> + <string>NSApplication</string> + <key>ProcessedKey1</key> + <string>${DEPENDENT_KEY1}</string> + <key>ProcessedKey2</key> + <string>${DEPENDENT_KEY2}</string> + <key>ProcessedKey3</key> + <string>${DEPENDENT_KEY3}</string> +</dict> +</plist> diff --git a/tools/gyp/test/mac/xcode-env-order/main.c b/tools/gyp/test/mac/xcode-env-order/main.c new file mode 100644 index 00000000000..1bf4b2a11ab --- /dev/null +++ b/tools/gyp/test/mac/xcode-env-order/main.c @@ -0,0 +1,7 @@ +// 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. + +int main() { + return 0; +} diff --git a/tools/gyp/test/mac/xcode-env-order/test.gyp b/tools/gyp/test/mac/xcode-env-order/test.gyp new file mode 100644 index 00000000000..d9191aab5e2 --- /dev/null +++ b/tools/gyp/test/mac/xcode-env-order/test.gyp @@ -0,0 +1,23 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +{ + 'targets': [ + { + 'target_name': 'test_app', + 'product_name': 'Test', + 'type': 'executable', + 'mac_bundle': 1, + 'sources': [ + 'main.c', + ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'Info.plist', + 'STRING_KEY': '/Source/Project', + 'DEPENDENT_KEY2': '$(STRING_KEY)/$(PRODUCT_NAME)', + 'DEPENDENT_KEY1': 'DEP:$(DEPENDENT_KEY2)', + 'DEPENDENT_KEY3': '$(PRODUCT_TYPE):$(DEPENDENT_KEY1)', + }, + }, + ], +} diff --git a/tools/gyp/test/make/dependencies.gyp b/tools/gyp/test/make/dependencies.gyp new file mode 100644 index 00000000000..e2bee24fcef --- /dev/null +++ b/tools/gyp/test/make/dependencies.gyp @@ -0,0 +1,15 @@ +# 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': 'main', + 'type': 'executable', + 'sources': [ + 'main.cc', + ], + }, + ], +} diff --git a/tools/gyp/test/make/gyptest-dependencies.py b/tools/gyp/test/make/gyptest-dependencies.py new file mode 100755 index 00000000000..76cfd0e819c --- /dev/null +++ b/tools/gyp/test/make/gyptest-dependencies.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 .d files and all.deps are properly generated. +""" + +import os +import TestGyp + +# .d files are only used by the make build. +test = TestGyp.TestGyp(formats=['make']) + +test.run_gyp('dependencies.gyp') + +test.build('dependencies.gyp', test.ALL) + +deps_file = test.built_file_path(".deps/out/Default/obj.target/main/main.o.d") +test.must_contain(deps_file, "main.h") + +# Build a second time to make sure we generate all.deps. +test.build('dependencies.gyp', test.ALL) + +all_deps_file = test.built_file_path(".deps/all.deps") +test.must_contain(all_deps_file, "main.h") +test.must_contain(all_deps_file, "cmd_") + +test.pass_test() diff --git a/tools/gyp/test/make/gyptest-noload.py b/tools/gyp/test/make/gyptest-noload.py new file mode 100755 index 00000000000..1f5103315cf --- /dev/null +++ b/tools/gyp/test/make/gyptest-noload.py @@ -0,0 +1,57 @@ +#!/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. + +""" +Tests the use of the NO_LOAD flag which makes loading sub .mk files +optional. +""" + +# Python 2.5 needs this for the with statement. +from __future__ import with_statement + +import os +import TestGyp + +test = TestGyp.TestGyp(formats=['make']) + +test.run_gyp('all.gyp', chdir='noload') + +test.relocate('noload', 'relocate/noload') + +test.build('build/all.gyp', test.ALL, chdir='relocate/noload') +test.run_built_executable('exe', chdir='relocate/noload', + stdout='Hello from shared.c.\n') + +# Just sanity test that NO_LOAD=lib doesn't break anything. +test.build('build/all.gyp', test.ALL, chdir='relocate/noload', + arguments=['NO_LOAD=lib']) +test.run_built_executable('exe', chdir='relocate/noload', + stdout='Hello from shared.c.\n') +test.build('build/all.gyp', test.ALL, chdir='relocate/noload', + arguments=['NO_LOAD=z']) +test.run_built_executable('exe', chdir='relocate/noload', + stdout='Hello from shared.c.\n') + +# Make sure we can rebuild without reloading the sub .mk file. +with open('relocate/noload/main.c', 'a') as src_file: + src_file.write("\n") +test.build('build/all.gyp', test.ALL, chdir='relocate/noload', + arguments=['NO_LOAD=lib']) +test.run_built_executable('exe', chdir='relocate/noload', + stdout='Hello from shared.c.\n') + +# Change shared.c, but verify that it doesn't get rebuild if we don't load it. +with open('relocate/noload/lib/shared.c', 'w') as shared_file: + shared_file.write( + '#include "shared.h"\n' + 'const char kSharedStr[] = "modified";\n' + ) +test.build('build/all.gyp', test.ALL, chdir='relocate/noload', + arguments=['NO_LOAD=lib']) +test.run_built_executable('exe', chdir='relocate/noload', + stdout='Hello from shared.c.\n') + +test.pass_test() diff --git a/tools/gyp/test/make/main.cc b/tools/gyp/test/make/main.cc new file mode 100644 index 00000000000..70ac6e46ae0 --- /dev/null +++ b/tools/gyp/test/make/main.cc @@ -0,0 +1,12 @@ +/* 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. */ + +#include <stdio.h> + +#include "main.h" + +int main(int argc, char *argv[]) { + printf("hello world\n"); + return 0; +} diff --git a/tools/gyp/test/make/main.h b/tools/gyp/test/make/main.h new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/tools/gyp/test/make/main.h diff --git a/tools/gyp/test/make/noload/all.gyp b/tools/gyp/test/make/noload/all.gyp new file mode 100644 index 00000000000..1617a9e97c9 --- /dev/null +++ b/tools/gyp/test/make/noload/all.gyp @@ -0,0 +1,18 @@ +# 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': 'exe', + 'type': 'executable', + 'sources': [ + 'main.c', + ], + 'dependencies': [ + 'lib/shared.gyp:shared', + ], + }, + ], +} diff --git a/tools/gyp/test/make/noload/lib/shared.c b/tools/gyp/test/make/noload/lib/shared.c new file mode 100644 index 00000000000..51776c5acfa --- /dev/null +++ b/tools/gyp/test/make/noload/lib/shared.c @@ -0,0 +1,3 @@ +#include "shared.h" + +const char kSharedStr[] = "shared.c"; diff --git a/tools/gyp/test/make/noload/lib/shared.gyp b/tools/gyp/test/make/noload/lib/shared.gyp new file mode 100644 index 00000000000..8a8841b3a06 --- /dev/null +++ b/tools/gyp/test/make/noload/lib/shared.gyp @@ -0,0 +1,16 @@ +# 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': 'shared', + 'type': 'shared_library', + 'sources': [ + 'shared.c', + 'shared.h', + ], + }, + ], +} diff --git a/tools/gyp/test/make/noload/lib/shared.h b/tools/gyp/test/make/noload/lib/shared.h new file mode 100644 index 00000000000..a21da7538bf --- /dev/null +++ b/tools/gyp/test/make/noload/lib/shared.h @@ -0,0 +1 @@ +extern const char kSharedStr[]; diff --git a/tools/gyp/test/make/noload/main.c b/tools/gyp/test/make/noload/main.c new file mode 100644 index 00000000000..46d3c52c2d4 --- /dev/null +++ b/tools/gyp/test/make/noload/main.c @@ -0,0 +1,9 @@ +#include <stdio.h> + +#include "lib/shared.h" + +int main(int argc, char *argv[]) +{ + printf("Hello from %s.\n", kSharedStr); + return 0; +} diff --git a/tools/gyp/test/module/gyptest-default.py b/tools/gyp/test/module/gyptest-default.py new file mode 100755 index 00000000000..6b1c9b6a853 --- /dev/null +++ b/tools/gyp/test/module/gyptest-default.py @@ -0,0 +1,28 @@ +#!/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 build of a "Hello, world!" program with loadable modules. The +default for all platforms should be to output the loadable modules to the same +path as the executable. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('module.gyp', chdir='src') + +test.build('module.gyp', test.ALL, chdir='src') + +expect = """\ +Hello from program.c +Hello from lib1.c +Hello from lib2.c +""" +test.run_built_executable('program', chdir='src', stdout=expect) + +test.pass_test() diff --git a/tools/gyp/test/module/src/lib1.c b/tools/gyp/test/module/src/lib1.c new file mode 100644 index 00000000000..8de0e94bee7 --- /dev/null +++ b/tools/gyp/test/module/src/lib1.c @@ -0,0 +1,10 @@ +#include <stdio.h> + +#ifdef _WIN32 +__declspec(dllexport) +#endif +void module_main(void) +{ + fprintf(stdout, "Hello from lib1.c\n"); + fflush(stdout); +} diff --git a/tools/gyp/test/module/src/lib2.c b/tools/gyp/test/module/src/lib2.c new file mode 100644 index 00000000000..266396dc91c --- /dev/null +++ b/tools/gyp/test/module/src/lib2.c @@ -0,0 +1,10 @@ +#include <stdio.h> + +#ifdef _WIN32 +__declspec(dllexport) +#endif +void module_main(void) +{ + fprintf(stdout, "Hello from lib2.c\n"); + fflush(stdout); +} diff --git a/tools/gyp/test/module/src/module.gyp b/tools/gyp/test/module/src/module.gyp new file mode 100644 index 00000000000..bb43c302307 --- /dev/null +++ b/tools/gyp/test/module/src/module.gyp @@ -0,0 +1,55 @@ +# 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'], + # Support 64-bit shared libs (also works fine for 32-bit). + 'cflags': ['-fPIC'], + 'ldflags': ['-ldl'], + }], + ], + }, + 'targets': [ + { + 'target_name': 'program', + 'type': 'executable', + 'dependencies': [ + 'lib1', + 'lib2', + ], + 'sources': [ + 'program.c', + ], + }, + { + 'target_name': 'lib1', + 'type': 'loadable_module', + 'product_name': 'lib1', + 'product_prefix': '', + 'xcode_settings': {'OTHER_LDFLAGS': ['-dynamiclib'], 'MACH_O_TYPE': ''}, + 'sources': [ + 'lib1.c', + ], + }, + { + 'target_name': 'lib2', + 'product_name': 'lib2', + 'product_prefix': '', + 'type': 'loadable_module', + 'xcode_settings': {'OTHER_LDFLAGS': ['-dynamiclib'], 'MACH_O_TYPE': ''}, + 'sources': [ + 'lib2.c', + ], + }, + ], +} diff --git a/tools/gyp/test/module/src/program.c b/tools/gyp/test/module/src/program.c new file mode 100644 index 00000000000..b2f33209176 --- /dev/null +++ b/tools/gyp/test/module/src/program.c @@ -0,0 +1,111 @@ +#include <stdio.h> +#include <stdlib.h> + +#if defined(PLATFORM_WIN) +#include <windows.h> +#elif defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) +#include <dlfcn.h> +#include <libgen.h> +#include <string.h> +#include <sys/param.h> +#define MAX_PATH PATH_MAX +#endif + +#if defined(PLATFORM_WIN) +#define MODULE_SUFFIX ".dll" +#elif defined(PLATFORM_MAC) +#define MODULE_SUFFIX ".so" +#elif defined(PLATFORM_LINUX) +#define MODULE_SUFFIX ".so" +#endif + +typedef void (*module_symbol)(void); +char bin_path[MAX_PATH + 1]; + + +void CallModule(const char* module) { + char module_path[MAX_PATH + 1]; + const char* module_function = "module_main"; + module_symbol funcptr; +#if defined(PLATFORM_WIN) + HMODULE dl; + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + + if (_splitpath_s(bin_path, drive, _MAX_DRIVE, dir, _MAX_DIR, + NULL, 0, NULL, 0)) { + fprintf(stderr, "Failed to split executable path.\n"); + return; + } + if (_makepath_s(module_path, MAX_PATH, drive, dir, module, MODULE_SUFFIX)) { + fprintf(stderr, "Failed to calculate module path.\n"); + return; + } + + dl = LoadLibrary(module_path); + if (!dl) { + fprintf(stderr, "Failed to open module: %s\n", module_path); + return; + } + + funcptr = (module_symbol) GetProcAddress(dl, module_function); + if (!funcptr) { + fprintf(stderr, "Failed to find symbol: %s\n", module_function); + return; + } + funcptr(); + + FreeLibrary(dl); +#elif defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) + void* dl; + char* path_copy = strdup(bin_path); + char* bin_dir = dirname(path_copy); + int path_size = snprintf(module_path, MAX_PATH, "%s/%s%s", bin_dir, module, + MODULE_SUFFIX); + free(path_copy); + if (path_size < 0 || path_size > MAX_PATH) { + fprintf(stderr, "Failed to calculate module path.\n"); + return; + } + module_path[path_size] = 0; + + dl = dlopen(module_path, RTLD_LAZY); + if (!dl) { + fprintf(stderr, "Failed to open module: %s\n", module_path); + return; + } + + funcptr = dlsym(dl, module_function); + if (!funcptr) { + fprintf(stderr, "Failed to find symbol: %s\n", module_function); + return; + } + funcptr(); + + dlclose(dl); +#endif +} + +int main(int argc, char *argv[]) +{ + fprintf(stdout, "Hello from program.c\n"); + fflush(stdout); + +#if defined(PLATFORM_WIN) + if (!GetModuleFileName(NULL, bin_path, MAX_PATH)) { + fprintf(stderr, "Failed to determine executable path.\n"); + return; + } +#elif defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) + // Using argv[0] should be OK here since we control how the tests run, and + // can avoid exec and such issues that make it unreliable. + if (!realpath(argv[0], bin_path)) { + fprintf(stderr, "Failed to determine executable path (%s).\n", argv[0]); + return; + } +#endif + + CallModule("lib1"); + CallModule("lib2"); + return 0; +} diff --git a/tools/gyp/test/msvs/express/base/base.gyp b/tools/gyp/test/msvs/express/base/base.gyp new file mode 100644 index 00000000000..b7c9fc6d81f --- /dev/null +++ b/tools/gyp/test/msvs/express/base/base.gyp @@ -0,0 +1,22 @@ +# 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': 'a', + 'type': 'static_library', + 'sources': [ + 'a.c', + ], + }, + { + 'target_name': 'b', + 'type': 'static_library', + 'sources': [ + 'b.c', + ], + }, + ], +} diff --git a/tools/gyp/test/msvs/express/express.gyp b/tools/gyp/test/msvs/express/express.gyp new file mode 100644 index 00000000000..917abe2cc0b --- /dev/null +++ b/tools/gyp/test/msvs/express/express.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. + +{ + 'targets': [ + { + 'target_name': 'express', + 'type': 'executable', + 'dependencies': [ + 'base/base.gyp:a', + 'base/base.gyp:b', + ], + 'sources': [ + 'main.c', + ], + }, + ], +} diff --git a/tools/gyp/test/msvs/express/gyptest-express.py b/tools/gyp/test/msvs/express/gyptest-express.py new file mode 100755 index 00000000000..54c06f664ae --- /dev/null +++ b/tools/gyp/test/msvs/express/gyptest-express.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 flat solutions get generated for Express versions of +Visual Studio. +""" + +import TestGyp + +test = TestGyp.TestGyp(formats=['msvs']) + +test.run_gyp('express.gyp', '-G', 'msvs_version=2005') +test.must_contain('express.sln', '(base)') + +test.run_gyp('express.gyp', '-G', 'msvs_version=2008') +test.must_contain('express.sln', '(base)') + +test.run_gyp('express.gyp', '-G', 'msvs_version=2005e') +test.must_not_contain('express.sln', '(base)') + +test.run_gyp('express.gyp', '-G', 'msvs_version=2008e') +test.must_not_contain('express.sln', '(base)') + + +test.pass_test() diff --git a/tools/gyp/test/msvs/precompiled/gyptest-all.py b/tools/gyp/test/msvs/precompiled/gyptest-all.py new file mode 100755 index 00000000000..327ca6d6e10 --- /dev/null +++ b/tools/gyp/test/msvs/precompiled/gyptest-all.py @@ -0,0 +1,23 @@ +#!/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 that precompiled headers can be specified. +""" + +import TestGyp + +test = TestGyp.TestGyp(formats=['msvs'], workdir='workarea_all') + +test.run_gyp('hello.gyp') + +test.build('hello.gyp', 'hello') + +test.run_built_executable('hello', stdout="Hello, world!\nHello, two!\n") + +test.up_to_date('hello.gyp', test.ALL) + +test.pass_test() diff --git a/tools/gyp/test/msvs/precompiled/hello.c b/tools/gyp/test/msvs/precompiled/hello.c new file mode 100644 index 00000000000..d1abbb9e517 --- /dev/null +++ b/tools/gyp/test/msvs/precompiled/hello.c @@ -0,0 +1,14 @@ +/* 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. */ + +// Note the abscence of a stdio.h include. This will be inserted because of the +// precompiled header. + +extern int hello2(); + +int main(int argc, char *argv[]) { + printf("Hello, world!\n"); + hello2(); + return 0; +} diff --git a/tools/gyp/test/msvs/precompiled/hello.gyp b/tools/gyp/test/msvs/precompiled/hello.gyp new file mode 100644 index 00000000000..b9533efd851 --- /dev/null +++ b/tools/gyp/test/msvs/precompiled/hello.gyp @@ -0,0 +1,19 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'hello', + 'type': 'executable', + 'sources': [ + 'hello.c', + 'hello2.c', + 'precomp.c', + ], + 'msvs_precompiled_header': 'stdio.h', + 'msvs_precompiled_source': 'precomp.c', + }, + ], +} diff --git a/tools/gyp/test/msvs/precompiled/hello2.c b/tools/gyp/test/msvs/precompiled/hello2.c new file mode 100644 index 00000000000..d6d53111fb8 --- /dev/null +++ b/tools/gyp/test/msvs/precompiled/hello2.c @@ -0,0 +1,13 @@ +/* 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. */ + +// Unlike hello.c, this file specifies the headers. + +#include <windows.h> +#include <stdio.h> + +int hello2() { + printf("Hello, two!\n"); + return 0; +} diff --git a/tools/gyp/test/msvs/precompiled/precomp.c b/tools/gyp/test/msvs/precompiled/precomp.c new file mode 100644 index 00000000000..517c61a36ba --- /dev/null +++ b/tools/gyp/test/msvs/precompiled/precomp.c @@ -0,0 +1,8 @@ +/* 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. */ + +// The precompiled header does not have to be the first one in the file. + +#include <windows.h> +#include <stdio.h> diff --git a/tools/gyp/test/multiple-targets/gyptest-all.py b/tools/gyp/test/multiple-targets/gyptest-all.py new file mode 100755 index 00000000000..9f157c4f82a --- /dev/null +++ b/tools/gyp/test/multiple-targets/gyptest-all.py @@ -0,0 +1,35 @@ +#!/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 TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('multiple.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +# TODO(sgk): remove stderr=None when the --generator-output= support +# gets rid of the scons warning +test.build('multiple.gyp', test.ALL, chdir='relocate/src', stderr=None) + +expect1 = """\ +hello from prog1.c +hello from common.c +""" + +expect2 = """\ +hello from prog2.c +hello from common.c +""" + +test.run_built_executable('prog1', stdout=expect1, chdir='relocate/src') +test.run_built_executable('prog2', stdout=expect2, chdir='relocate/src') + +test.pass_test() diff --git a/tools/gyp/test/multiple-targets/gyptest-default.py b/tools/gyp/test/multiple-targets/gyptest-default.py new file mode 100755 index 00000000000..8d5072d2305 --- /dev/null +++ b/tools/gyp/test/multiple-targets/gyptest-default.py @@ -0,0 +1,35 @@ +#!/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 TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('multiple.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +# TODO(sgk): remove stderr=None when the --generator-output= support +# gets rid of the scons warning +test.build('multiple.gyp', chdir='relocate/src', stderr=None) + +expect1 = """\ +hello from prog1.c +hello from common.c +""" + +expect2 = """\ +hello from prog2.c +hello from common.c +""" + +test.run_built_executable('prog1', stdout=expect1, chdir='relocate/src') +test.run_built_executable('prog2', stdout=expect2, chdir='relocate/src') + +test.pass_test() diff --git a/tools/gyp/test/multiple-targets/src/common.c b/tools/gyp/test/multiple-targets/src/common.c new file mode 100644 index 00000000000..f1df7c14314 --- /dev/null +++ b/tools/gyp/test/multiple-targets/src/common.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +void common(void) +{ + printf("hello from common.c\n"); + return; +} diff --git a/tools/gyp/test/multiple-targets/src/multiple.gyp b/tools/gyp/test/multiple-targets/src/multiple.gyp new file mode 100644 index 00000000000..3db4ea30cd0 --- /dev/null +++ b/tools/gyp/test/multiple-targets/src/multiple.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': 'prog1', + 'type': 'executable', + 'sources': [ + 'prog1.c', + 'common.c', + ], + }, + { + 'target_name': 'prog2', + 'type': 'executable', + 'sources': [ + 'prog2.c', + 'common.c', + ], + }, + ], +} diff --git a/tools/gyp/test/multiple-targets/src/prog1.c b/tools/gyp/test/multiple-targets/src/prog1.c new file mode 100644 index 00000000000..d55f8af1d04 --- /dev/null +++ b/tools/gyp/test/multiple-targets/src/prog1.c @@ -0,0 +1,10 @@ +#include <stdio.h> + +extern void common(void); + +int main(int argc, char *argv[]) +{ + printf("hello from prog1.c\n"); + common(); + return 0; +} diff --git a/tools/gyp/test/multiple-targets/src/prog2.c b/tools/gyp/test/multiple-targets/src/prog2.c new file mode 100644 index 00000000000..760590eb68a --- /dev/null +++ b/tools/gyp/test/multiple-targets/src/prog2.c @@ -0,0 +1,10 @@ +#include <stdio.h> + +extern void common(void); + +int main(int argc, char *argv[]) +{ + printf("hello from prog2.c\n"); + common(); + return 0; +} diff --git a/tools/gyp/test/ninja/action_dependencies/gyptest-action-dependencies.py b/tools/gyp/test/ninja/action_dependencies/gyptest-action-dependencies.py new file mode 100755 index 00000000000..f84af24ec51 --- /dev/null +++ b/tools/gyp/test/ninja/action_dependencies/gyptest-action-dependencies.py @@ -0,0 +1,45 @@ +#!/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. + +""" +Verify that building an object file correctly depends on running actions in +dependent targets, but not the targets themselves. +""" + +import TestGyp + +# NOTE(piman): This test will not work with other generators because: +# - it explicitly tests the optimization, which is not implemented (yet?) on +# other generators +# - it relies on the exact path to output object files, which is generator +# dependent, and actually, relies on the ability to build only that object file, +# which I don't think is available on all generators. +# TODO(piman): Extend to other generators when possible. +test = TestGyp.TestGyp(formats=['ninja']) + +test.run_gyp('action_dependencies.gyp', chdir='src') + +chdir = 'relocate/src' +test.relocate('src', chdir) + +test.build('action_dependencies.gyp', 'obj/b.b.o', chdir=chdir) + +# The 'a' actions should be run (letting b.c compile), but the a static library +# should not be built. +test.built_file_must_not_exist('a', type=test.STATIC_LIB, chdir=chdir) +test.built_file_must_not_exist('b', type=test.STATIC_LIB, chdir=chdir) +test.built_file_must_exist('obj/b.b.o', chdir=chdir) + +test.build('action_dependencies.gyp', 'obj/c.c.o', chdir=chdir) + +# 'a' and 'b' should be built, so that the 'c' action succeeds, letting c.c +# compile +test.built_file_must_exist('a', type=test.STATIC_LIB, chdir=chdir) +test.built_file_must_exist('b', type=test.EXECUTABLE, chdir=chdir) +test.built_file_must_exist('obj/c.c.o', chdir=chdir) + + +test.pass_test() diff --git a/tools/gyp/test/ninja/action_dependencies/src/a.c b/tools/gyp/test/ninja/action_dependencies/src/a.c new file mode 100644 index 00000000000..4d7af9b26ca --- /dev/null +++ b/tools/gyp/test/ninja/action_dependencies/src/a.c @@ -0,0 +1,10 @@ +/* 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 "a.h" + +int funcA() { + return 42; +} diff --git a/tools/gyp/test/ninja/action_dependencies/src/a.h b/tools/gyp/test/ninja/action_dependencies/src/a.h new file mode 100644 index 00000000000..335db567398 --- /dev/null +++ b/tools/gyp/test/ninja/action_dependencies/src/a.h @@ -0,0 +1,13 @@ +/* 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. + */ + +#ifndef A_H_ +#define A_H_ + +#include "a/generated.h" + +int funcA(); + +#endif // A_H_ diff --git a/tools/gyp/test/ninja/action_dependencies/src/action_dependencies.gyp b/tools/gyp/test/ninja/action_dependencies/src/action_dependencies.gyp new file mode 100644 index 00000000000..5baa7a7d47e --- /dev/null +++ b/tools/gyp/test/ninja/action_dependencies/src/action_dependencies.gyp @@ -0,0 +1,88 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'a', + 'type': 'static_library', + 'sources': [ + 'a.c', + 'a.h', + ], + 'actions': [ + { + 'action_name': 'generate_headers', + 'inputs': [ + 'emit.py' + ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/a/generated.h' + ], + 'action': [ + 'python', + 'emit.py', + '<(SHARED_INTERMEDIATE_DIR)/a/generated.h', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + 'include_dirs': [ + '<(SHARED_INTERMEDIATE_DIR)', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '<(SHARED_INTERMEDIATE_DIR)', + ], + }, + }, + { + 'target_name': 'b', + 'type': 'executable', + 'sources': [ + 'b.c', + 'b.h', + ], + 'dependencies': [ + 'a', + ], + }, + { + 'target_name': 'c', + 'type': 'static_library', + 'sources': [ + 'c.c', + 'c.h', + ], + 'dependencies': [ + 'b', + ], + 'actions': [ + { + 'action_name': 'generate_headers', + 'inputs': [ + ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/c/generated.h' + ], + 'action': [ + '<(PRODUCT_DIR)/b', + '<(SHARED_INTERMEDIATE_DIR)/c/generated.h', + ], + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }, + ], + 'include_dirs': [ + '<(SHARED_INTERMEDIATE_DIR)', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '<(SHARED_INTERMEDIATE_DIR)', + ], + }, + }, + ], +} diff --git a/tools/gyp/test/ninja/action_dependencies/src/b.c b/tools/gyp/test/ninja/action_dependencies/src/b.c new file mode 100644 index 00000000000..7d70d01ca07 --- /dev/null +++ b/tools/gyp/test/ninja/action_dependencies/src/b.c @@ -0,0 +1,17 @@ +/* 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> + +#include "b.h" + +int main(int argc, char** argv) { + if (argc < 2) + return 1; + FILE* f = fopen(argv[1], "wt"); + fprintf(f, "#define VALUE %d\n", funcA()); + fclose(f); + return 0; +} diff --git a/tools/gyp/test/ninja/action_dependencies/src/b.h b/tools/gyp/test/ninja/action_dependencies/src/b.h new file mode 100644 index 00000000000..91362cd8997 --- /dev/null +++ b/tools/gyp/test/ninja/action_dependencies/src/b.h @@ -0,0 +1,13 @@ +/* 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. + */ + +#ifndef B_H_ +#define B_H_ + +#include "a.h" + +int funcB(); + +#endif // B_H_ diff --git a/tools/gyp/test/ninja/action_dependencies/src/c.c b/tools/gyp/test/ninja/action_dependencies/src/c.c new file mode 100644 index 00000000000..b412087ec87 --- /dev/null +++ b/tools/gyp/test/ninja/action_dependencies/src/c.c @@ -0,0 +1,10 @@ +/* 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 "c.h" + +int funcC() { + return VALUE; +} diff --git a/tools/gyp/test/ninja/action_dependencies/src/c.h b/tools/gyp/test/ninja/action_dependencies/src/c.h new file mode 100644 index 00000000000..c81a45bbe76 --- /dev/null +++ b/tools/gyp/test/ninja/action_dependencies/src/c.h @@ -0,0 +1,13 @@ +/* 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. + */ + +#ifndef C_H_ +#define C_H_ + +#include "c/generated.h" + +int funcC(); + +#endif // C_H_ diff --git a/tools/gyp/test/ninja/action_dependencies/src/emit.py b/tools/gyp/test/ninja/action_dependencies/src/emit.py new file mode 100755 index 00000000000..2df74b79a12 --- /dev/null +++ b/tools/gyp/test/ninja/action_dependencies/src/emit.py @@ -0,0 +1,11 @@ +#!/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 + +f = open(sys.argv[1], 'wb') +f.write('/* Hello World */\n') +f.close() diff --git a/tools/gyp/test/no-output/gyptest-no-output.py b/tools/gyp/test/no-output/gyptest-no-output.py new file mode 100755 index 00000000000..bf9a0b5aaa4 --- /dev/null +++ b/tools/gyp/test/no-output/gyptest-no-output.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. + +""" +Verified things don't explode when there are targets without outputs. +""" + +import TestGyp + +# TODO(evan): in ninja when there are no targets, there is no 'all' +# target either. Disabling this test for now. +test = TestGyp.TestGyp(formats=['!ninja']) + +test.run_gyp('nooutput.gyp', chdir='src') +test.relocate('src', 'relocate/src') +test.build('nooutput.gyp', chdir='relocate/src') + +test.pass_test() diff --git a/tools/gyp/test/no-output/src/nooutput.gyp b/tools/gyp/test/no-output/src/nooutput.gyp new file mode 100644 index 00000000000..c40124efc1e --- /dev/null +++ b/tools/gyp/test/no-output/src/nooutput.gyp @@ -0,0 +1,17 @@ +# 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': 'no_output', + 'type': 'none', + 'direct_dependent_settings': { + 'defines': [ + 'NADA', + ], + }, + }, + ], +} diff --git a/tools/gyp/test/product/gyptest-product.py b/tools/gyp/test/product/gyptest-product.py new file mode 100755 index 00000000000..e9790f30da5 --- /dev/null +++ b/tools/gyp/test/product/gyptest-product.py @@ -0,0 +1,43 @@ +#!/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 simplest-possible build of a "Hello, world!" program +using the default build target. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('product.gyp') +test.build('product.gyp') + +# executables +test.built_file_must_exist('alt1' + test._exe, test.EXECUTABLE, bare=True) +test.built_file_must_exist('hello2.stuff', test.EXECUTABLE, bare=True) +test.built_file_must_exist('yoalt3.stuff', test.EXECUTABLE, bare=True) + +# shared libraries +test.built_file_must_exist(test.dll_ + 'alt4' + test._dll, + test.SHARED_LIB, bare=True) +test.built_file_must_exist(test.dll_ + 'hello5.stuff', + test.SHARED_LIB, bare=True) +test.built_file_must_exist('yoalt6.stuff', test.SHARED_LIB, bare=True) + +# static libraries +test.built_file_must_exist(test.lib_ + 'alt7' + test._lib, + test.STATIC_LIB, bare=True) +test.built_file_must_exist(test.lib_ + 'hello8.stuff', + test.STATIC_LIB, bare=True) +test.built_file_must_exist('yoalt9.stuff', test.STATIC_LIB, bare=True) + +# alternate product_dir +test.built_file_must_exist('bob/yoalt10.stuff', test.EXECUTABLE, bare=True) +test.built_file_must_exist('bob/yoalt11.stuff', test.EXECUTABLE, bare=True) +test.built_file_must_exist('bob/yoalt12.stuff', test.EXECUTABLE, bare=True) + +test.pass_test() diff --git a/tools/gyp/test/product/hello.c b/tools/gyp/test/product/hello.c new file mode 100644 index 00000000000..94798f3e751 --- /dev/null +++ b/tools/gyp/test/product/hello.c @@ -0,0 +1,15 @@ +/* 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. */ + +#include <stdio.h> + +int func1(void) { + return 42; +} + +int main(int argc, char *argv[]) { + printf("Hello, world!\n"); + printf("%d\n", func1()); + return 0; +} diff --git a/tools/gyp/test/product/product.gyp b/tools/gyp/test/product/product.gyp new file mode 100644 index 00000000000..c25eaaacb51 --- /dev/null +++ b/tools/gyp/test/product/product.gyp @@ -0,0 +1,128 @@ +# 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': 'hello1', + 'product_name': 'alt1', + 'type': 'executable', + 'sources': [ + 'hello.c', + ], + }, + { + 'target_name': 'hello2', + 'product_extension': 'stuff', + 'type': 'executable', + 'sources': [ + 'hello.c', + ], + }, + { + 'target_name': 'hello3', + 'product_name': 'alt3', + 'product_extension': 'stuff', + 'product_prefix': 'yo', + 'type': 'executable', + 'sources': [ + 'hello.c', + ], + }, + + { + 'target_name': 'hello4', + 'product_name': 'alt4', + 'type': 'shared_library', + 'sources': [ + 'hello.c', + ], + }, + { + 'target_name': 'hello5', + 'product_extension': 'stuff', + 'type': 'shared_library', + 'sources': [ + 'hello.c', + ], + }, + { + 'target_name': 'hello6', + 'product_name': 'alt6', + 'product_extension': 'stuff', + 'product_prefix': 'yo', + 'type': 'shared_library', + 'sources': [ + 'hello.c', + ], + }, + + { + 'target_name': 'hello7', + 'product_name': 'alt7', + 'type': 'static_library', + 'sources': [ + 'hello.c', + ], + }, + { + 'target_name': 'hello8', + 'product_extension': 'stuff', + 'type': 'static_library', + 'sources': [ + 'hello.c', + ], + }, + { + 'target_name': 'hello9', + 'product_name': 'alt9', + 'product_extension': 'stuff', + 'product_prefix': 'yo', + 'type': 'static_library', + 'sources': [ + 'hello.c', + ], + }, + { + 'target_name': 'hello10', + 'product_name': 'alt10', + 'product_extension': 'stuff', + 'product_prefix': 'yo', + 'product_dir': '<(PRODUCT_DIR)/bob', + 'type': 'executable', + 'sources': [ + 'hello.c', + ], + }, + { + 'target_name': 'hello11', + 'product_name': 'alt11', + 'product_extension': 'stuff', + 'product_prefix': 'yo', + 'product_dir': '<(PRODUCT_DIR)/bob', + 'type': 'shared_library', + 'sources': [ + 'hello.c', + ], + }, + { + 'target_name': 'hello12', + 'product_name': 'alt12', + 'product_extension': 'stuff', + 'product_prefix': 'yo', + 'product_dir': '<(PRODUCT_DIR)/bob', + 'type': 'static_library', + 'sources': [ + 'hello.c', + ], + }, + ], + 'conditions': [ + ['OS=="linux"', { + 'target_defaults': { + 'cflags': ['-fPIC'], + }, + }], + ], +} diff --git a/tools/gyp/test/rules-dirname/gyptest-dirname.py b/tools/gyp/test/rules-dirname/gyptest-dirname.py new file mode 100755 index 00000000000..6e684a4c42f --- /dev/null +++ b/tools/gyp/test/rules-dirname/gyptest-dirname.py @@ -0,0 +1,38 @@ +#!/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 simple rules when using an explicit build target of 'all'. +""" + +import TestGyp + +test = TestGyp.TestGyp(formats=['make', 'ninja', 'xcode']) + +test.run_gyp('actions.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('actions.gyp', chdir='relocate/src') + +expect = """\ +hi c +hello baz +""" +if test.format == 'xcode': + chdir = 'relocate/src/subdir' +else: + chdir = 'relocate/src' +test.run_built_executable('gencc_int_output', chdir=chdir, stdout=expect) + +if test.format == 'msvs': + test.must_exist('relocate/src/subdir/foo/bar/baz.printed') + test.must_exist('relocate/src/subdir/a/b/c.printed') +else: + test.must_match('relocate/src/subdir/foo/bar/baz.printed', 'foo/bar') + test.must_match('relocate/src/subdir/a/b/c.printed', 'a/b') + +test.pass_test() diff --git a/tools/gyp/test/rules-dirname/src/actions.gyp b/tools/gyp/test/rules-dirname/src/actions.gyp new file mode 100644 index 00000000000..c5693c6c9e1 --- /dev/null +++ b/tools/gyp/test/rules-dirname/src/actions.gyp @@ -0,0 +1,15 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'pull_in_all_actions', + 'type': 'none', + 'dependencies': [ + 'subdir/input-rule-dirname.gyp:*', + ], + }, + ], +} diff --git a/tools/gyp/test/rules-dirname/src/copy-file.py b/tools/gyp/test/rules-dirname/src/copy-file.py new file mode 100755 index 00000000000..9774ccc9607 --- /dev/null +++ b/tools/gyp/test/rules-dirname/src/copy-file.py @@ -0,0 +1,11 @@ +#!/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 + +contents = open(sys.argv[1], 'r').read() +open(sys.argv[2], 'wb').write(contents) + +sys.exit(0) diff --git a/tools/gyp/test/rules-dirname/src/subdir/a/b/c.gencc b/tools/gyp/test/rules-dirname/src/subdir/a/b/c.gencc new file mode 100644 index 00000000000..a4c8eea95f3 --- /dev/null +++ b/tools/gyp/test/rules-dirname/src/subdir/a/b/c.gencc @@ -0,0 +1,11 @@ +// -*- mode: c++ -*- +#include <iostream> + +using std::cout; +using std::endl; + +namespace gen { + void c() { + cout << "hi c" << endl; + } +} diff --git a/tools/gyp/test/rules-dirname/src/subdir/a/b/c.printvars b/tools/gyp/test/rules-dirname/src/subdir/a/b/c.printvars new file mode 100644 index 00000000000..cc4561dc414 --- /dev/null +++ b/tools/gyp/test/rules-dirname/src/subdir/a/b/c.printvars @@ -0,0 +1 @@ +# Empty file for testing build rules diff --git a/tools/gyp/test/rules-dirname/src/subdir/foo/bar/baz.gencc b/tools/gyp/test/rules-dirname/src/subdir/foo/bar/baz.gencc new file mode 100644 index 00000000000..ff01c2ee503 --- /dev/null +++ b/tools/gyp/test/rules-dirname/src/subdir/foo/bar/baz.gencc @@ -0,0 +1,11 @@ +// -*- mode: c++ -*- +#include <iostream> + +using std::cout; +using std::endl; + +namespace gen { + void baz() { + cout << "hello baz" << endl; + } +} diff --git a/tools/gyp/test/rules-dirname/src/subdir/foo/bar/baz.printvars b/tools/gyp/test/rules-dirname/src/subdir/foo/bar/baz.printvars new file mode 100644 index 00000000000..cc4561dc414 --- /dev/null +++ b/tools/gyp/test/rules-dirname/src/subdir/foo/bar/baz.printvars @@ -0,0 +1 @@ +# Empty file for testing build rules diff --git a/tools/gyp/test/rules-dirname/src/subdir/input-rule-dirname.gyp b/tools/gyp/test/rules-dirname/src/subdir/input-rule-dirname.gyp new file mode 100644 index 00000000000..96e32efa7a4 --- /dev/null +++ b/tools/gyp/test/rules-dirname/src/subdir/input-rule-dirname.gyp @@ -0,0 +1,92 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'print_rule_input_path', + 'type': 'none', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'foo/bar/baz.printvars', + 'a/b/c.printvars', + ], + 'rules': [ + { + 'rule_name': 'printvars', + 'extension': 'printvars', + 'inputs': [ + 'printvars.py', + ], + 'outputs': [ + '<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).printed', + ], + 'action': [ + 'python', '<@(_inputs)', '<(RULE_INPUT_DIRNAME)', '<@(_outputs)', + ], + }, + ], + }, + { + 'target_name': 'gencc_int_output', + 'type': 'executable', + 'msvs_cygwin_shell': 0, + 'msvs_cygwin_dirs': ['../../../../../../<(DEPTH)/third_party/cygwin'], + 'sources': [ + 'foo/bar/baz.gencc', + 'a/b/c.gencc', + 'main.cc', + ], + 'conditions': [ + ['OS=="win"', { + 'dependencies': [ + 'cygwin', + ], + }], + ], + 'rules': [ + { + 'rule_name': 'gencc', + 'extension': 'gencc', + 'msvs_external_rule': 1, + 'inputs': [ + '<(DEPTH)/copy-file.py', + ], + 'outputs': [ + '<(INTERMEDIATE_DIR)/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).cc', + ], + 'action': [ + 'python', '<@(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + ], + }, + ], + 'conditions': [ + ['OS=="win"', { + 'targets': [ + { + 'target_name': 'cygwin', + 'type': 'none', + 'actions': [ + { + 'action_name': 'setup_mount', + 'msvs_cygwin_shell': 0, + 'inputs': [ + '../../../../../../<(DEPTH)/third_party/cygwin/setup_mount.bat', + ], + # Visual Studio requires an output file, or else the + # custom build step won't run. + 'outputs': [ + '<(INTERMEDIATE_DIR)/_always_run_setup_mount.marker', + ], + 'action': ['', '<@(_inputs)'], + }, + ], + }, + ], + }], + ], +} diff --git a/tools/gyp/test/rules-dirname/src/subdir/main.cc b/tools/gyp/test/rules-dirname/src/subdir/main.cc new file mode 100644 index 00000000000..bacc568ad2a --- /dev/null +++ b/tools/gyp/test/rules-dirname/src/subdir/main.cc @@ -0,0 +1,12 @@ +// 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. +namespace gen { + extern void c(); + extern void baz(); +} + +int main() { + gen::c(); + gen::baz(); +} diff --git a/tools/gyp/test/rules-dirname/src/subdir/printvars.py b/tools/gyp/test/rules-dirname/src/subdir/printvars.py new file mode 100755 index 00000000000..ef3d92e8cf7 --- /dev/null +++ b/tools/gyp/test/rules-dirname/src/subdir/printvars.py @@ -0,0 +1,14 @@ +#!/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. + +""" +Prints interesting vars +""" + +import sys; + +out = open(sys.argv[2], 'w') +out.write(sys.argv[1]); diff --git a/tools/gyp/test/rules-rebuild/gyptest-all.py b/tools/gyp/test/rules-rebuild/gyptest-all.py new file mode 100755 index 00000000000..aaaa2a6e6f9 --- /dev/null +++ b/tools/gyp/test/rules-rebuild/gyptest-all.py @@ -0,0 +1,70 @@ +#!/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 a rule that generates multiple outputs rebuilds +correctly when the inputs change. +""" + +import TestGyp + +test = TestGyp.TestGyp(workdir='workarea_all') + +test.run_gyp('same_target.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + + +test.build('same_target.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello from main.c +Hello from prog1.in! +Hello from prog2.in! +""" + +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + +test.up_to_date('same_target.gyp', 'program', chdir='relocate/src') + + +test.sleep() +contents = test.read(['relocate', 'src', 'prog1.in']) +contents = contents.replace('!', ' AGAIN!') +test.write(['relocate', 'src', 'prog1.in'], contents) + +test.build('same_target.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello from main.c +Hello from prog1.in AGAIN! +Hello from prog2.in! +""" + +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + +test.up_to_date('same_target.gyp', 'program', chdir='relocate/src') + + +test.sleep() +contents = test.read(['relocate', 'src', 'prog2.in']) +contents = contents.replace('!', ' AGAIN!') +test.write(['relocate', 'src', 'prog2.in'], contents) + +test.build('same_target.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello from main.c +Hello from prog1.in AGAIN! +Hello from prog2.in AGAIN! +""" + +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + +test.up_to_date('same_target.gyp', 'program', chdir='relocate/src') + + +test.pass_test() diff --git a/tools/gyp/test/rules-rebuild/gyptest-default.py b/tools/gyp/test/rules-rebuild/gyptest-default.py new file mode 100755 index 00000000000..89694ef08b7 --- /dev/null +++ b/tools/gyp/test/rules-rebuild/gyptest-default.py @@ -0,0 +1,70 @@ +#!/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 a rule that generates multiple outputs rebuilds +correctly when the inputs change. +""" + +import TestGyp + +test = TestGyp.TestGyp(workdir='workarea_default') + +test.run_gyp('same_target.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + + +test.build('same_target.gyp', chdir='relocate/src') + +expect = """\ +Hello from main.c +Hello from prog1.in! +Hello from prog2.in! +""" + +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + +test.up_to_date('same_target.gyp', 'program', chdir='relocate/src') + + +test.sleep() +contents = test.read(['relocate', 'src', 'prog1.in']) +contents = contents.replace('!', ' AGAIN!') +test.write(['relocate', 'src', 'prog1.in'], contents) + +test.build('same_target.gyp', chdir='relocate/src') + +expect = """\ +Hello from main.c +Hello from prog1.in AGAIN! +Hello from prog2.in! +""" + +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + +test.up_to_date('same_target.gyp', 'program', chdir='relocate/src') + + +test.sleep() +contents = test.read(['relocate', 'src', 'prog2.in']) +contents = contents.replace('!', ' AGAIN!') +test.write(['relocate', 'src', 'prog2.in'], contents) + +test.build('same_target.gyp', chdir='relocate/src') + +expect = """\ +Hello from main.c +Hello from prog1.in AGAIN! +Hello from prog2.in AGAIN! +""" + +test.run_built_executable('program', chdir='relocate/src', stdout=expect) + +test.up_to_date('same_target.gyp', 'program', chdir='relocate/src') + + +test.pass_test() diff --git a/tools/gyp/test/rules-rebuild/src/main.c b/tools/gyp/test/rules-rebuild/src/main.c new file mode 100644 index 00000000000..bdc5ec875ea --- /dev/null +++ b/tools/gyp/test/rules-rebuild/src/main.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 main.c\n"); + prog1(); + prog2(); + return 0; +} diff --git a/tools/gyp/test/rules-rebuild/src/make-sources.py b/tools/gyp/test/rules-rebuild/src/make-sources.py new file mode 100755 index 00000000000..7ec022780c0 --- /dev/null +++ b/tools/gyp/test/rules-rebuild/src/make-sources.py @@ -0,0 +1,19 @@ +#!/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 + +assert len(sys.argv) == 4, sys.argv + +(in_file, c_file, h_file) = sys.argv[1:] + +def write_file(filename, contents): + open(filename, 'wb').write(contents) + +write_file(c_file, open(in_file, 'rb').read()) + +write_file(h_file, '#define NAME "%s"\n' % in_file) + +sys.exit(0) diff --git a/tools/gyp/test/rules-rebuild/src/prog1.in b/tools/gyp/test/rules-rebuild/src/prog1.in new file mode 100644 index 00000000000..191b00ef1e6 --- /dev/null +++ b/tools/gyp/test/rules-rebuild/src/prog1.in @@ -0,0 +1,7 @@ +#include <stdio.h> +#include "prog1.h" + +void prog1(void) +{ + printf("Hello from %s!\n", NAME); +} diff --git a/tools/gyp/test/rules-rebuild/src/prog2.in b/tools/gyp/test/rules-rebuild/src/prog2.in new file mode 100644 index 00000000000..7bfac5104c9 --- /dev/null +++ b/tools/gyp/test/rules-rebuild/src/prog2.in @@ -0,0 +1,7 @@ +#include <stdio.h> +#include "prog2.h" + +void prog2(void) +{ + printf("Hello from %s!\n", NAME); +} diff --git a/tools/gyp/test/rules-rebuild/src/same_target.gyp b/tools/gyp/test/rules-rebuild/src/same_target.gyp new file mode 100644 index 00000000000..22ba56056d2 --- /dev/null +++ b/tools/gyp/test/rules-rebuild/src/same_target.gyp @@ -0,0 +1,31 @@ +{ + 'targets': [ + { + 'target_name': 'program', + 'type': 'executable', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'main.c', + 'prog1.in', + 'prog2.in', + ], + 'rules': [ + { + 'rule_name': 'make_sources', + 'extension': 'in', + 'inputs': [ + 'make-sources.py', + ], + 'outputs': [ + '<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).c', + '<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).h', + ], + 'action': [ + 'python', '<(_inputs)', '<(RULE_INPUT_NAME)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/rules-variables/gyptest-rules-variables.py b/tools/gyp/test/rules-variables/gyptest-rules-variables.py new file mode 100755 index 00000000000..06ee5ca8382 --- /dev/null +++ b/tools/gyp/test/rules-variables/gyptest-rules-variables.py @@ -0,0 +1,26 @@ +#!/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 rules related variables are expanded. +""" + +import TestGyp + +test = TestGyp.TestGyp(formats=['ninja']) + +test.relocate('src', 'relocate/src') + +test.run_gyp('variables.gyp', chdir='relocate/src') + +test.build('variables.gyp', chdir='relocate/src') + +test.run_built_executable('all_rule_variables', + chdir='relocate/src', + stdout="input_root\ninput_dirname\ninput_path\n" + + "input_ext\ninput_name\n") + +test.pass_test() diff --git a/tools/gyp/test/rules-variables/src/input_ext.c b/tools/gyp/test/rules-variables/src/input_ext.c new file mode 100644 index 00000000000..f41e73ef8ad --- /dev/null +++ b/tools/gyp/test/rules-variables/src/input_ext.c @@ -0,0 +1,9 @@ +// 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 input_ext() { + printf("input_ext\n"); +} diff --git a/tools/gyp/test/rules-variables/src/input_name/test.c b/tools/gyp/test/rules-variables/src/input_name/test.c new file mode 100644 index 00000000000..e28b74d1158 --- /dev/null +++ b/tools/gyp/test/rules-variables/src/input_name/test.c @@ -0,0 +1,9 @@ +// 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 input_name() { + printf("input_name\n"); +} diff --git a/tools/gyp/test/rules-variables/src/input_path/subdir/test.c b/tools/gyp/test/rules-variables/src/input_path/subdir/test.c new file mode 100644 index 00000000000..403dbbda4cf --- /dev/null +++ b/tools/gyp/test/rules-variables/src/input_path/subdir/test.c @@ -0,0 +1,9 @@ +// 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 input_path() { + printf("input_path\n"); +} diff --git a/tools/gyp/test/rules-variables/src/subdir/input_dirname.c b/tools/gyp/test/rules-variables/src/subdir/input_dirname.c new file mode 100644 index 00000000000..40cecd87d9f --- /dev/null +++ b/tools/gyp/test/rules-variables/src/subdir/input_dirname.c @@ -0,0 +1,9 @@ +// 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 input_dirname() { + printf("input_dirname\n"); +} diff --git a/tools/gyp/test/rules-variables/src/subdir/test.c b/tools/gyp/test/rules-variables/src/subdir/test.c new file mode 100644 index 00000000000..6c0280b8adf --- /dev/null +++ b/tools/gyp/test/rules-variables/src/subdir/test.c @@ -0,0 +1,18 @@ +// 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. + +extern void input_root(); +extern void input_dirname(); +extern void input_path(); +extern void input_ext(); +extern void input_name(); + +int main() { + input_root(); + input_dirname(); + input_path(); + input_ext(); + input_name(); + return 0; +} diff --git a/tools/gyp/test/rules-variables/src/test.input_root.c b/tools/gyp/test/rules-variables/src/test.input_root.c new file mode 100644 index 00000000000..33a7740a5cb --- /dev/null +++ b/tools/gyp/test/rules-variables/src/test.input_root.c @@ -0,0 +1,9 @@ +// 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 input_root() { + printf("input_root\n"); +} diff --git a/tools/gyp/test/rules-variables/src/variables.gyp b/tools/gyp/test/rules-variables/src/variables.gyp new file mode 100644 index 00000000000..e40f3a85f55 --- /dev/null +++ b/tools/gyp/test/rules-variables/src/variables.gyp @@ -0,0 +1,30 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'all_rule_variables', + 'type': 'executable', + 'sources': [ + 'subdir/test.c', + ], + 'rules': [ + { + 'rule_name': 'rule_variable', + 'extension': 'c', + 'outputs': [ + '<(RULE_INPUT_ROOT).input_root.c', + '<(RULE_INPUT_DIRNAME)/input_dirname.c', + 'input_path/<(RULE_INPUT_PATH)', + 'input_ext<(RULE_INPUT_EXT)', + 'input_name/<(RULE_INPUT_NAME)', + ], + 'action': [], + 'process_outputs_as_sources': 1, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/rules/gyptest-all.py b/tools/gyp/test/rules/gyptest-all.py new file mode 100755 index 00000000000..63c3a10ba56 --- /dev/null +++ b/tools/gyp/test/rules/gyptest-all.py @@ -0,0 +1,66 @@ +#!/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 simple rules when using an explicit build target of 'all'. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('actions.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('actions.gyp', test.ALL, chdir='relocate/src') + +expect = """\ +Hello from program.c +Hello from function1.in +Hello from function2.in +""" + +if test.format == 'xcode': + chdir = 'relocate/src/subdir1' +else: + chdir = 'relocate/src' +test.run_built_executable('program', chdir=chdir, stdout=expect) + +expect = """\ +Hello from program.c +Hello from function3.in +""" + +if test.format == 'xcode': + chdir = 'relocate/src/subdir3' +else: + chdir = 'relocate/src' +test.run_built_executable('program2', chdir=chdir, stdout=expect) + +test.must_match('relocate/src/subdir2/file1.out', 'Hello from file1.in\n') +test.must_match('relocate/src/subdir2/file2.out', 'Hello from file2.in\n') + +test.must_match('relocate/src/subdir2/file1.out2', 'Hello from file1.in\n') +test.must_match('relocate/src/subdir2/file2.out2', 'Hello from file2.in\n') + +test.must_match('relocate/src/external/file1.external_rules.out', + 'Hello from file1.in\n') +test.must_match('relocate/src/external/file2.external_rules.out', + 'Hello from file2.in\n') + +expect = """\ +Hello from program.c +Got 41. +""" + +if test.format == 'xcode': + chdir = 'relocate/src/subdir4' +else: + chdir = 'relocate/src' +test.run_built_executable('program4', chdir=chdir, stdout=expect) + +test.pass_test() diff --git a/tools/gyp/test/rules/gyptest-default.py b/tools/gyp/test/rules/gyptest-default.py new file mode 100755 index 00000000000..117c53db034 --- /dev/null +++ b/tools/gyp/test/rules/gyptest-default.py @@ -0,0 +1,55 @@ +#!/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 simple rules when using an explicit build target of 'all'. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('actions.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('actions.gyp', chdir='relocate/src') + +expect = """\ +Hello from program.c +Hello from function1.in +Hello from function2.in +""" + +if test.format == 'xcode': + chdir = 'relocate/src/subdir1' +else: + chdir = 'relocate/src' +test.run_built_executable('program', chdir=chdir, stdout=expect) + +expect = """\ +Hello from program.c +Hello from function3.in +""" + +if test.format == 'xcode': + chdir = 'relocate/src/subdir3' +else: + chdir = 'relocate/src' +test.run_built_executable('program2', chdir=chdir, stdout=expect) + +test.must_match('relocate/src/subdir2/file1.out', 'Hello from file1.in\n') +test.must_match('relocate/src/subdir2/file2.out', 'Hello from file2.in\n') + +test.must_match('relocate/src/subdir2/file1.out2', 'Hello from file1.in\n') +test.must_match('relocate/src/subdir2/file2.out2', 'Hello from file2.in\n') + +test.must_match('relocate/src/external/file1.external_rules.out', + 'Hello from file1.in\n') +test.must_match('relocate/src/external/file2.external_rules.out', + 'Hello from file2.in\n') + +test.pass_test() diff --git a/tools/gyp/test/rules/gyptest-input-root.py b/tools/gyp/test/rules/gyptest-input-root.py new file mode 100755 index 00000000000..92bade6d48b --- /dev/null +++ b/tools/gyp/test/rules/gyptest-input-root.py @@ -0,0 +1,26 @@ +#!/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 that RULE_INPUT_ROOT isn't turned into a path in rule actions +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('input-root.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('input-root.gyp', target='test', chdir='relocate/src') + +expect = """\ +Hello somefile +""" + +test.run_built_executable('test', chdir='relocate/src', stdout=expect) +test.pass_test() diff --git a/tools/gyp/test/rules/src/actions.gyp b/tools/gyp/test/rules/src/actions.gyp new file mode 100644 index 00000000000..23e00cec61e --- /dev/null +++ b/tools/gyp/test/rules/src/actions.gyp @@ -0,0 +1,21 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'pull_in_all_actions', + 'type': 'none', + 'dependencies': [ + 'subdir1/executable.gyp:*', + 'subdir2/never_used.gyp:*', + 'subdir2/no_inputs.gyp:*', + 'subdir2/none.gyp:*', + 'subdir3/executable2.gyp:*', + 'subdir4/build-asm.gyp:*', + 'external/external.gyp:*', + ], + }, + ], +} diff --git a/tools/gyp/test/rules/src/copy-file.py b/tools/gyp/test/rules/src/copy-file.py new file mode 100755 index 00000000000..5a5feae1f21 --- /dev/null +++ b/tools/gyp/test/rules/src/copy-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 = open(sys.argv[1], 'r').read() +open(sys.argv[2], 'wb').write(contents) + +sys.exit(0) diff --git a/tools/gyp/test/rules/src/external/external.gyp b/tools/gyp/test/rules/src/external/external.gyp new file mode 100644 index 00000000000..004ec635991 --- /dev/null +++ b/tools/gyp/test/rules/src/external/external.gyp @@ -0,0 +1,66 @@ +# 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 that the case where there are no inputs (other than the +# file the rule applies to). +{ + 'target_defaults': { + 'msvs_cygwin_dirs': ['../../../../../../<(DEPTH)/third_party/cygwin'], + }, + 'targets': [ + { + 'target_name': 'external_rules', + 'type': 'none', + 'sources': [ + 'file1.in', + 'file2.in', + ], + 'conditions': [ + ['OS=="win"', { + 'dependencies': [ + 'cygwin', + ], + }], + ], + 'rules': [ + { + 'rule_name': 'copy_file', + 'extension': 'in', + 'msvs_external_rule': 1, + 'outputs': [ + '<(RULE_INPUT_ROOT).external_rules.out', + ], + 'action': [ + 'python', '../copy-file.py', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + }, + ], + }, + ], + 'conditions': [ + ['OS=="win"', { + 'targets': [ + { + 'target_name': 'cygwin', + 'type': 'none', + 'actions': [ + { + 'action_name': 'setup_mount', + 'msvs_cygwin_shell': 0, + 'inputs': [ + '../../../../../../<(DEPTH)/third_party/cygwin/setup_mount.bat', + ], + # Visual Studio requires an output file, or else the + # custom build step won't run. + 'outputs': [ + '<(INTERMEDIATE_DIR)/_always_run_setup_mount.marker', + ], + 'action': ['', '<@(_inputs)'], + }, + ], + }, + ], + }], + ], +} diff --git a/tools/gyp/test/rules/src/external/file1.in b/tools/gyp/test/rules/src/external/file1.in new file mode 100644 index 00000000000..86ac3ad389d --- /dev/null +++ b/tools/gyp/test/rules/src/external/file1.in @@ -0,0 +1 @@ +Hello from file1.in diff --git a/tools/gyp/test/rules/src/external/file2.in b/tools/gyp/test/rules/src/external/file2.in new file mode 100644 index 00000000000..bf83d8ecece --- /dev/null +++ b/tools/gyp/test/rules/src/external/file2.in @@ -0,0 +1 @@ +Hello from file2.in diff --git a/tools/gyp/test/rules/src/input-root.gyp b/tools/gyp/test/rules/src/input-root.gyp new file mode 100644 index 00000000000..b6600e767c8 --- /dev/null +++ b/tools/gyp/test/rules/src/input-root.gyp @@ -0,0 +1,24 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'test', + 'type': 'executable', + 'sources': [ 'somefile.ext', ], + 'rules': [{ + 'rule_name': 'rule', + 'extension': 'ext', + 'inputs': [ 'rule.py', ], + 'outputs': [ '<(RULE_INPUT_ROOT).cc', ], + 'action': [ 'python', 'rule.py', '<(RULE_INPUT_ROOT)', ], + 'message': 'Processing <(RULE_INPUT_PATH)', + 'process_outputs_as_sources': 1, + # Allows the test to run without hermetic cygwin on windows. + 'msvs_cygwin_shell': 0, + }], + }, + ], +} diff --git a/tools/gyp/test/rules/src/rule.py b/tools/gyp/test/rules/src/rule.py new file mode 100755 index 00000000000..8a1f36dedb1 --- /dev/null +++ b/tools/gyp/test/rules/src/rule.py @@ -0,0 +1,17 @@ +#!/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 + +f = open(sys.argv[1] + ".cc", "w") +f.write("""\ +#include <stdio.h> + +int main() { + puts("Hello %s"); + return 0; +} +""" % sys.argv[1]) +f.close() diff --git a/tools/gyp/test/rules/src/somefile.ext b/tools/gyp/test/rules/src/somefile.ext new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/tools/gyp/test/rules/src/somefile.ext diff --git a/tools/gyp/test/rules/src/subdir1/executable.gyp b/tools/gyp/test/rules/src/subdir1/executable.gyp new file mode 100644 index 00000000000..302857789d5 --- /dev/null +++ b/tools/gyp/test/rules/src/subdir1/executable.gyp @@ -0,0 +1,37 @@ +# 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', + 'function1.in', + 'function2.in', + ], + 'rules': [ + { + 'rule_name': 'copy_file', + 'extension': 'in', + 'inputs': [ + '../copy-file.py', + ], + 'outputs': [ + # TODO: fix SCons and Make to support generated files not + # in a variable-named path like <(INTERMEDIATE_DIR) + #'<(RULE_INPUT_ROOT).c', + '<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).c', + ], + 'action': [ + 'python', '<(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/rules/src/subdir1/function1.in b/tools/gyp/test/rules/src/subdir1/function1.in new file mode 100644 index 00000000000..60ff28949b9 --- /dev/null +++ b/tools/gyp/test/rules/src/subdir1/function1.in @@ -0,0 +1,6 @@ +#include <stdio.h> + +void function1(void) +{ + printf("Hello from function1.in\n"); +} diff --git a/tools/gyp/test/rules/src/subdir1/function2.in b/tools/gyp/test/rules/src/subdir1/function2.in new file mode 100644 index 00000000000..0fcfc03fdb9 --- /dev/null +++ b/tools/gyp/test/rules/src/subdir1/function2.in @@ -0,0 +1,6 @@ +#include <stdio.h> + +void function2(void) +{ + printf("Hello from function2.in\n"); +} diff --git a/tools/gyp/test/rules/src/subdir1/program.c b/tools/gyp/test/rules/src/subdir1/program.c new file mode 100644 index 00000000000..258d7f99ef0 --- /dev/null +++ b/tools/gyp/test/rules/src/subdir1/program.c @@ -0,0 +1,12 @@ +#include <stdio.h> + +extern void function1(void); +extern void function2(void); + +int main(int argc, char *argv[]) +{ + printf("Hello from program.c\n"); + function1(); + function2(); + return 0; +} diff --git a/tools/gyp/test/rules/src/subdir2/file1.in b/tools/gyp/test/rules/src/subdir2/file1.in new file mode 100644 index 00000000000..86ac3ad389d --- /dev/null +++ b/tools/gyp/test/rules/src/subdir2/file1.in @@ -0,0 +1 @@ +Hello from file1.in diff --git a/tools/gyp/test/rules/src/subdir2/file2.in b/tools/gyp/test/rules/src/subdir2/file2.in new file mode 100644 index 00000000000..bf83d8ecece --- /dev/null +++ b/tools/gyp/test/rules/src/subdir2/file2.in @@ -0,0 +1 @@ +Hello from file2.in diff --git a/tools/gyp/test/rules/src/subdir2/never_used.gyp b/tools/gyp/test/rules/src/subdir2/never_used.gyp new file mode 100644 index 00000000000..17f6f553710 --- /dev/null +++ b/tools/gyp/test/rules/src/subdir2/never_used.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. + +# Test that the case where there is a rule that doesn't apply to anything. +{ + 'targets': [ + { + 'target_name': 'files_no_input2', + 'type': 'none', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'file1.in', + 'file2.in', + ], + 'rules': [ + { + 'rule_name': 'copy_file3', + 'extension': 'in2', + 'outputs': [ + '<(RULE_INPUT_ROOT).out3', + ], + 'action': [ + 'python', '../copy-file.py', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/rules/src/subdir2/no_inputs.gyp b/tools/gyp/test/rules/src/subdir2/no_inputs.gyp new file mode 100644 index 00000000000..e61a1a3ff67 --- /dev/null +++ b/tools/gyp/test/rules/src/subdir2/no_inputs.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. + +# Test that the case where there are no inputs (other than the +# file the rule applies to). +{ + 'targets': [ + { + 'target_name': 'files_no_input', + 'type': 'none', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'file1.in', + 'file2.in', + ], + 'rules': [ + { + 'rule_name': 'copy_file2', + 'extension': 'in', + 'outputs': [ + '<(RULE_INPUT_ROOT).out2', + ], + 'action': [ + 'python', '../copy-file.py', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/rules/src/subdir2/none.gyp b/tools/gyp/test/rules/src/subdir2/none.gyp new file mode 100644 index 00000000000..38bcdabdf66 --- /dev/null +++ b/tools/gyp/test/rules/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': 'files', + 'type': 'none', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'file1.in', + 'file2.in', + ], + 'rules': [ + { + 'rule_name': 'copy_file', + 'extension': 'in', + 'inputs': [ + '../copy-file.py', + ], + 'outputs': [ + '<(RULE_INPUT_ROOT).out', + ], + 'action': [ + 'python', '<(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/rules/src/subdir3/executable2.gyp b/tools/gyp/test/rules/src/subdir3/executable2.gyp new file mode 100644 index 00000000000..a2a528fc7be --- /dev/null +++ b/tools/gyp/test/rules/src/subdir3/executable2.gyp @@ -0,0 +1,37 @@ +# 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. + +# This one tests that rules are properly written if extensions are different +# between the target's sources (program.c) and the generated files +# (function3.cc) + +{ + 'targets': [ + { + 'target_name': 'program2', + 'type': 'executable', + 'msvs_cygwin_shell': 0, + 'sources': [ + 'program.c', + 'function3.in', + ], + 'rules': [ + { + 'rule_name': 'copy_file', + 'extension': 'in', + 'inputs': [ + '../copy-file.py', + ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).cc', + ], + 'action': [ + 'python', '<(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + ], + }, + ], +} diff --git a/tools/gyp/test/rules/src/subdir3/function3.in b/tools/gyp/test/rules/src/subdir3/function3.in new file mode 100644 index 00000000000..99f46ab05e6 --- /dev/null +++ b/tools/gyp/test/rules/src/subdir3/function3.in @@ -0,0 +1,6 @@ +#include <stdio.h> + +extern "C" void function3(void) +{ + printf("Hello from function3.in\n"); +} diff --git a/tools/gyp/test/rules/src/subdir3/program.c b/tools/gyp/test/rules/src/subdir3/program.c new file mode 100644 index 00000000000..94f6c50912c --- /dev/null +++ b/tools/gyp/test/rules/src/subdir3/program.c @@ -0,0 +1,10 @@ +#include <stdio.h> + +extern void function3(void); + +int main(int argc, char *argv[]) +{ + printf("Hello from program.c\n"); + function3(); + return 0; +} diff --git a/tools/gyp/test/rules/src/subdir4/asm-function.asm b/tools/gyp/test/rules/src/subdir4/asm-function.asm new file mode 100644 index 00000000000..ed47cade959 --- /dev/null +++ b/tools/gyp/test/rules/src/subdir4/asm-function.asm @@ -0,0 +1,10 @@ +#if PLATFORM_WINDOWS || PLATFORM_MAC +# define IDENTIFIER(n) _##n +#else /* Linux */ +# define IDENTIFIER(n) n +#endif + +.globl IDENTIFIER(asm_function) +IDENTIFIER(asm_function): + movl $41, %eax + ret diff --git a/tools/gyp/test/rules/src/subdir4/build-asm.gyp b/tools/gyp/test/rules/src/subdir4/build-asm.gyp new file mode 100644 index 00000000000..be4a612d187 --- /dev/null +++ b/tools/gyp/test/rules/src/subdir4/build-asm.gyp @@ -0,0 +1,49 @@ +# 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. + +# This one tests that assembly files ended as .s and .S are compiled. + +{ + 'target_defaults': { + 'conditions': [ + ['OS=="win"', { + 'defines': ['PLATFORM_WIN'], + }], + ['OS=="mac"', { + 'defines': ['PLATFORM_MAC'], + }], + ['OS=="linux"', { + 'defines': ['PLATFORM_LINUX'], + }], + ], + }, + 'targets': [ + { + 'target_name': 'program4', + 'type': 'executable', + 'sources': [ + 'asm-function.asm', + 'program.c', + ], + 'conditions': [ + ['OS=="linux" or OS=="mac"', { + 'rules': [ + { + 'rule_name': 'convert_asm', + 'extension': 'asm', + 'inputs': [], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).S', + ], + 'action': [ + 'bash', '-c', 'mv <(RULE_INPUT_PATH) <@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + ], + }], + ], + }, + ], +} diff --git a/tools/gyp/test/rules/src/subdir4/program.c b/tools/gyp/test/rules/src/subdir4/program.c new file mode 100644 index 00000000000..42475906243 --- /dev/null +++ b/tools/gyp/test/rules/src/subdir4/program.c @@ -0,0 +1,19 @@ +#include <stdio.h> + +// Use the assembly function in linux and mac where it is built. +#if PLATFORM_LINUX || PLATFORM_MAC +extern int asm_function(void); +#else +int asm_function() { + return 41; +} +#endif + +int main(int argc, char *argv[]) +{ + fprintf(stdout, "Hello from program.c\n"); + fflush(stdout); + fprintf(stdout, "Got %d.\n", asm_function()); + fflush(stdout); + return 0; +} diff --git a/tools/gyp/test/same-gyp-name/gyptest-all.py b/tools/gyp/test/same-gyp-name/gyptest-all.py new file mode 100755 index 00000000000..76456885ed2 --- /dev/null +++ b/tools/gyp/test/same-gyp-name/gyptest-all.py @@ -0,0 +1,34 @@ +#!/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. + +""" +Build a .gyp that depends on 2 gyp files with the same name. +""" + +import TestGyp + +# This causes a problem on XCode (duplicate ID). +# See http://code.google.com/p/gyp/issues/detail?id=114 +test = TestGyp.TestGyp(formats=['msvs', 'scons', 'make']) + +test.run_gyp('all.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('all.gyp', test.ALL, chdir='relocate/src') + +expect1 = """\ +Hello from main1.cc +""" + +expect2 = """\ +Hello from main2.cc +""" + +test.run_built_executable('program1', chdir='relocate/src', stdout=expect1) +test.run_built_executable('program2', chdir='relocate/src', stdout=expect2) + +test.pass_test() diff --git a/tools/gyp/test/same-gyp-name/gyptest-default.py b/tools/gyp/test/same-gyp-name/gyptest-default.py new file mode 100755 index 00000000000..c1031f86bd1 --- /dev/null +++ b/tools/gyp/test/same-gyp-name/gyptest-default.py @@ -0,0 +1,34 @@ +#!/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. + +""" +Build a .gyp that depends on 2 gyp files with the same name. +""" + +import TestGyp + +# This causes a problem on XCode (duplicate ID). +# See http://code.google.com/p/gyp/issues/detail?id=114 +test = TestGyp.TestGyp(formats=['msvs', 'scons', 'make']) + +test.run_gyp('all.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('all.gyp', chdir='relocate/src') + +expect1 = """\ +Hello from main1.cc +""" + +expect2 = """\ +Hello from main2.cc +""" + +test.run_built_executable('program1', chdir='relocate/src', stdout=expect1) +test.run_built_executable('program2', chdir='relocate/src', stdout=expect2) + +test.pass_test() diff --git a/tools/gyp/test/same-gyp-name/src/all.gyp b/tools/gyp/test/same-gyp-name/src/all.gyp new file mode 100644 index 00000000000..229f02ea845 --- /dev/null +++ b/tools/gyp/test/same-gyp-name/src/all.gyp @@ -0,0 +1,16 @@ +# 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_exes', + 'type': 'none', + 'dependencies': [ + 'subdir1/executable.gyp:*', + 'subdir2/executable.gyp:*', + ], + }, + ], +} diff --git a/tools/gyp/test/same-gyp-name/src/subdir1/executable.gyp b/tools/gyp/test/same-gyp-name/src/subdir1/executable.gyp new file mode 100644 index 00000000000..82483b4c696 --- /dev/null +++ b/tools/gyp/test/same-gyp-name/src/subdir1/executable.gyp @@ -0,0 +1,15 @@ +# 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': 'program1', + 'type': 'executable', + 'sources': [ + 'main1.cc', + ], + }, + ], +} diff --git a/tools/gyp/test/same-gyp-name/src/subdir1/main1.cc b/tools/gyp/test/same-gyp-name/src/subdir1/main1.cc new file mode 100644 index 00000000000..3645558324d --- /dev/null +++ b/tools/gyp/test/same-gyp-name/src/subdir1/main1.cc @@ -0,0 +1,6 @@ +#include <stdio.h> + +int main() { + printf("Hello from main1.cc\n"); + return 0; +} diff --git a/tools/gyp/test/same-gyp-name/src/subdir2/executable.gyp b/tools/gyp/test/same-gyp-name/src/subdir2/executable.gyp new file mode 100644 index 00000000000..e3537013eb1 --- /dev/null +++ b/tools/gyp/test/same-gyp-name/src/subdir2/executable.gyp @@ -0,0 +1,15 @@ +# 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': 'program2', + 'type': 'executable', + 'sources': [ + 'main2.cc', + ], + }, + ], +} diff --git a/tools/gyp/test/same-gyp-name/src/subdir2/main2.cc b/tools/gyp/test/same-gyp-name/src/subdir2/main2.cc new file mode 100644 index 00000000000..0c724dee35f --- /dev/null +++ b/tools/gyp/test/same-gyp-name/src/subdir2/main2.cc @@ -0,0 +1,6 @@ +#include <stdio.h> + +int main() { + printf("Hello from main2.cc\n"); + return 0; +} diff --git a/tools/gyp/test/same-name/gyptest-all.py b/tools/gyp/test/same-name/gyptest-all.py new file mode 100755 index 00000000000..4c215027c2a --- /dev/null +++ b/tools/gyp/test/same-name/gyptest-all.py @@ -0,0 +1,34 @@ +#!/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. + +""" +Build a .gyp with two targets that share a common .c source file. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('all.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('all.gyp', test.ALL, chdir='relocate/src') + +expect1 = """\ +Hello from prog1.c +Hello prog1 from func.c +""" + +expect2 = """\ +Hello from prog2.c +Hello prog2 from func.c +""" + +test.run_built_executable('prog1', chdir='relocate/src', stdout=expect1) +test.run_built_executable('prog2', chdir='relocate/src', stdout=expect2) + +test.pass_test() diff --git a/tools/gyp/test/same-name/gyptest-default.py b/tools/gyp/test/same-name/gyptest-default.py new file mode 100755 index 00000000000..98757c26971 --- /dev/null +++ b/tools/gyp/test/same-name/gyptest-default.py @@ -0,0 +1,34 @@ +#!/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. + +""" +Build a .gyp with two targets that share a common .c source file. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('all.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('all.gyp', chdir='relocate/src') + +expect1 = """\ +Hello from prog1.c +Hello prog1 from func.c +""" + +expect2 = """\ +Hello from prog2.c +Hello prog2 from func.c +""" + +test.run_built_executable('prog1', chdir='relocate/src', stdout=expect1) +test.run_built_executable('prog2', chdir='relocate/src', stdout=expect2) + +test.pass_test() diff --git a/tools/gyp/test/same-name/src/all.gyp b/tools/gyp/test/same-name/src/all.gyp new file mode 100644 index 00000000000..44e1049821b --- /dev/null +++ b/tools/gyp/test/same-name/src/all.gyp @@ -0,0 +1,38 @@ +# 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': 'prog1', + 'type': 'executable', + 'defines': [ + 'PROG="prog1"', + ], + 'sources': [ + 'prog1.c', + 'func.c', + # Uncomment to test same-named files in different directories, + # which Visual Studio doesn't support. + #'subdir1/func.c', + #'subdir2/func.c', + ], + }, + { + 'target_name': 'prog2', + 'type': 'executable', + 'defines': [ + 'PROG="prog2"', + ], + 'sources': [ + 'prog2.c', + 'func.c', + # Uncomment to test same-named files in different directories, + # which Visual Studio doesn't support. + #'subdir1/func.c', + #'subdir2/func.c', + ], + }, + ], +} diff --git a/tools/gyp/test/same-name/src/func.c b/tools/gyp/test/same-name/src/func.c new file mode 100644 index 00000000000..e069c692a69 --- /dev/null +++ b/tools/gyp/test/same-name/src/func.c @@ -0,0 +1,6 @@ +#include <stdio.h> + +void func(void) +{ + printf("Hello %s from func.c\n", PROG); +} diff --git a/tools/gyp/test/same-name/src/prog1.c b/tools/gyp/test/same-name/src/prog1.c new file mode 100644 index 00000000000..c8940fedc3a --- /dev/null +++ b/tools/gyp/test/same-name/src/prog1.c @@ -0,0 +1,16 @@ +#include <stdio.h> + +extern void func(void); + +int main(int argc, char *argv[]) +{ + printf("Hello from prog1.c\n"); + func(); + /* + * Uncomment to test same-named files in different directories, + * which Visual Studio doesn't support. + subdir1_func(); + subdir2_func(); + */ + return 0; +} diff --git a/tools/gyp/test/same-name/src/prog2.c b/tools/gyp/test/same-name/src/prog2.c new file mode 100644 index 00000000000..e6605c2bd99 --- /dev/null +++ b/tools/gyp/test/same-name/src/prog2.c @@ -0,0 +1,16 @@ +#include <stdio.h> + +extern void func(void); + +int main(int argc, char *argv[]) +{ + printf("Hello from prog2.c\n"); + func(); + /* + * Uncomment to test same-named files in different directories, + * which Visual Studio doesn't support. + subdir1_func(); + subdir2_func(); + */ + return 0; +} diff --git a/tools/gyp/test/same-name/src/subdir1/func.c b/tools/gyp/test/same-name/src/subdir1/func.c new file mode 100644 index 00000000000..b73450d105e --- /dev/null +++ b/tools/gyp/test/same-name/src/subdir1/func.c @@ -0,0 +1,6 @@ +#include <stdio.h> + +void subdir1_func(void) +{ + printf("Hello %s from subdir1/func.c\n", PROG); +} diff --git a/tools/gyp/test/same-name/src/subdir2/func.c b/tools/gyp/test/same-name/src/subdir2/func.c new file mode 100644 index 00000000000..0248b5720e0 --- /dev/null +++ b/tools/gyp/test/same-name/src/subdir2/func.c @@ -0,0 +1,6 @@ +#include <stdio.h> + +void subdir2_func(void) +{ + printf("Hello %s from subdir2/func.c\n", PROG); +} diff --git a/tools/gyp/test/same-target-name/gyptest-same-target-name.py b/tools/gyp/test/same-target-name/gyptest-same-target-name.py new file mode 100755 index 00000000000..bfe5540f312 --- /dev/null +++ b/tools/gyp/test/same-target-name/gyptest-same-target-name.py @@ -0,0 +1,18 @@ +#!/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. + +""" +Check that duplicate targets in a directory gives an error. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +# Require that gyp files with duplicate targets spit out an error. +test.run_gyp('all.gyp', chdir='src', status=1, stderr=None) + +test.pass_test() diff --git a/tools/gyp/test/same-target-name/src/all.gyp b/tools/gyp/test/same-target-name/src/all.gyp new file mode 100644 index 00000000000..ac16976da6a --- /dev/null +++ b/tools/gyp/test/same-target-name/src/all.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': 'all_exes', + 'type': 'none', + 'dependencies': [ + 'executable1.gyp:*', + 'executable2.gyp:*', + ], + }, + ], +} diff --git a/tools/gyp/test/same-target-name/src/executable1.gyp b/tools/gyp/test/same-target-name/src/executable1.gyp new file mode 100644 index 00000000000..3c492c1b375 --- /dev/null +++ b/tools/gyp/test/same-target-name/src/executable1.gyp @@ -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. + +{ + 'targets': [ + { + 'target_name': 'program', + 'type': 'executable', + 'sources': [ + 'main1.cc', + ], + }, + ], +} diff --git a/tools/gyp/test/same-target-name/src/executable2.gyp b/tools/gyp/test/same-target-name/src/executable2.gyp new file mode 100644 index 00000000000..41e84a61c67 --- /dev/null +++ b/tools/gyp/test/same-target-name/src/executable2.gyp @@ -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. + +{ + 'targets': [ + { + 'target_name': 'program', + 'type': 'executable', + 'sources': [ + 'main2.cc', + ], + }, + ], +} diff --git a/tools/gyp/test/scons_tools/gyptest-tools.py b/tools/gyp/test/scons_tools/gyptest-tools.py new file mode 100755 index 00000000000..e97f5e6318f --- /dev/null +++ b/tools/gyp/test/scons_tools/gyptest-tools.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. + +""" +Verifies that a scons build picks up tools modules specified +via 'scons_tools' in the 'scons_settings' dictionary. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('tools.gyp') + +test.build('tools.gyp', test.ALL) + +if test.format == 'scons': + expect = "Hello, world!\n" +else: + expect = "" +test.run_built_executable('tools', stdout=expect) + +test.pass_test() diff --git a/tools/gyp/test/scons_tools/site_scons/site_tools/this_tool.py b/tools/gyp/test/scons_tools/site_scons/site_tools/this_tool.py new file mode 100644 index 00000000000..10c89476d7c --- /dev/null +++ b/tools/gyp/test/scons_tools/site_scons/site_tools/this_tool.py @@ -0,0 +1,10 @@ +# 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. + +# SCons "tool" module that simply sets a -D value. +def generate(env): + env['CPPDEFINES'] = ['THIS_TOOL'] + +def exists(env): + pass diff --git a/tools/gyp/test/scons_tools/tools.c b/tools/gyp/test/scons_tools/tools.c new file mode 100644 index 00000000000..78dc0e31ef4 --- /dev/null +++ b/tools/gyp/test/scons_tools/tools.c @@ -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. */ + +#include <stdio.h> + +int main(int argc, char *argv[]) +{ +#ifdef THIS_TOOL + printf("Hello, world!\n"); +#endif + return 0; +} diff --git a/tools/gyp/test/scons_tools/tools.gyp b/tools/gyp/test/scons_tools/tools.gyp new file mode 100644 index 00000000000..736ba3f2247 --- /dev/null +++ b/tools/gyp/test/scons_tools/tools.gyp @@ -0,0 +1,18 @@ +# 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': 'tools', + 'type': 'executable', + 'sources': [ + 'tools.c', + ], + }, + ], + 'scons_settings': { + 'tools': ['default', 'this_tool'], + }, +} diff --git a/tools/gyp/test/settings/gyptest-settings.py b/tools/gyp/test/settings/gyptest-settings.py new file mode 100755 index 00000000000..0ed81edbf2c --- /dev/null +++ b/tools/gyp/test/settings/gyptest-settings.py @@ -0,0 +1,18 @@ +#!/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. + +""" +Smoke-tests 'settings' blocks. +""" + +import TestGyp + +# 'settings' is only supported for make and scons (and will be removed there as +# well eventually). +test = TestGyp.TestGyp(formats=['make', 'scons']) +test.run_gyp('settings.gyp') +test.build('test.gyp', test.ALL) +test.pass_test() diff --git a/tools/gyp/test/settings/settings.gyp b/tools/gyp/test/settings/settings.gyp new file mode 100644 index 00000000000..5bde13ef278 --- /dev/null +++ b/tools/gyp/test/settings/settings.gyp @@ -0,0 +1,20 @@ +# Copyright (c) 2011 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'targets': [ + { + 'target_name': 'settings_target', + 'type': 'settings', + # In real life, this would set 'cflags' etc and other targets + # would depend on it. + }, + { + # This is needed so scons will actually generate a SConstruct + # (which it doesn't do for settings targets alone). + 'target_name': 'junk1', + 'type': 'none', + }, + ], +} diff --git a/tools/gyp/test/sibling/gyptest-all.py b/tools/gyp/test/sibling/gyptest-all.py new file mode 100755 index 00000000000..7e80cf82361 --- /dev/null +++ b/tools/gyp/test/sibling/gyptest-all.py @@ -0,0 +1,39 @@ +#!/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 TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('build/all.gyp', chdir='src') + +test.build('build/all.gyp', test.ALL, chdir='src') + +chdir = 'src/build' + +# The top-level Makefile is in the directory where gyp was run. +# TODO(mmoss) Should the Makefile go in the directory of the passed in .gyp +# file? What about when passing in multiple .gyp files? Would sub-project +# Makefiles (see http://codereview.chromium.org/340008 comments) solve this? +if test.format in ('make', 'ninja'): + chdir = 'src' + +if test.format == 'xcode': + chdir = 'src/prog1' +test.run_built_executable('prog1', + chdir=chdir, + stdout="Hello from prog1.c\n") + +if test.format == 'xcode': + chdir = 'src/prog2' +test.run_built_executable('prog2', + chdir=chdir, + stdout="Hello from prog2.c\n") + +test.pass_test() diff --git a/tools/gyp/test/sibling/gyptest-relocate.py b/tools/gyp/test/sibling/gyptest-relocate.py new file mode 100755 index 00000000000..7c86548186b --- /dev/null +++ b/tools/gyp/test/sibling/gyptest-relocate.py @@ -0,0 +1,41 @@ +#!/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 TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('build/all.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('build/all.gyp', test.ALL, chdir='relocate/src') + +chdir = 'relocate/src/build' + +# The top-level Makefile is in the directory where gyp was run. +# TODO(mmoss) Should the Makefile go in the directory of the passed in .gyp +# file? What about when passing in multiple .gyp files? Would sub-project +# Makefiles (see http://codereview.chromium.org/340008 comments) solve this? +if test.format in ('make', 'ninja'): + chdir = 'relocate/src' + +if test.format == 'xcode': + chdir = 'relocate/src/prog1' +test.run_built_executable('prog1', + chdir=chdir, + stdout="Hello from prog1.c\n") + +if test.format == 'xcode': + chdir = 'relocate/src/prog2' +test.run_built_executable('prog2', + chdir=chdir, + stdout="Hello from prog2.c\n") + +test.pass_test() diff --git a/tools/gyp/test/sibling/src/build/all.gyp b/tools/gyp/test/sibling/src/build/all.gyp new file mode 100644 index 00000000000..6eafdf99b1a --- /dev/null +++ b/tools/gyp/test/sibling/src/build/all.gyp @@ -0,0 +1,17 @@ +# 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': [ + { + # TODO(sgk): a target name of 'all' leads to a scons dependency cycle + 'target_name': 'All', + 'type': 'none', + 'dependencies': [ + '../prog1/prog1.gyp:*', + '../prog2/prog2.gyp:*', + ], + }, + ], +} diff --git a/tools/gyp/test/sibling/src/prog1/prog1.c b/tools/gyp/test/sibling/src/prog1/prog1.c new file mode 100644 index 00000000000..161ae8a38e7 --- /dev/null +++ b/tools/gyp/test/sibling/src/prog1/prog1.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main(int argc, char *argv[]) +{ + printf("Hello from prog1.c\n"); + return 0; +} diff --git a/tools/gyp/test/sibling/src/prog1/prog1.gyp b/tools/gyp/test/sibling/src/prog1/prog1.gyp new file mode 100644 index 00000000000..fbe38b97ad3 --- /dev/null +++ b/tools/gyp/test/sibling/src/prog1/prog1.gyp @@ -0,0 +1,15 @@ +# 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': 'prog1', + 'type': 'executable', + 'sources': [ + 'prog1.c', + ], + }, + ], +} diff --git a/tools/gyp/test/sibling/src/prog2/prog2.c b/tools/gyp/test/sibling/src/prog2/prog2.c new file mode 100644 index 00000000000..7635ae8c1ce --- /dev/null +++ b/tools/gyp/test/sibling/src/prog2/prog2.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main(int argc, char *argv[]) +{ + printf("Hello from prog2.c\n"); + return 0; +} diff --git a/tools/gyp/test/sibling/src/prog2/prog2.gyp b/tools/gyp/test/sibling/src/prog2/prog2.gyp new file mode 100644 index 00000000000..59345483692 --- /dev/null +++ b/tools/gyp/test/sibling/src/prog2/prog2.gyp @@ -0,0 +1,15 @@ +# 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': 'prog2', + 'type': 'executable', + 'sources': [ + 'prog2.c', + ], + }, + ], +} diff --git a/tools/gyp/test/small/gyptest-small.py b/tools/gyp/test/small/gyptest-small.py new file mode 100755 index 00000000000..a484cb36676 --- /dev/null +++ b/tools/gyp/test/small/gyptest-small.py @@ -0,0 +1,51 @@ +#!/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. + +""" +Runs small tests. +""" + +import imp +import os +import sys +import unittest + +import TestGyp + + +test = TestGyp.TestGyp() + +# Add pylib to the import path (so tests can import their dependencies). +# This is consistant with the path.append done in the top file "gyp". +sys.path.append(os.path.join(test._cwd, 'pylib')) + +# Add new test suites here. +files_to_test = [ + 'pylib/gyp/MSVSSettings_test.py', + 'pylib/gyp/easy_xml_test.py', + 'pylib/gyp/generator/msvs_test.py', +] + +# Collect all the suites from the above files. +suites = [] +for filename in files_to_test: + # Carve the module name out of the path. + name = os.path.splitext(os.path.split(filename)[1])[0] + # Find the complete module path. + full_filename = os.path.join(test._cwd, filename) + # Load the module. + module = imp.load_source(name, full_filename) + # Add it to the list of test suites. + suites.append(unittest.defaultTestLoader.loadTestsFromModule(module)) +# Create combined suite. +all_tests = unittest.TestSuite(suites) + +# Run all the tests. +result = unittest.TextTestRunner(verbosity=2).run(all_tests) +if result.failures or result.errors: + test.fail_test() + +test.pass_test() diff --git a/tools/gyp/test/subdirectory/gyptest-SYMROOT-all.py b/tools/gyp/test/subdirectory/gyptest-SYMROOT-all.py new file mode 100755 index 00000000000..b7509041aec --- /dev/null +++ b/tools/gyp/test/subdirectory/gyptest-SYMROOT-all.py @@ -0,0 +1,36 @@ +#!/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 building a target and a subsidiary dependent target from a +.gyp file in a subdirectory, without specifying an explicit output build +directory, and using the generated solution or project file at the top +of the tree as the entry point. + +The configuration sets the Xcode SYMROOT variable and uses --depth= +to make Xcode behave like the other build tools--that is, put all +built targets in a single output build directory at the top of the tree. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('prog1.gyp', '-Dset_symroot=1', '--depth=.', chdir='src') + +test.relocate('src', 'relocate/src') + +# Suppress the test infrastructure's setting SYMROOT on the command line. +test.build('prog1.gyp', test.ALL, SYMROOT=None, chdir='relocate/src') + +test.run_built_executable('prog1', + stdout="Hello from prog1.c\n", + chdir='relocate/src') +test.run_built_executable('prog2', + stdout="Hello from prog2.c\n", + chdir='relocate/src') + +test.pass_test() diff --git a/tools/gyp/test/subdirectory/gyptest-SYMROOT-default.py b/tools/gyp/test/subdirectory/gyptest-SYMROOT-default.py new file mode 100755 index 00000000000..c64ae7da39c --- /dev/null +++ b/tools/gyp/test/subdirectory/gyptest-SYMROOT-default.py @@ -0,0 +1,37 @@ +#!/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 building a target and a subsidiary dependent target from a +.gyp file in a subdirectory, without specifying an explicit output build +directory, and using the generated solution or project file at the top +of the tree as the entry point. + +The configuration sets the Xcode SYMROOT variable and uses --depth= +to make Xcode behave like the other build tools--that is, put all +built targets in a single output build directory at the top of the tree. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('prog1.gyp', '-Dset_symroot=1', '--depth=.', chdir='src') + +test.relocate('src', 'relocate/src') + +# Suppress the test infrastructure's setting SYMROOT on the command line. +test.build('prog1.gyp', SYMROOT=None, chdir='relocate/src') + +test.run_built_executable('prog1', + stdout="Hello from prog1.c\n", + chdir='relocate/src') + +test.run_built_executable('prog2', + stdout="Hello from prog2.c\n", + chdir='relocate/src') + +test.pass_test() diff --git a/tools/gyp/test/subdirectory/gyptest-subdir-all.py b/tools/gyp/test/subdirectory/gyptest-subdir-all.py new file mode 100755 index 00000000000..93344a075cf --- /dev/null +++ b/tools/gyp/test/subdirectory/gyptest-subdir-all.py @@ -0,0 +1,34 @@ +#!/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 building a subsidiary dependent target from a .gyp file in a +subdirectory, without specifying an explicit output build directory, +and using the subdirectory's solution or project file as the entry point. +""" + +import TestGyp +import errno + +# Ninja doesn't support running from subdirectories. +test = TestGyp.TestGyp(formats=['!ninja']) + +test.run_gyp('prog1.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +chdir = 'relocate/src/subdir' +target = test.ALL + +test.build('prog2.gyp', target, chdir=chdir) + +test.built_file_must_not_exist('prog1', type=test.EXECUTABLE, chdir=chdir) + +test.run_built_executable('prog2', + chdir=chdir, + stdout="Hello from prog2.c\n") + +test.pass_test() diff --git a/tools/gyp/test/subdirectory/gyptest-subdir-default.py b/tools/gyp/test/subdirectory/gyptest-subdir-default.py new file mode 100755 index 00000000000..92edcd217a5 --- /dev/null +++ b/tools/gyp/test/subdirectory/gyptest-subdir-default.py @@ -0,0 +1,33 @@ +#!/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 building a subsidiary dependent target from a .gyp file in a +subdirectory, without specifying an explicit output build directory, +and using the subdirectory's solution or project file as the entry point. +""" + +import TestGyp +import errno + +# Ninja doesn't support running from subdirectories. +test = TestGyp.TestGyp(formats=['!ninja']) + +test.run_gyp('prog1.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +chdir = 'relocate/src/subdir' + +test.build('prog2.gyp', chdir=chdir) + +test.built_file_must_not_exist('prog1', type=test.EXECUTABLE, chdir=chdir) + +test.run_built_executable('prog2', + chdir=chdir, + stdout="Hello from prog2.c\n") + +test.pass_test() diff --git a/tools/gyp/test/subdirectory/gyptest-subdir2-deep.py b/tools/gyp/test/subdirectory/gyptest-subdir2-deep.py new file mode 100755 index 00000000000..48548982f8c --- /dev/null +++ b/tools/gyp/test/subdirectory/gyptest-subdir2-deep.py @@ -0,0 +1,25 @@ +#!/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 building a project rooted several layers under src_dir works. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('prog3.gyp', chdir='src/subdir/subdir2') + +test.relocate('src', 'relocate/src') + +test.build('prog3.gyp', test.ALL, chdir='relocate/src/subdir/subdir2') + +test.run_built_executable('prog3', + chdir='relocate/src/subdir/subdir2', + stdout="Hello from prog3.c\n") + +test.pass_test() diff --git a/tools/gyp/test/subdirectory/gyptest-top-all.py b/tools/gyp/test/subdirectory/gyptest-top-all.py new file mode 100755 index 00000000000..a29a41b4d1f --- /dev/null +++ b/tools/gyp/test/subdirectory/gyptest-top-all.py @@ -0,0 +1,43 @@ +#!/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 building a target and a subsidiary dependent target from a +.gyp file in a subdirectory, without specifying an explicit output build +directory, and using the generated solution or project file at the top +of the tree as the entry point. + +There is a difference here in the default behavior of the underlying +build tools. Specifically, when building the entire "solution", Xcode +puts the output of each project relative to the .xcodeproj directory, +while Visual Studio (and our implementations of SCons and Make) put it +in a build directory relative to the "solution"--that is, the entry-point +from which you built the entire tree. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('prog1.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('prog1.gyp', test.ALL, chdir='relocate/src') + +test.run_built_executable('prog1', + stdout="Hello from prog1.c\n", + chdir='relocate/src') + +if test.format == 'xcode': + chdir = 'relocate/src/subdir' +else: + chdir = 'relocate/src' +test.run_built_executable('prog2', + chdir=chdir, + stdout="Hello from prog2.c\n") + +test.pass_test() diff --git a/tools/gyp/test/subdirectory/gyptest-top-default.py b/tools/gyp/test/subdirectory/gyptest-top-default.py new file mode 100755 index 00000000000..ac5f60dbccb --- /dev/null +++ b/tools/gyp/test/subdirectory/gyptest-top-default.py @@ -0,0 +1,43 @@ +#!/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 building a target and a subsidiary dependent target from a +.gyp file in a subdirectory, without specifying an explicit output build +directory, and using the generated solution or project file at the top +of the tree as the entry point. + +There is a difference here in the default behavior of the underlying +build tools. Specifically, when building the entire "solution", Xcode +puts the output of each project relative to the .xcodeproj directory, +while Visual Studio (and our implementations of SCons and Make) put it +in a build directory relative to the "solution"--that is, the entry-point +from which you built the entire tree. +""" + +import TestGyp + +test = TestGyp.TestGyp() + +test.run_gyp('prog1.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('prog1.gyp', chdir='relocate/src') + +test.run_built_executable('prog1', + stdout="Hello from prog1.c\n", + chdir='relocate/src') + +if test.format == 'xcode': + chdir = 'relocate/src/subdir' +else: + chdir = 'relocate/src' +test.run_built_executable('prog2', + chdir=chdir, + stdout="Hello from prog2.c\n") + +test.pass_test() diff --git a/tools/gyp/test/subdirectory/src/prog1.c b/tools/gyp/test/subdirectory/src/prog1.c new file mode 100644 index 00000000000..161ae8a38e7 --- /dev/null +++ b/tools/gyp/test/subdirectory/src/prog1.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main(int argc, char *argv[]) +{ + printf("Hello from prog1.c\n"); + return 0; +} diff --git a/tools/gyp/test/subdirectory/src/prog1.gyp b/tools/gyp/test/subdirectory/src/prog1.gyp new file mode 100644 index 00000000000..2aa66ce7d7f --- /dev/null +++ b/tools/gyp/test/subdirectory/src/prog1.gyp @@ -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. + +{ + 'includes': [ + 'symroot.gypi', + ], + 'targets': [ + { + 'target_name': 'prog1', + 'type': 'executable', + 'dependencies': [ + 'subdir/prog2.gyp:prog2', + ], + 'sources': [ + 'prog1.c', + ], + }, + ], +} diff --git a/tools/gyp/test/subdirectory/src/subdir/prog2.c b/tools/gyp/test/subdirectory/src/subdir/prog2.c new file mode 100644 index 00000000000..7635ae8c1ce --- /dev/null +++ b/tools/gyp/test/subdirectory/src/subdir/prog2.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main(int argc, char *argv[]) +{ + printf("Hello from prog2.c\n"); + return 0; +} diff --git a/tools/gyp/test/subdirectory/src/subdir/prog2.gyp b/tools/gyp/test/subdirectory/src/subdir/prog2.gyp new file mode 100644 index 00000000000..c6cd35f7f81 --- /dev/null +++ b/tools/gyp/test/subdirectory/src/subdir/prog2.gyp @@ -0,0 +1,18 @@ +# 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': [ + '../symroot.gypi', + ], + 'targets': [ + { + 'target_name': 'prog2', + 'type': 'executable', + 'sources': [ + 'prog2.c', + ], + }, + ], +} diff --git a/tools/gyp/test/subdirectory/src/subdir/subdir2/prog3.c b/tools/gyp/test/subdirectory/src/subdir/subdir2/prog3.c new file mode 100644 index 00000000000..7cfb0fa9482 --- /dev/null +++ b/tools/gyp/test/subdirectory/src/subdir/subdir2/prog3.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main(int argc, char *argv[]) +{ + printf("Hello from prog3.c\n"); + return 0; +} diff --git a/tools/gyp/test/subdirectory/src/subdir/subdir2/prog3.gyp b/tools/gyp/test/subdirectory/src/subdir/subdir2/prog3.gyp new file mode 100644 index 00000000000..b49fb591137 --- /dev/null +++ b/tools/gyp/test/subdirectory/src/subdir/subdir2/prog3.gyp @@ -0,0 +1,18 @@ +# 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': [ + '../../symroot.gypi', + ], + 'targets': [ + { + 'target_name': 'prog3', + 'type': 'executable', + 'sources': [ + 'prog3.c', + ], + }, + ], +} diff --git a/tools/gyp/test/subdirectory/src/symroot.gypi b/tools/gyp/test/subdirectory/src/symroot.gypi new file mode 100644 index 00000000000..519916427c9 --- /dev/null +++ b/tools/gyp/test/subdirectory/src/symroot.gypi @@ -0,0 +1,16 @@ +# 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. + +{ + 'variables': { + 'set_symroot%': 0, + }, + 'conditions': [ + ['set_symroot == 1', { + 'xcode_settings': { + 'SYMROOT': '<(DEPTH)/build', + }, + }], + ], +} diff --git a/tools/gyp/test/toolsets/gyptest-toolsets.py b/tools/gyp/test/toolsets/gyptest-toolsets.py new file mode 100755 index 00000000000..19737f83d0a --- /dev/null +++ b/tools/gyp/test/toolsets/gyptest-toolsets.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 that toolsets are correctly applied +""" + +import TestGyp + +# Multiple toolsets are currently only supported by the make generator. +test = TestGyp.TestGyp(formats=['make']) + +test.run_gyp('toolsets.gyp') + +test.build('toolsets.gyp', test.ALL) + +test.run_built_executable('host-main', stdout="Host\n") +test.run_built_executable('target-main', stdout="Target\n") + +test.pass_test() diff --git a/tools/gyp/test/toolsets/main.cc b/tools/gyp/test/toolsets/main.cc new file mode 100644 index 00000000000..0f353ae54f4 --- /dev/null +++ b/tools/gyp/test/toolsets/main.cc @@ -0,0 +1,11 @@ +/* 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. */ + +#include <stdio.h> + +const char *GetToolset(); + +int main(int argc, char *argv[]) { + printf("%s\n", GetToolset()); +} diff --git a/tools/gyp/test/toolsets/toolsets.cc b/tools/gyp/test/toolsets/toolsets.cc new file mode 100644 index 00000000000..a45fa029cb7 --- /dev/null +++ b/tools/gyp/test/toolsets/toolsets.cc @@ -0,0 +1,11 @@ +/* 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. */ + +const char *GetToolset() { +#ifdef TARGET + return "Target"; +#else + return "Host"; +#endif +} diff --git a/tools/gyp/test/toolsets/toolsets.gyp b/tools/gyp/test/toolsets/toolsets.gyp new file mode 100644 index 00000000000..e41b928de69 --- /dev/null +++ b/tools/gyp/test/toolsets/toolsets.gyp @@ -0,0 +1,38 @@ +# 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': { + 'target_conditions': [ + ['_toolset=="target"', {'defines': ['TARGET']}] + ] + }, + 'targets': [ + { + 'target_name': 'toolsets', + 'type': 'static_library', + 'toolsets': ['target', 'host'], + 'sources': [ + 'toolsets.cc', + ], + }, + { + 'target_name': 'host-main', + 'type': 'executable', + 'toolsets': ['host'], + 'dependencies': ['toolsets'], + 'sources': [ + 'main.cc', + ], + }, + { + 'target_name': 'target-main', + 'type': 'executable', + 'dependencies': ['toolsets'], + 'sources': [ + 'main.cc', + ], + }, + ], +} diff --git a/tools/gyp/test/toplevel-dir/gyptest-toplevel-dir.py b/tools/gyp/test/toplevel-dir/gyptest-toplevel-dir.py new file mode 100755 index 00000000000..61986cdaa50 --- /dev/null +++ b/tools/gyp/test/toplevel-dir/gyptest-toplevel-dir.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 building a subsidiary dependent target from a .gyp file in a +subdirectory, without specifying an explicit output build directory, +and using the subdirectory's solution or project file as the entry point. +""" + +import TestGyp +import errno + +test = TestGyp.TestGyp(formats=['make']) + +# We want our Makefile to be one dir up from main.gyp. +test.run_gyp('main.gyp', '--toplevel-dir=..', chdir='src/sub1') + +toplevel_dir = 'src' + +test.build('all', chdir=toplevel_dir) + +test.built_file_must_exist('prog1', type=test.EXECUTABLE, chdir=toplevel_dir) + +test.run_built_executable('prog1', + chdir=toplevel_dir, + stdout="Hello from prog1.c\n") + +test.pass_test() diff --git a/tools/gyp/test/toplevel-dir/src/sub1/main.gyp b/tools/gyp/test/toplevel-dir/src/sub1/main.gyp new file mode 100644 index 00000000000..33219010e48 --- /dev/null +++ b/tools/gyp/test/toplevel-dir/src/sub1/main.gyp @@ -0,0 +1,18 @@ +# 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': 'prog1', + 'type': 'executable', + 'dependencies': [ + '<(DEPTH)/../sub2/prog2.gyp:prog2', + ], + 'sources': [ + 'prog1.c', + ], + }, + ], +} diff --git a/tools/gyp/test/toplevel-dir/src/sub1/prog1.c b/tools/gyp/test/toplevel-dir/src/sub1/prog1.c new file mode 100644 index 00000000000..161ae8a38e7 --- /dev/null +++ b/tools/gyp/test/toplevel-dir/src/sub1/prog1.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main(int argc, char *argv[]) +{ + printf("Hello from prog1.c\n"); + return 0; +} diff --git a/tools/gyp/test/toplevel-dir/src/sub2/prog2.c b/tools/gyp/test/toplevel-dir/src/sub2/prog2.c new file mode 100644 index 00000000000..7635ae8c1ce --- /dev/null +++ b/tools/gyp/test/toplevel-dir/src/sub2/prog2.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main(int argc, char *argv[]) +{ + printf("Hello from prog2.c\n"); + return 0; +} diff --git a/tools/gyp/test/toplevel-dir/src/sub2/prog2.gyp b/tools/gyp/test/toplevel-dir/src/sub2/prog2.gyp new file mode 100644 index 00000000000..59345483692 --- /dev/null +++ b/tools/gyp/test/toplevel-dir/src/sub2/prog2.gyp @@ -0,0 +1,15 @@ +# 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': 'prog2', + 'type': 'executable', + 'sources': [ + 'prog2.c', + ], + }, + ], +} diff --git a/tools/gyp/test/variables/commands/commands-repeated.gyp b/tools/gyp/test/variables/commands/commands-repeated.gyp new file mode 100644 index 00000000000..822ae4f05d4 --- /dev/null +++ b/tools/gyp/test/variables/commands/commands-repeated.gyp @@ -0,0 +1,128 @@ +# 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. + +# This is a simple test file to make sure that variable substitution +# happens correctly. Run "run_tests.py" using python to generate the +# output from this gyp file. + +{ + 'variables': { + 'pi': 'import math; print math.pi', + 'third_letters': "<(other_letters)HIJK", + 'letters_list': 'ABCD', + 'other_letters': '<(letters_list)EFG', + 'check_included': '<(included_variable)', + 'check_lists': [ + '<(included_variable)', + '<(third_letters)', + ], + 'check_int': 5, + 'check_str_int': '6', + 'check_list_int': [ + 7, + '8', + 9, + ], + 'not_int_1': ' 10', + 'not_int_2': '11 ', + 'not_int_3': '012', + 'not_int_4': '13.0', + 'not_int_5': '+14', + 'negative_int': '-15', + 'zero_int': '0', + }, + 'includes': [ + 'commands.gypi', + ], + 'targets': [ + { + 'target_name': 'foo', + 'type': 'none', + 'variables': { + 'var1': '<!(["python", "-c", "<(pi)"])', + 'var2': '<!(python -c "print \'<!(python -c "<(pi)") <(letters_list)\'")', + 'var3': '<!(python -c "print \'<(letters_list)\'")', + 'var4': '<(<!(python -c "print \'letters_list\'"))', + 'var5': 'letters_', + 'var6': 'list', + 'var7': '<(check_int)', + 'var8': '<(check_int)blah', + 'var9': '<(check_str_int)', + 'var10': '<(check_list_int)', + 'var11': ['<@(check_list_int)'], + 'var12': '<(not_int_1)', + 'var13': '<(not_int_2)', + 'var14': '<(not_int_3)', + 'var15': '<(not_int_4)', + 'var16': '<(not_int_5)', + 'var17': '<(negative_int)', + 'var18': '<(zero_int)', + # A second set with different names to make sure they only execute the + # commands once. + 'var1prime': '<!(["python", "-c", "<(pi)"])', + 'var2prime': '<!(python -c "print \'<!(python -c "<(pi)") <(letters_list)\'")', + 'var3prime': '<!(python -c "print \'<(letters_list)\'")', + 'var4prime': '<(<!(python -c "print \'letters_list\'"))', + }, + 'actions': [ + { + 'action_name': 'test_action', + 'variables': { + 'var7': '<!(echo <(var5)<(var6))', + }, + 'inputs' : [ + '<(var2)', + ], + 'outputs': [ + '<(var4)', + '<(var7)', + ], + 'action': [ + 'echo', + '<(_inputs)', + '<(_outputs)', + ], + }, + # Again with the same vars to make sure the right things happened. + { + 'action_name': 'test_action_prime', + 'variables': { + 'var7': '<!(echo <(var5)<(var6))', + }, + 'inputs' : [ + '<(var2)', + ], + 'outputs': [ + '<(var4)', + '<(var7)', + ], + 'action': [ + 'echo', + '<(_inputs)', + '<(_outputs)', + ], + }, + # And one more time with the other vars... + { + 'action_name': 'test_action_prime_prime', + 'variables': { + 'var7': '<!(echo <(var5)<(var6))', + }, + 'inputs' : [ + '<(var2prime)', + ], + 'outputs': [ + '<(var4prime)', + '<(var7)', + ], + 'action': [ + 'echo', + '<(_inputs)', + '<(_outputs)', + ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/variables/commands/commands-repeated.gyp.stdout b/tools/gyp/test/variables/commands/commands-repeated.gyp.stdout new file mode 100644 index 00000000000..2a9f64f2f9b --- /dev/null +++ b/tools/gyp/test/variables/commands/commands-repeated.gyp.stdout @@ -0,0 +1,405 @@ +GENERAL:__init__.py:356:main running with these options: +GENERAL:__init__.py:363:main check: None +GENERAL:__init__.py:363:main circular_check: True +GENERAL:__init__.py:363:main debug: ['variables', 'general'] +GENERAL:__init__.py:363:main defines: None +GENERAL:__init__.py:361:main depth: '.' +GENERAL:__init__.py:363:main formats: ['gypd'] +GENERAL:__init__.py:363:main generator_flags: [] +GENERAL:__init__.py:363:main generator_output: None +GENERAL:__init__.py:363:main includes: None +GENERAL:__init__.py:363:main msvs_version: None +GENERAL:__init__.py:361:main suffix: '' +GENERAL:__init__.py:363:main toplevel_dir: None +GENERAL:__init__.py:363:main use_environment: True +GENERAL:__init__.py:417:main cmdline_default_variables: {} +GENERAL:__init__.py:443:main generator_flags: {} +VARIABLES:input.py:785:ExpandVariables Expanding '0' to 0 +VARIABLES:input.py:785:ExpandVariables Expanding '11 ' to '11 ' +VARIABLES:input.py:785:ExpandVariables Expanding '+14' to '+14' +VARIABLES:input.py:785:ExpandVariables Expanding '-15' to -15 +VARIABLES:input.py:785:ExpandVariables Expanding ' 10' to ' 10' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'letters_list', 'is_array': '', 'replace': '<(letters_list)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCDEFG', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCDEFG' to 'ABCDEFG' +VARIABLES:input.py:785:ExpandVariables Expanding '<(letters_list)EFG' to 'ABCDEFG' +VARIABLES:input.py:785:ExpandVariables Expanding '012' to '012' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'other_letters', 'is_array': '', 'replace': '<(other_letters)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'other_letters' to 'other_letters' +VARIABLES:input.py:767:ExpandVariables Found output '<(letters_list)EFGHIJK', recursing. +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'letters_list', 'is_array': '', 'replace': '<(letters_list)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCDEFGHIJK', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCDEFGHIJK' to 'ABCDEFGHIJK' +VARIABLES:input.py:785:ExpandVariables Expanding '<(letters_list)EFGHIJK' to 'ABCDEFGHIJK' +VARIABLES:input.py:785:ExpandVariables Expanding '<(other_letters)HIJK' to 'ABCDEFGHIJK' +VARIABLES:input.py:785:ExpandVariables Expanding 'XYZ' to 'XYZ' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '13.0' to '13.0' +VARIABLES:input.py:785:ExpandVariables Expanding 'import math; print math.pi' to 'import math; print math.pi' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'included_variable', 'is_array': '', 'replace': '<(included_variable)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'included_variable' to 'included_variable' +VARIABLES:input.py:767:ExpandVariables Found output 'XYZ', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'XYZ' to 'XYZ' +VARIABLES:input.py:785:ExpandVariables Expanding '<(included_variable)' to 'XYZ' +VARIABLES:input.py:785:ExpandVariables Expanding '6' to 6 +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'included_variable', 'is_array': '', 'replace': '<(included_variable)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'included_variable' to 'included_variable' +VARIABLES:input.py:767:ExpandVariables Found output 'XYZ', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'XYZ' to 'XYZ' +VARIABLES:input.py:785:ExpandVariables Expanding '<(included_variable)' to 'XYZ' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'third_letters', 'is_array': '', 'replace': '<(third_letters)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'third_letters' to 'third_letters' +VARIABLES:input.py:767:ExpandVariables Found output '<(other_letters)HIJK', recursing. +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'other_letters', 'is_array': '', 'replace': '<(other_letters)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'other_letters' to 'other_letters' +VARIABLES:input.py:767:ExpandVariables Found output '<(letters_list)EFGHIJK', recursing. +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'letters_list', 'is_array': '', 'replace': '<(letters_list)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCDEFGHIJK', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCDEFGHIJK' to 'ABCDEFGHIJK' +VARIABLES:input.py:785:ExpandVariables Expanding '<(letters_list)EFGHIJK' to 'ABCDEFGHIJK' +VARIABLES:input.py:785:ExpandVariables Expanding '<(other_letters)HIJK' to 'ABCDEFGHIJK' +VARIABLES:input.py:785:ExpandVariables Expanding '<(third_letters)' to 'ABCDEFGHIJK' +VARIABLES:input.py:785:ExpandVariables Expanding '8' to 8 +VARIABLES:input.py:785:ExpandVariables Expanding '.' to '.' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'letters_list', 'is_array': '', 'replace': '<(letters_list)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'python -c "print \'<!(python -c "<(pi', 'is_array': '', 'replace': '<!(python -c "print \'<!(python -c "<(pi)', 'type': '<!', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'python -c "<(pi', 'is_array': '', 'replace': '<!(python -c "<(pi)', 'type': '<!', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'pi', 'is_array': '', 'replace': '<(pi)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'pi' to 'pi' +VARIABLES:input.py:767:ExpandVariables Found output 'python -c "import math; print math.pi"', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "import math; print math.pi"' to 'python -c "import math; print math.pi"' +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "<(pi)"' to 'python -c "import math; print math.pi"' +VARIABLES:input.py:660:ExpandVariables Executing command 'python -c "import math; print math.pi"' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output 'python -c "print \'3.14159265359 ABCD\'"', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "print \'3.14159265359 ABCD\'"' to 'python -c "print \'3.14159265359 ABCD\'"' +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "print \'<!(python -c "<(pi)") ABCD\'"' to 'python -c "print \'3.14159265359 ABCD\'"' +VARIABLES:input.py:660:ExpandVariables Executing command 'python -c "print '3.14159265359 ABCD'"' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output '3.14159265359 ABCD', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359 ABCD' to '3.14159265359 ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '<!(python -c "print \'<!(python -c "<(pi)") <(letters_list)\'")' to '3.14159265359 ABCD' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': '"python", "-c", "<(pi', 'is_array': '[', 'replace': '<!(["python", "-c", "<(pi)', 'type': '<!', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'pi', 'is_array': '', 'replace': '<(pi)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'pi' to 'pi' +VARIABLES:input.py:767:ExpandVariables Found output '["python", "-c", "import math; print math.pi"]', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '["python", "-c", "import math; print math.pi"]' to '["python", "-c", "import math; print math.pi"]' +VARIABLES:input.py:785:ExpandVariables Expanding '["python", "-c", "<(pi)"]' to '["python", "-c", "import math; print math.pi"]' +VARIABLES:input.py:660:ExpandVariables Executing command '['python', '-c', 'import math; print math.pi']' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output '3.14159265359', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359' to '3.14159265359' +VARIABLES:input.py:785:ExpandVariables Expanding '<!(["python", "-c", "<(pi)"])' to '3.14159265359' +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_' to 'letters_' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': '<!(python -c "print \'letters_list\'"', 'is_array': '', 'replace': '<(<!(python -c "print \'letters_list\'")', 'type': '<', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'python -c "print \'letters_list\'"', 'is_array': '', 'replace': '<!(python -c "print \'letters_list\'")', 'type': '<!', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "print \'letters_list\'"' to 'python -c "print \'letters_list\'"' +VARIABLES:input.py:660:ExpandVariables Executing command 'python -c "print 'letters_list'"' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output 'letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '<!(python -c "print \'letters_list\'")' to 'letters_list' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCD', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '<(<!(python -c "print \'letters_list\'"))' to 'ABCD' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'check_int', 'is_array': '', 'replace': '<(check_int)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'check_int' to 'check_int' +VARIABLES:input.py:767:ExpandVariables Found output '5', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '5' to 5 +VARIABLES:input.py:785:ExpandVariables Expanding '<(check_int)' to 5 +VARIABLES:input.py:785:ExpandVariables Expanding 'list' to 'list' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': '"python", "-c", "<(pi', 'is_array': '[', 'replace': '<!(["python", "-c", "<(pi)', 'type': '<!', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'pi', 'is_array': '', 'replace': '<(pi)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'pi' to 'pi' +VARIABLES:input.py:767:ExpandVariables Found output '["python", "-c", "import math; print math.pi"]', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '["python", "-c", "import math; print math.pi"]' to '["python", "-c", "import math; print math.pi"]' +VARIABLES:input.py:785:ExpandVariables Expanding '["python", "-c", "<(pi)"]' to '["python", "-c", "import math; print math.pi"]' +VARIABLES:input.py:705:ExpandVariables Had cache value for command '['python', '-c', 'import math; print math.pi']' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output '3.14159265359', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359' to '3.14159265359' +VARIABLES:input.py:785:ExpandVariables Expanding '<!(["python", "-c", "<(pi)"])' to '3.14159265359' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'python -c "print \'<(letters_list', 'is_array': '', 'replace': '<!(python -c "print \'<(letters_list)', 'type': '<!', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'letters_list', 'is_array': '', 'replace': '<(letters_list)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:767:ExpandVariables Found output 'python -c "print \'ABCD\'"', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "print \'ABCD\'"' to 'python -c "print \'ABCD\'"' +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "print \'<(letters_list)\'"' to 'python -c "print \'ABCD\'"' +VARIABLES:input.py:660:ExpandVariables Executing command 'python -c "print 'ABCD'"' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCD', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '<!(python -c "print \'<(letters_list)\'")' to 'ABCD' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'letters_list', 'is_array': '', 'replace': '<(letters_list)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'python -c "print \'<!(python -c "<(pi', 'is_array': '', 'replace': '<!(python -c "print \'<!(python -c "<(pi)', 'type': '<!', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'python -c "<(pi', 'is_array': '', 'replace': '<!(python -c "<(pi)', 'type': '<!', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'pi', 'is_array': '', 'replace': '<(pi)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'pi' to 'pi' +VARIABLES:input.py:767:ExpandVariables Found output 'python -c "import math; print math.pi"', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "import math; print math.pi"' to 'python -c "import math; print math.pi"' +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "<(pi)"' to 'python -c "import math; print math.pi"' +VARIABLES:input.py:705:ExpandVariables Had cache value for command 'python -c "import math; print math.pi"' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output 'python -c "print \'3.14159265359 ABCD\'"', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "print \'3.14159265359 ABCD\'"' to 'python -c "print \'3.14159265359 ABCD\'"' +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "print \'<!(python -c "<(pi)") ABCD\'"' to 'python -c "print \'3.14159265359 ABCD\'"' +VARIABLES:input.py:705:ExpandVariables Had cache value for command 'python -c "print '3.14159265359 ABCD'"' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output '3.14159265359 ABCD', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359 ABCD' to '3.14159265359 ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '<!(python -c "print \'<!(python -c "<(pi)") <(letters_list)\'")' to '3.14159265359 ABCD' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'check_str_int', 'is_array': '', 'replace': '<(check_str_int)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'check_str_int' to 'check_str_int' +VARIABLES:input.py:767:ExpandVariables Found output '6', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '6' to 6 +VARIABLES:input.py:785:ExpandVariables Expanding '<(check_str_int)' to 6 +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'check_int', 'is_array': '', 'replace': '<(check_int)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'check_int' to 'check_int' +VARIABLES:input.py:767:ExpandVariables Found output '5blah', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '5blah' to '5blah' +VARIABLES:input.py:785:ExpandVariables Expanding '<(check_int)blah' to '5blah' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': '<!(python -c "print \'letters_list\'"', 'is_array': '', 'replace': '<(<!(python -c "print \'letters_list\'")', 'type': '<', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'python -c "print \'letters_list\'"', 'is_array': '', 'replace': '<!(python -c "print \'letters_list\'")', 'type': '<!', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "print \'letters_list\'"' to 'python -c "print \'letters_list\'"' +VARIABLES:input.py:705:ExpandVariables Had cache value for command 'python -c "print 'letters_list'"' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output 'letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '<!(python -c "print \'letters_list\'")' to 'letters_list' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCD', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '<(<!(python -c "print \'letters_list\'"))' to 'ABCD' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'python -c "print \'<(letters_list', 'is_array': '', 'replace': '<!(python -c "print \'<(letters_list)', 'type': '<!', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'letters_list', 'is_array': '', 'replace': '<(letters_list)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:767:ExpandVariables Found output 'python -c "print \'ABCD\'"', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "print \'ABCD\'"' to 'python -c "print \'ABCD\'"' +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "print \'<(letters_list)\'"' to 'python -c "print \'ABCD\'"' +VARIABLES:input.py:705:ExpandVariables Had cache value for command 'python -c "print 'ABCD'"' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCD', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '<!(python -c "print \'<(letters_list)\'")' to 'ABCD' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'not_int_4', 'is_array': '', 'replace': '<(not_int_4)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'not_int_4' to 'not_int_4' +VARIABLES:input.py:767:ExpandVariables Found output '13.0', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '13.0' to '13.0' +VARIABLES:input.py:785:ExpandVariables Expanding '<(not_int_4)' to '13.0' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'not_int_3', 'is_array': '', 'replace': '<(not_int_3)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'not_int_3' to 'not_int_3' +VARIABLES:input.py:767:ExpandVariables Found output '012', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '012' to '012' +VARIABLES:input.py:785:ExpandVariables Expanding '<(not_int_3)' to '012' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'negative_int', 'is_array': '', 'replace': '<(negative_int)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'negative_int' to 'negative_int' +VARIABLES:input.py:767:ExpandVariables Found output '-15', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '-15' to -15 +VARIABLES:input.py:785:ExpandVariables Expanding '<(negative_int)' to -15 +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'not_int_5', 'is_array': '', 'replace': '<(not_int_5)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'not_int_5' to 'not_int_5' +VARIABLES:input.py:767:ExpandVariables Found output '+14', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '+14' to '+14' +VARIABLES:input.py:785:ExpandVariables Expanding '<(not_int_5)' to '+14' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'check_list_int', 'is_array': '', 'replace': '<(check_list_int)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'check_list_int' to 'check_list_int' +VARIABLES:input.py:767:ExpandVariables Found output '7 8 9', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '7 8 9' to '7 8 9' +VARIABLES:input.py:785:ExpandVariables Expanding '<(check_list_int)' to '7 8 9' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'not_int_2', 'is_array': '', 'replace': '<(not_int_2)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'not_int_2' to 'not_int_2' +VARIABLES:input.py:767:ExpandVariables Found output '11 ', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '11 ' to '11 ' +VARIABLES:input.py:785:ExpandVariables Expanding '<(not_int_2)' to '11 ' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'not_int_1', 'is_array': '', 'replace': '<(not_int_1)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'not_int_1' to 'not_int_1' +VARIABLES:input.py:767:ExpandVariables Found output ' 10', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding ' 10' to ' 10' +VARIABLES:input.py:785:ExpandVariables Expanding '<(not_int_1)' to ' 10' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'zero_int', 'is_array': '', 'replace': '<(zero_int)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'zero_int' to 'zero_int' +VARIABLES:input.py:767:ExpandVariables Found output '0', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '0' to 0 +VARIABLES:input.py:785:ExpandVariables Expanding '<(zero_int)' to 0 +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'check_list_int', 'is_array': '', 'replace': '<@(check_list_int)', 'type': '<@', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'check_list_int' to 'check_list_int' +VARIABLES:input.py:767:ExpandVariables Found output [7, 8, 9], recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 7 to 7 +VARIABLES:input.py:785:ExpandVariables Expanding 8 to 8 +VARIABLES:input.py:785:ExpandVariables Expanding 9 to 9 +VARIABLES:input.py:785:ExpandVariables Expanding '<@(check_list_int)' to [7, 8, 9] +VARIABLES:input.py:785:ExpandVariables Expanding 'foo' to 'foo' +VARIABLES:input.py:785:ExpandVariables Expanding 'target' to 'target' +VARIABLES:input.py:785:ExpandVariables Expanding 'none' to 'none' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var6', 'is_array': '', 'replace': '<(var6)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var6' to 'var6' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'echo <(var5', 'is_array': '', 'replace': '<!(echo <(var5)', 'type': '<!', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var5', 'is_array': '', 'replace': '<(var5)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var5' to 'var5' +VARIABLES:input.py:767:ExpandVariables Found output 'echo letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'echo letters_list' to 'echo letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding 'echo <(var5)list' to 'echo letters_list' +VARIABLES:input.py:660:ExpandVariables Executing command 'echo letters_list' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output 'letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '<!(echo <(var5)<(var6))' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding 'test_action' to 'test_action' +VARIABLES:input.py:785:ExpandVariables Expanding 'echo' to 'echo' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': '_inputs', 'is_array': '', 'replace': '<(_inputs)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding '_inputs' to '_inputs' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var2', 'is_array': '', 'replace': '<(var2)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var2' to 'var2' +VARIABLES:input.py:767:ExpandVariables Found output '3.14159265359 ABCD', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359 ABCD' to '3.14159265359 ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '<(var2)' to '3.14159265359 ABCD' +VARIABLES:input.py:767:ExpandVariables Found output '"3.14159265359 ABCD"', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '"3.14159265359 ABCD"' to '"3.14159265359 ABCD"' +VARIABLES:input.py:785:ExpandVariables Expanding '<(_inputs)' to '"3.14159265359 ABCD"' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': '_outputs', 'is_array': '', 'replace': '<(_outputs)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding '_outputs' to '_outputs' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var4', 'is_array': '', 'replace': '<(var4)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var4' to 'var4' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCD', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '<(var4)' to 'ABCD' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var7', 'is_array': '', 'replace': '<(var7)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var7' to 'var7' +VARIABLES:input.py:767:ExpandVariables Found output 'letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '<(var7)' to 'letters_list' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCD letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD letters_list' to 'ABCD letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '<(_outputs)' to 'ABCD letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359 ABCD' to '3.14159265359 ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var6', 'is_array': '', 'replace': '<(var6)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var6' to 'var6' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'echo <(var5', 'is_array': '', 'replace': '<!(echo <(var5)', 'type': '<!', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var5', 'is_array': '', 'replace': '<(var5)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var5' to 'var5' +VARIABLES:input.py:767:ExpandVariables Found output 'echo letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'echo letters_list' to 'echo letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding 'echo <(var5)list' to 'echo letters_list' +VARIABLES:input.py:705:ExpandVariables Had cache value for command 'echo letters_list' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output 'letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '<!(echo <(var5)<(var6))' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding 'test_action_prime' to 'test_action_prime' +VARIABLES:input.py:785:ExpandVariables Expanding 'echo' to 'echo' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': '_inputs', 'is_array': '', 'replace': '<(_inputs)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding '_inputs' to '_inputs' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var2', 'is_array': '', 'replace': '<(var2)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var2' to 'var2' +VARIABLES:input.py:767:ExpandVariables Found output '3.14159265359 ABCD', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359 ABCD' to '3.14159265359 ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '<(var2)' to '3.14159265359 ABCD' +VARIABLES:input.py:767:ExpandVariables Found output '"3.14159265359 ABCD"', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '"3.14159265359 ABCD"' to '"3.14159265359 ABCD"' +VARIABLES:input.py:785:ExpandVariables Expanding '<(_inputs)' to '"3.14159265359 ABCD"' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': '_outputs', 'is_array': '', 'replace': '<(_outputs)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding '_outputs' to '_outputs' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var4', 'is_array': '', 'replace': '<(var4)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var4' to 'var4' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCD', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '<(var4)' to 'ABCD' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var7', 'is_array': '', 'replace': '<(var7)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var7' to 'var7' +VARIABLES:input.py:767:ExpandVariables Found output 'letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '<(var7)' to 'letters_list' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCD letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD letters_list' to 'ABCD letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '<(_outputs)' to 'ABCD letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359 ABCD' to '3.14159265359 ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var6', 'is_array': '', 'replace': '<(var6)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var6' to 'var6' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'echo <(var5', 'is_array': '', 'replace': '<!(echo <(var5)', 'type': '<!', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var5', 'is_array': '', 'replace': '<(var5)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var5' to 'var5' +VARIABLES:input.py:767:ExpandVariables Found output 'echo letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'echo letters_list' to 'echo letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding 'echo <(var5)list' to 'echo letters_list' +VARIABLES:input.py:705:ExpandVariables Had cache value for command 'echo letters_list' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output 'letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '<!(echo <(var5)<(var6))' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding 'test_action_prime_prime' to 'test_action_prime_prime' +VARIABLES:input.py:785:ExpandVariables Expanding 'echo' to 'echo' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': '_inputs', 'is_array': '', 'replace': '<(_inputs)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding '_inputs' to '_inputs' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var2prime', 'is_array': '', 'replace': '<(var2prime)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var2prime' to 'var2prime' +VARIABLES:input.py:767:ExpandVariables Found output '3.14159265359 ABCD', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359 ABCD' to '3.14159265359 ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '<(var2prime)' to '3.14159265359 ABCD' +VARIABLES:input.py:767:ExpandVariables Found output '"3.14159265359 ABCD"', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '"3.14159265359 ABCD"' to '"3.14159265359 ABCD"' +VARIABLES:input.py:785:ExpandVariables Expanding '<(_inputs)' to '"3.14159265359 ABCD"' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': '_outputs', 'is_array': '', 'replace': '<(_outputs)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding '_outputs' to '_outputs' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var4prime', 'is_array': '', 'replace': '<(var4prime)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var4prime' to 'var4prime' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCD', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '<(var4prime)' to 'ABCD' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var7', 'is_array': '', 'replace': '<(var7)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var7' to 'var7' +VARIABLES:input.py:767:ExpandVariables Found output 'letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '<(var7)' to 'letters_list' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCD letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD letters_list' to 'ABCD letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '<(_outputs)' to 'ABCD letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359 ABCD' to '3.14159265359 ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding 'dummy' to 'dummy' +VARIABLES:input.py:785:ExpandVariables Expanding 'target' to 'target' +VARIABLES:input.py:785:ExpandVariables Expanding 'none' to 'none' +VARIABLES:input.py:785:ExpandVariables Expanding 'commands-repeated.gyp' to 'commands-repeated.gyp' +VARIABLES:input.py:785:ExpandVariables Expanding 'commands.gypi' to 'commands.gypi' +VARIABLES:input.py:785:ExpandVariables Expanding 'dummy' to 'dummy' +VARIABLES:input.py:785:ExpandVariables Expanding 'target' to 'target' +VARIABLES:input.py:785:ExpandVariables Expanding 'none' to 'none' +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359 ABCD' to '3.14159265359 ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359' to '3.14159265359' +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_' to 'letters_' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'list' to 'list' +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359' to '3.14159265359' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359 ABCD' to '3.14159265359 ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '5blah' to '5blah' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '13.0' to '13.0' +VARIABLES:input.py:785:ExpandVariables Expanding '012' to '012' +VARIABLES:input.py:785:ExpandVariables Expanding '+14' to '+14' +VARIABLES:input.py:785:ExpandVariables Expanding '7 8 9' to '7 8 9' +VARIABLES:input.py:785:ExpandVariables Expanding '11 ' to '11 ' +VARIABLES:input.py:785:ExpandVariables Expanding ' 10' to ' 10' +VARIABLES:input.py:785:ExpandVariables Expanding 'foo' to 'foo' +VARIABLES:input.py:785:ExpandVariables Expanding 'target' to 'target' +VARIABLES:input.py:785:ExpandVariables Expanding 'none' to 'none' +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding 'test_action' to 'test_action' +VARIABLES:input.py:785:ExpandVariables Expanding 'echo' to 'echo' +VARIABLES:input.py:785:ExpandVariables Expanding '"3.14159265359 ABCD"' to '"3.14159265359 ABCD"' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD letters_list' to 'ABCD letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359 ABCD' to '3.14159265359 ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding 'test_action_prime' to 'test_action_prime' +VARIABLES:input.py:785:ExpandVariables Expanding 'echo' to 'echo' +VARIABLES:input.py:785:ExpandVariables Expanding '"3.14159265359 ABCD"' to '"3.14159265359 ABCD"' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD letters_list' to 'ABCD letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359 ABCD' to '3.14159265359 ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding 'test_action_prime_prime' to 'test_action_prime_prime' +VARIABLES:input.py:785:ExpandVariables Expanding 'echo' to 'echo' +VARIABLES:input.py:785:ExpandVariables Expanding '"3.14159265359 ABCD"' to '"3.14159265359 ABCD"' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD letters_list' to 'ABCD letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359 ABCD' to '3.14159265359 ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' diff --git a/tools/gyp/test/variables/commands/commands-repeated.gypd.golden b/tools/gyp/test/variables/commands/commands-repeated.gypd.golden new file mode 100644 index 00000000000..96615b66314 --- /dev/null +++ b/tools/gyp/test/variables/commands/commands-repeated.gypd.golden @@ -0,0 +1,72 @@ +{'_DEPTH': '.', + 'included_files': ['commands-repeated.gyp', 'commands.gypi'], + 'targets': [{'actions': [{'action': ['echo', + '"3.14159265359 ABCD"', + 'ABCD letters_list'], + 'action_name': 'test_action', + 'inputs': ['3.14159265359 ABCD'], + 'outputs': ['ABCD', 'letters_list'], + 'variables': {'var7': 'letters_list'}}, + {'action': ['echo', + '"3.14159265359 ABCD"', + 'ABCD letters_list'], + 'action_name': 'test_action_prime', + 'inputs': ['3.14159265359 ABCD'], + 'outputs': ['ABCD', 'letters_list'], + 'variables': {'var7': 'letters_list'}}, + {'action': ['echo', + '"3.14159265359 ABCD"', + 'ABCD letters_list'], + 'action_name': 'test_action_prime_prime', + 'inputs': ['3.14159265359 ABCD'], + 'outputs': ['ABCD', 'letters_list'], + 'variables': {'var7': 'letters_list'}}], + 'configurations': {'Default': {}}, + 'default_configuration': 'Default', + 'target_name': 'foo', + 'toolset': 'target', + 'type': 'none', + 'variables': {'var1': '3.14159265359', + 'var10': '7 8 9', + 'var11': ['7', '8', '9'], + 'var12': ' 10', + 'var13': '11 ', + 'var14': '012', + 'var15': '13.0', + 'var16': '+14', + 'var17': '-15', + 'var18': '0', + 'var1prime': '3.14159265359', + 'var2': '3.14159265359 ABCD', + 'var2prime': '3.14159265359 ABCD', + 'var3': 'ABCD', + 'var3prime': 'ABCD', + 'var4': 'ABCD', + 'var4prime': 'ABCD', + 'var5': 'letters_', + 'var6': 'list', + 'var7': '5', + 'var8': '5blah', + 'var9': '6'}}, + {'configurations': {'Default': {}}, + 'default_configuration': 'Default', + 'target_name': 'dummy', + 'toolset': 'target', + 'type': 'none'}], + 'variables': {'check_included': 'XYZ', + 'check_int': '5', + 'check_list_int': ['7', '8', '9'], + 'check_lists': ['XYZ', 'ABCDEFGHIJK'], + 'check_str_int': '6', + 'included_variable': 'XYZ', + 'letters_list': 'ABCD', + 'negative_int': '-15', + 'not_int_1': ' 10', + 'not_int_2': '11 ', + 'not_int_3': '012', + 'not_int_4': '13.0', + 'not_int_5': '+14', + 'other_letters': 'ABCDEFG', + 'pi': 'import math; print math.pi', + 'third_letters': 'ABCDEFGHIJK', + 'zero_int': '0'}} diff --git a/tools/gyp/test/variables/commands/commands.gyp b/tools/gyp/test/variables/commands/commands.gyp new file mode 100644 index 00000000000..113e4a279fd --- /dev/null +++ b/tools/gyp/test/variables/commands/commands.gyp @@ -0,0 +1,84 @@ +# 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. + +# This is a simple test file to make sure that variable substitution +# happens correctly. Run "run_tests.py" using python to generate the +# output from this gyp file. + +{ + 'variables': { + 'pi': 'import math; print math.pi', + 'third_letters': "<(other_letters)HIJK", + 'letters_list': 'ABCD', + 'other_letters': '<(letters_list)EFG', + 'check_included': '<(included_variable)', + 'check_lists': [ + '<(included_variable)', + '<(third_letters)', + ], + 'check_int': 5, + 'check_str_int': '6', + 'check_list_int': [ + 7, + '8', + 9, + ], + 'not_int_1': ' 10', + 'not_int_2': '11 ', + 'not_int_3': '012', + 'not_int_4': '13.0', + 'not_int_5': '+14', + 'negative_int': '-15', + 'zero_int': '0', + }, + 'includes': [ + 'commands.gypi', + ], + 'targets': [ + { + 'target_name': 'foo', + 'type': 'none', + 'variables': { + 'var1': '<!(["python", "-c", "<(pi)"])', + 'var2': '<!(python -c "print \'<!(python -c "<(pi)") <(letters_list)\'")', + 'var3': '<!(python -c "print \'<(letters_list)\'")', + 'var4': '<(<!(python -c "print \'letters_list\'"))', + 'var5': 'letters_', + 'var6': 'list', + 'var7': '<(check_int)', + 'var8': '<(check_int)blah', + 'var9': '<(check_str_int)', + 'var10': '<(check_list_int)', + 'var11': ['<@(check_list_int)'], + 'var12': '<(not_int_1)', + 'var13': '<(not_int_2)', + 'var14': '<(not_int_3)', + 'var15': '<(not_int_4)', + 'var16': '<(not_int_5)', + 'var17': '<(negative_int)', + 'var18': '<(zero_int)', + }, + 'actions': [ + { + 'action_name': 'test_action', + 'variables': { + 'var7': '<!(echo <(var5)<(var6))', + }, + 'inputs' : [ + '<(var2)', + ], + 'outputs': [ + '<(var4)', + '<(var7)', + ], + 'action': [ + 'echo', + '<(_inputs)', + '<(_outputs)', + ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/variables/commands/commands.gyp.ignore-env.stdout b/tools/gyp/test/variables/commands/commands.gyp.ignore-env.stdout new file mode 100644 index 00000000000..57c100a279a --- /dev/null +++ b/tools/gyp/test/variables/commands/commands.gyp.ignore-env.stdout @@ -0,0 +1,254 @@ +GENERAL:__init__.py:356:main running with these options: +GENERAL:__init__.py:363:main check: None +GENERAL:__init__.py:363:main circular_check: True +GENERAL:__init__.py:363:main debug: ['variables', 'general'] +GENERAL:__init__.py:363:main defines: None +GENERAL:__init__.py:361:main depth: '.' +GENERAL:__init__.py:363:main formats: ['gypd'] +GENERAL:__init__.py:363:main generator_flags: [] +GENERAL:__init__.py:363:main generator_output: None +GENERAL:__init__.py:363:main includes: None +GENERAL:__init__.py:363:main msvs_version: None +GENERAL:__init__.py:361:main suffix: '' +GENERAL:__init__.py:363:main toplevel_dir: None +GENERAL:__init__.py:363:main use_environment: False +GENERAL:__init__.py:417:main cmdline_default_variables: {} +GENERAL:__init__.py:443:main generator_flags: {} +VARIABLES:input.py:785:ExpandVariables Expanding '0' to 0 +VARIABLES:input.py:785:ExpandVariables Expanding '11 ' to '11 ' +VARIABLES:input.py:785:ExpandVariables Expanding '+14' to '+14' +VARIABLES:input.py:785:ExpandVariables Expanding '-15' to -15 +VARIABLES:input.py:785:ExpandVariables Expanding ' 10' to ' 10' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'letters_list', 'is_array': '', 'replace': '<(letters_list)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCDEFG', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCDEFG' to 'ABCDEFG' +VARIABLES:input.py:785:ExpandVariables Expanding '<(letters_list)EFG' to 'ABCDEFG' +VARIABLES:input.py:785:ExpandVariables Expanding '012' to '012' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'other_letters', 'is_array': '', 'replace': '<(other_letters)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'other_letters' to 'other_letters' +VARIABLES:input.py:767:ExpandVariables Found output '<(letters_list)EFGHIJK', recursing. +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'letters_list', 'is_array': '', 'replace': '<(letters_list)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCDEFGHIJK', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCDEFGHIJK' to 'ABCDEFGHIJK' +VARIABLES:input.py:785:ExpandVariables Expanding '<(letters_list)EFGHIJK' to 'ABCDEFGHIJK' +VARIABLES:input.py:785:ExpandVariables Expanding '<(other_letters)HIJK' to 'ABCDEFGHIJK' +VARIABLES:input.py:785:ExpandVariables Expanding 'XYZ' to 'XYZ' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '13.0' to '13.0' +VARIABLES:input.py:785:ExpandVariables Expanding 'import math; print math.pi' to 'import math; print math.pi' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'included_variable', 'is_array': '', 'replace': '<(included_variable)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'included_variable' to 'included_variable' +VARIABLES:input.py:767:ExpandVariables Found output 'XYZ', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'XYZ' to 'XYZ' +VARIABLES:input.py:785:ExpandVariables Expanding '<(included_variable)' to 'XYZ' +VARIABLES:input.py:785:ExpandVariables Expanding '6' to 6 +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'included_variable', 'is_array': '', 'replace': '<(included_variable)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'included_variable' to 'included_variable' +VARIABLES:input.py:767:ExpandVariables Found output 'XYZ', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'XYZ' to 'XYZ' +VARIABLES:input.py:785:ExpandVariables Expanding '<(included_variable)' to 'XYZ' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'third_letters', 'is_array': '', 'replace': '<(third_letters)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'third_letters' to 'third_letters' +VARIABLES:input.py:767:ExpandVariables Found output '<(other_letters)HIJK', recursing. +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'other_letters', 'is_array': '', 'replace': '<(other_letters)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'other_letters' to 'other_letters' +VARIABLES:input.py:767:ExpandVariables Found output '<(letters_list)EFGHIJK', recursing. +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'letters_list', 'is_array': '', 'replace': '<(letters_list)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCDEFGHIJK', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCDEFGHIJK' to 'ABCDEFGHIJK' +VARIABLES:input.py:785:ExpandVariables Expanding '<(letters_list)EFGHIJK' to 'ABCDEFGHIJK' +VARIABLES:input.py:785:ExpandVariables Expanding '<(other_letters)HIJK' to 'ABCDEFGHIJK' +VARIABLES:input.py:785:ExpandVariables Expanding '<(third_letters)' to 'ABCDEFGHIJK' +VARIABLES:input.py:785:ExpandVariables Expanding '8' to 8 +VARIABLES:input.py:785:ExpandVariables Expanding '.' to '.' +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_' to 'letters_' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': '<!(python -c "print \'letters_list\'"', 'is_array': '', 'replace': '<(<!(python -c "print \'letters_list\'")', 'type': '<', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'python -c "print \'letters_list\'"', 'is_array': '', 'replace': '<!(python -c "print \'letters_list\'")', 'type': '<!', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "print \'letters_list\'"' to 'python -c "print \'letters_list\'"' +VARIABLES:input.py:660:ExpandVariables Executing command 'python -c "print 'letters_list'"' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output 'letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '<!(python -c "print \'letters_list\'")' to 'letters_list' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCD', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '<(<!(python -c "print \'letters_list\'"))' to 'ABCD' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'check_int', 'is_array': '', 'replace': '<(check_int)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'check_int' to 'check_int' +VARIABLES:input.py:767:ExpandVariables Found output '5', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '5' to 5 +VARIABLES:input.py:785:ExpandVariables Expanding '<(check_int)' to 5 +VARIABLES:input.py:785:ExpandVariables Expanding 'list' to 'list' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': '"python", "-c", "<(pi', 'is_array': '[', 'replace': '<!(["python", "-c", "<(pi)', 'type': '<!', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'pi', 'is_array': '', 'replace': '<(pi)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'pi' to 'pi' +VARIABLES:input.py:767:ExpandVariables Found output '["python", "-c", "import math; print math.pi"]', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '["python", "-c", "import math; print math.pi"]' to '["python", "-c", "import math; print math.pi"]' +VARIABLES:input.py:785:ExpandVariables Expanding '["python", "-c", "<(pi)"]' to '["python", "-c", "import math; print math.pi"]' +VARIABLES:input.py:660:ExpandVariables Executing command '['python', '-c', 'import math; print math.pi']' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output '3.14159265359', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359' to '3.14159265359' +VARIABLES:input.py:785:ExpandVariables Expanding '<!(["python", "-c", "<(pi)"])' to '3.14159265359' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'python -c "print \'<(letters_list', 'is_array': '', 'replace': '<!(python -c "print \'<(letters_list)', 'type': '<!', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'letters_list', 'is_array': '', 'replace': '<(letters_list)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:767:ExpandVariables Found output 'python -c "print \'ABCD\'"', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "print \'ABCD\'"' to 'python -c "print \'ABCD\'"' +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "print \'<(letters_list)\'"' to 'python -c "print \'ABCD\'"' +VARIABLES:input.py:660:ExpandVariables Executing command 'python -c "print 'ABCD'"' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCD', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '<!(python -c "print \'<(letters_list)\'")' to 'ABCD' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'letters_list', 'is_array': '', 'replace': '<(letters_list)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'python -c "print \'<!(python -c "<(pi', 'is_array': '', 'replace': '<!(python -c "print \'<!(python -c "<(pi)', 'type': '<!', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'python -c "<(pi', 'is_array': '', 'replace': '<!(python -c "<(pi)', 'type': '<!', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'pi', 'is_array': '', 'replace': '<(pi)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'pi' to 'pi' +VARIABLES:input.py:767:ExpandVariables Found output 'python -c "import math; print math.pi"', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "import math; print math.pi"' to 'python -c "import math; print math.pi"' +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "<(pi)"' to 'python -c "import math; print math.pi"' +VARIABLES:input.py:660:ExpandVariables Executing command 'python -c "import math; print math.pi"' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output 'python -c "print \'3.14159265359 ABCD\'"', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "print \'3.14159265359 ABCD\'"' to 'python -c "print \'3.14159265359 ABCD\'"' +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "print \'<!(python -c "<(pi)") ABCD\'"' to 'python -c "print \'3.14159265359 ABCD\'"' +VARIABLES:input.py:660:ExpandVariables Executing command 'python -c "print '3.14159265359 ABCD'"' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output '3.14159265359 ABCD', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359 ABCD' to '3.14159265359 ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '<!(python -c "print \'<!(python -c "<(pi)") <(letters_list)\'")' to '3.14159265359 ABCD' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'check_str_int', 'is_array': '', 'replace': '<(check_str_int)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'check_str_int' to 'check_str_int' +VARIABLES:input.py:767:ExpandVariables Found output '6', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '6' to 6 +VARIABLES:input.py:785:ExpandVariables Expanding '<(check_str_int)' to 6 +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'check_int', 'is_array': '', 'replace': '<(check_int)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'check_int' to 'check_int' +VARIABLES:input.py:767:ExpandVariables Found output '5blah', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '5blah' to '5blah' +VARIABLES:input.py:785:ExpandVariables Expanding '<(check_int)blah' to '5blah' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'not_int_4', 'is_array': '', 'replace': '<(not_int_4)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'not_int_4' to 'not_int_4' +VARIABLES:input.py:767:ExpandVariables Found output '13.0', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '13.0' to '13.0' +VARIABLES:input.py:785:ExpandVariables Expanding '<(not_int_4)' to '13.0' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'not_int_3', 'is_array': '', 'replace': '<(not_int_3)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'not_int_3' to 'not_int_3' +VARIABLES:input.py:767:ExpandVariables Found output '012', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '012' to '012' +VARIABLES:input.py:785:ExpandVariables Expanding '<(not_int_3)' to '012' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'negative_int', 'is_array': '', 'replace': '<(negative_int)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'negative_int' to 'negative_int' +VARIABLES:input.py:767:ExpandVariables Found output '-15', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '-15' to -15 +VARIABLES:input.py:785:ExpandVariables Expanding '<(negative_int)' to -15 +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'not_int_5', 'is_array': '', 'replace': '<(not_int_5)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'not_int_5' to 'not_int_5' +VARIABLES:input.py:767:ExpandVariables Found output '+14', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '+14' to '+14' +VARIABLES:input.py:785:ExpandVariables Expanding '<(not_int_5)' to '+14' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'check_list_int', 'is_array': '', 'replace': '<(check_list_int)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'check_list_int' to 'check_list_int' +VARIABLES:input.py:767:ExpandVariables Found output '7 8 9', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '7 8 9' to '7 8 9' +VARIABLES:input.py:785:ExpandVariables Expanding '<(check_list_int)' to '7 8 9' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'not_int_2', 'is_array': '', 'replace': '<(not_int_2)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'not_int_2' to 'not_int_2' +VARIABLES:input.py:767:ExpandVariables Found output '11 ', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '11 ' to '11 ' +VARIABLES:input.py:785:ExpandVariables Expanding '<(not_int_2)' to '11 ' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'not_int_1', 'is_array': '', 'replace': '<(not_int_1)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'not_int_1' to 'not_int_1' +VARIABLES:input.py:767:ExpandVariables Found output ' 10', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding ' 10' to ' 10' +VARIABLES:input.py:785:ExpandVariables Expanding '<(not_int_1)' to ' 10' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'zero_int', 'is_array': '', 'replace': '<(zero_int)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'zero_int' to 'zero_int' +VARIABLES:input.py:767:ExpandVariables Found output '0', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '0' to 0 +VARIABLES:input.py:785:ExpandVariables Expanding '<(zero_int)' to 0 +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'check_list_int', 'is_array': '', 'replace': '<@(check_list_int)', 'type': '<@', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'check_list_int' to 'check_list_int' +VARIABLES:input.py:767:ExpandVariables Found output [7, 8, 9], recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 7 to 7 +VARIABLES:input.py:785:ExpandVariables Expanding 8 to 8 +VARIABLES:input.py:785:ExpandVariables Expanding 9 to 9 +VARIABLES:input.py:785:ExpandVariables Expanding '<@(check_list_int)' to [7, 8, 9] +VARIABLES:input.py:785:ExpandVariables Expanding 'foo' to 'foo' +VARIABLES:input.py:785:ExpandVariables Expanding 'target' to 'target' +VARIABLES:input.py:785:ExpandVariables Expanding 'none' to 'none' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var6', 'is_array': '', 'replace': '<(var6)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var6' to 'var6' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'echo <(var5', 'is_array': '', 'replace': '<!(echo <(var5)', 'type': '<!', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var5', 'is_array': '', 'replace': '<(var5)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var5' to 'var5' +VARIABLES:input.py:767:ExpandVariables Found output 'echo letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'echo letters_list' to 'echo letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding 'echo <(var5)list' to 'echo letters_list' +VARIABLES:input.py:660:ExpandVariables Executing command 'echo letters_list' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output 'letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '<!(echo <(var5)<(var6))' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding 'test_action' to 'test_action' +VARIABLES:input.py:785:ExpandVariables Expanding 'echo' to 'echo' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': '_inputs', 'is_array': '', 'replace': '<(_inputs)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding '_inputs' to '_inputs' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var2', 'is_array': '', 'replace': '<(var2)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var2' to 'var2' +VARIABLES:input.py:767:ExpandVariables Found output '3.14159265359 ABCD', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359 ABCD' to '3.14159265359 ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '<(var2)' to '3.14159265359 ABCD' +VARIABLES:input.py:767:ExpandVariables Found output '"3.14159265359 ABCD"', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '"3.14159265359 ABCD"' to '"3.14159265359 ABCD"' +VARIABLES:input.py:785:ExpandVariables Expanding '<(_inputs)' to '"3.14159265359 ABCD"' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': '_outputs', 'is_array': '', 'replace': '<(_outputs)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding '_outputs' to '_outputs' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var4', 'is_array': '', 'replace': '<(var4)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var4' to 'var4' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCD', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '<(var4)' to 'ABCD' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var7', 'is_array': '', 'replace': '<(var7)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var7' to 'var7' +VARIABLES:input.py:767:ExpandVariables Found output 'letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '<(var7)' to 'letters_list' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCD letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD letters_list' to 'ABCD letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '<(_outputs)' to 'ABCD letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359 ABCD' to '3.14159265359 ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding 'dummy' to 'dummy' +VARIABLES:input.py:785:ExpandVariables Expanding 'target' to 'target' +VARIABLES:input.py:785:ExpandVariables Expanding 'none' to 'none' +VARIABLES:input.py:785:ExpandVariables Expanding 'commands.gyp' to 'commands.gyp' +VARIABLES:input.py:785:ExpandVariables Expanding 'commands.gypi' to 'commands.gypi' +VARIABLES:input.py:785:ExpandVariables Expanding 'dummy' to 'dummy' +VARIABLES:input.py:785:ExpandVariables Expanding 'target' to 'target' +VARIABLES:input.py:785:ExpandVariables Expanding 'none' to 'none' +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_' to 'letters_' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'list' to 'list' +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359' to '3.14159265359' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359 ABCD' to '3.14159265359 ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '5blah' to '5blah' +VARIABLES:input.py:785:ExpandVariables Expanding '13.0' to '13.0' +VARIABLES:input.py:785:ExpandVariables Expanding '012' to '012' +VARIABLES:input.py:785:ExpandVariables Expanding '+14' to '+14' +VARIABLES:input.py:785:ExpandVariables Expanding '7 8 9' to '7 8 9' +VARIABLES:input.py:785:ExpandVariables Expanding '11 ' to '11 ' +VARIABLES:input.py:785:ExpandVariables Expanding ' 10' to ' 10' +VARIABLES:input.py:785:ExpandVariables Expanding 'foo' to 'foo' +VARIABLES:input.py:785:ExpandVariables Expanding 'target' to 'target' +VARIABLES:input.py:785:ExpandVariables Expanding 'none' to 'none' +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding 'test_action' to 'test_action' +VARIABLES:input.py:785:ExpandVariables Expanding 'echo' to 'echo' +VARIABLES:input.py:785:ExpandVariables Expanding '"3.14159265359 ABCD"' to '"3.14159265359 ABCD"' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD letters_list' to 'ABCD letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359 ABCD' to '3.14159265359 ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' diff --git a/tools/gyp/test/variables/commands/commands.gyp.stdout b/tools/gyp/test/variables/commands/commands.gyp.stdout new file mode 100644 index 00000000000..5c0ad5140a7 --- /dev/null +++ b/tools/gyp/test/variables/commands/commands.gyp.stdout @@ -0,0 +1,254 @@ +GENERAL:__init__.py:356:main running with these options: +GENERAL:__init__.py:363:main check: None +GENERAL:__init__.py:363:main circular_check: True +GENERAL:__init__.py:363:main debug: ['variables', 'general'] +GENERAL:__init__.py:363:main defines: None +GENERAL:__init__.py:361:main depth: '.' +GENERAL:__init__.py:363:main formats: ['gypd'] +GENERAL:__init__.py:363:main generator_flags: [] +GENERAL:__init__.py:363:main generator_output: None +GENERAL:__init__.py:363:main includes: None +GENERAL:__init__.py:363:main msvs_version: None +GENERAL:__init__.py:361:main suffix: '' +GENERAL:__init__.py:363:main toplevel_dir: None +GENERAL:__init__.py:363:main use_environment: True +GENERAL:__init__.py:417:main cmdline_default_variables: {} +GENERAL:__init__.py:443:main generator_flags: {} +VARIABLES:input.py:785:ExpandVariables Expanding '0' to 0 +VARIABLES:input.py:785:ExpandVariables Expanding '11 ' to '11 ' +VARIABLES:input.py:785:ExpandVariables Expanding '+14' to '+14' +VARIABLES:input.py:785:ExpandVariables Expanding '-15' to -15 +VARIABLES:input.py:785:ExpandVariables Expanding ' 10' to ' 10' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'letters_list', 'is_array': '', 'replace': '<(letters_list)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCDEFG', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCDEFG' to 'ABCDEFG' +VARIABLES:input.py:785:ExpandVariables Expanding '<(letters_list)EFG' to 'ABCDEFG' +VARIABLES:input.py:785:ExpandVariables Expanding '012' to '012' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'other_letters', 'is_array': '', 'replace': '<(other_letters)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'other_letters' to 'other_letters' +VARIABLES:input.py:767:ExpandVariables Found output '<(letters_list)EFGHIJK', recursing. +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'letters_list', 'is_array': '', 'replace': '<(letters_list)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCDEFGHIJK', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCDEFGHIJK' to 'ABCDEFGHIJK' +VARIABLES:input.py:785:ExpandVariables Expanding '<(letters_list)EFGHIJK' to 'ABCDEFGHIJK' +VARIABLES:input.py:785:ExpandVariables Expanding '<(other_letters)HIJK' to 'ABCDEFGHIJK' +VARIABLES:input.py:785:ExpandVariables Expanding 'XYZ' to 'XYZ' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '13.0' to '13.0' +VARIABLES:input.py:785:ExpandVariables Expanding 'import math; print math.pi' to 'import math; print math.pi' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'included_variable', 'is_array': '', 'replace': '<(included_variable)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'included_variable' to 'included_variable' +VARIABLES:input.py:767:ExpandVariables Found output 'XYZ', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'XYZ' to 'XYZ' +VARIABLES:input.py:785:ExpandVariables Expanding '<(included_variable)' to 'XYZ' +VARIABLES:input.py:785:ExpandVariables Expanding '6' to 6 +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'included_variable', 'is_array': '', 'replace': '<(included_variable)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'included_variable' to 'included_variable' +VARIABLES:input.py:767:ExpandVariables Found output 'XYZ', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'XYZ' to 'XYZ' +VARIABLES:input.py:785:ExpandVariables Expanding '<(included_variable)' to 'XYZ' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'third_letters', 'is_array': '', 'replace': '<(third_letters)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'third_letters' to 'third_letters' +VARIABLES:input.py:767:ExpandVariables Found output '<(other_letters)HIJK', recursing. +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'other_letters', 'is_array': '', 'replace': '<(other_letters)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'other_letters' to 'other_letters' +VARIABLES:input.py:767:ExpandVariables Found output '<(letters_list)EFGHIJK', recursing. +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'letters_list', 'is_array': '', 'replace': '<(letters_list)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCDEFGHIJK', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCDEFGHIJK' to 'ABCDEFGHIJK' +VARIABLES:input.py:785:ExpandVariables Expanding '<(letters_list)EFGHIJK' to 'ABCDEFGHIJK' +VARIABLES:input.py:785:ExpandVariables Expanding '<(other_letters)HIJK' to 'ABCDEFGHIJK' +VARIABLES:input.py:785:ExpandVariables Expanding '<(third_letters)' to 'ABCDEFGHIJK' +VARIABLES:input.py:785:ExpandVariables Expanding '8' to 8 +VARIABLES:input.py:785:ExpandVariables Expanding '.' to '.' +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_' to 'letters_' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': '<!(python -c "print \'letters_list\'"', 'is_array': '', 'replace': '<(<!(python -c "print \'letters_list\'")', 'type': '<', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'python -c "print \'letters_list\'"', 'is_array': '', 'replace': '<!(python -c "print \'letters_list\'")', 'type': '<!', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "print \'letters_list\'"' to 'python -c "print \'letters_list\'"' +VARIABLES:input.py:660:ExpandVariables Executing command 'python -c "print 'letters_list'"' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output 'letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '<!(python -c "print \'letters_list\'")' to 'letters_list' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCD', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '<(<!(python -c "print \'letters_list\'"))' to 'ABCD' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'check_int', 'is_array': '', 'replace': '<(check_int)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'check_int' to 'check_int' +VARIABLES:input.py:767:ExpandVariables Found output '5', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '5' to 5 +VARIABLES:input.py:785:ExpandVariables Expanding '<(check_int)' to 5 +VARIABLES:input.py:785:ExpandVariables Expanding 'list' to 'list' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': '"python", "-c", "<(pi', 'is_array': '[', 'replace': '<!(["python", "-c", "<(pi)', 'type': '<!', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'pi', 'is_array': '', 'replace': '<(pi)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'pi' to 'pi' +VARIABLES:input.py:767:ExpandVariables Found output '["python", "-c", "import math; print math.pi"]', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '["python", "-c", "import math; print math.pi"]' to '["python", "-c", "import math; print math.pi"]' +VARIABLES:input.py:785:ExpandVariables Expanding '["python", "-c", "<(pi)"]' to '["python", "-c", "import math; print math.pi"]' +VARIABLES:input.py:660:ExpandVariables Executing command '['python', '-c', 'import math; print math.pi']' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output '3.14159265359', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359' to '3.14159265359' +VARIABLES:input.py:785:ExpandVariables Expanding '<!(["python", "-c", "<(pi)"])' to '3.14159265359' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'python -c "print \'<(letters_list', 'is_array': '', 'replace': '<!(python -c "print \'<(letters_list)', 'type': '<!', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'letters_list', 'is_array': '', 'replace': '<(letters_list)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:767:ExpandVariables Found output 'python -c "print \'ABCD\'"', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "print \'ABCD\'"' to 'python -c "print \'ABCD\'"' +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "print \'<(letters_list)\'"' to 'python -c "print \'ABCD\'"' +VARIABLES:input.py:660:ExpandVariables Executing command 'python -c "print 'ABCD'"' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCD', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '<!(python -c "print \'<(letters_list)\'")' to 'ABCD' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'letters_list', 'is_array': '', 'replace': '<(letters_list)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'python -c "print \'<!(python -c "<(pi', 'is_array': '', 'replace': '<!(python -c "print \'<!(python -c "<(pi)', 'type': '<!', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'python -c "<(pi', 'is_array': '', 'replace': '<!(python -c "<(pi)', 'type': '<!', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'pi', 'is_array': '', 'replace': '<(pi)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'pi' to 'pi' +VARIABLES:input.py:767:ExpandVariables Found output 'python -c "import math; print math.pi"', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "import math; print math.pi"' to 'python -c "import math; print math.pi"' +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "<(pi)"' to 'python -c "import math; print math.pi"' +VARIABLES:input.py:660:ExpandVariables Executing command 'python -c "import math; print math.pi"' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output 'python -c "print \'3.14159265359 ABCD\'"', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "print \'3.14159265359 ABCD\'"' to 'python -c "print \'3.14159265359 ABCD\'"' +VARIABLES:input.py:785:ExpandVariables Expanding 'python -c "print \'<!(python -c "<(pi)") ABCD\'"' to 'python -c "print \'3.14159265359 ABCD\'"' +VARIABLES:input.py:660:ExpandVariables Executing command 'python -c "print '3.14159265359 ABCD'"' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output '3.14159265359 ABCD', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359 ABCD' to '3.14159265359 ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '<!(python -c "print \'<!(python -c "<(pi)") <(letters_list)\'")' to '3.14159265359 ABCD' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'check_str_int', 'is_array': '', 'replace': '<(check_str_int)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'check_str_int' to 'check_str_int' +VARIABLES:input.py:767:ExpandVariables Found output '6', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '6' to 6 +VARIABLES:input.py:785:ExpandVariables Expanding '<(check_str_int)' to 6 +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'check_int', 'is_array': '', 'replace': '<(check_int)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'check_int' to 'check_int' +VARIABLES:input.py:767:ExpandVariables Found output '5blah', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '5blah' to '5blah' +VARIABLES:input.py:785:ExpandVariables Expanding '<(check_int)blah' to '5blah' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'not_int_4', 'is_array': '', 'replace': '<(not_int_4)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'not_int_4' to 'not_int_4' +VARIABLES:input.py:767:ExpandVariables Found output '13.0', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '13.0' to '13.0' +VARIABLES:input.py:785:ExpandVariables Expanding '<(not_int_4)' to '13.0' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'not_int_3', 'is_array': '', 'replace': '<(not_int_3)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'not_int_3' to 'not_int_3' +VARIABLES:input.py:767:ExpandVariables Found output '012', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '012' to '012' +VARIABLES:input.py:785:ExpandVariables Expanding '<(not_int_3)' to '012' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'negative_int', 'is_array': '', 'replace': '<(negative_int)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'negative_int' to 'negative_int' +VARIABLES:input.py:767:ExpandVariables Found output '-15', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '-15' to -15 +VARIABLES:input.py:785:ExpandVariables Expanding '<(negative_int)' to -15 +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'not_int_5', 'is_array': '', 'replace': '<(not_int_5)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'not_int_5' to 'not_int_5' +VARIABLES:input.py:767:ExpandVariables Found output '+14', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '+14' to '+14' +VARIABLES:input.py:785:ExpandVariables Expanding '<(not_int_5)' to '+14' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'check_list_int', 'is_array': '', 'replace': '<(check_list_int)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'check_list_int' to 'check_list_int' +VARIABLES:input.py:767:ExpandVariables Found output '7 8 9', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '7 8 9' to '7 8 9' +VARIABLES:input.py:785:ExpandVariables Expanding '<(check_list_int)' to '7 8 9' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'not_int_2', 'is_array': '', 'replace': '<(not_int_2)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'not_int_2' to 'not_int_2' +VARIABLES:input.py:767:ExpandVariables Found output '11 ', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '11 ' to '11 ' +VARIABLES:input.py:785:ExpandVariables Expanding '<(not_int_2)' to '11 ' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'not_int_1', 'is_array': '', 'replace': '<(not_int_1)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'not_int_1' to 'not_int_1' +VARIABLES:input.py:767:ExpandVariables Found output ' 10', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding ' 10' to ' 10' +VARIABLES:input.py:785:ExpandVariables Expanding '<(not_int_1)' to ' 10' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'zero_int', 'is_array': '', 'replace': '<(zero_int)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'zero_int' to 'zero_int' +VARIABLES:input.py:767:ExpandVariables Found output '0', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '0' to 0 +VARIABLES:input.py:785:ExpandVariables Expanding '<(zero_int)' to 0 +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'check_list_int', 'is_array': '', 'replace': '<@(check_list_int)', 'type': '<@', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'check_list_int' to 'check_list_int' +VARIABLES:input.py:767:ExpandVariables Found output [7, 8, 9], recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 7 to 7 +VARIABLES:input.py:785:ExpandVariables Expanding 8 to 8 +VARIABLES:input.py:785:ExpandVariables Expanding 9 to 9 +VARIABLES:input.py:785:ExpandVariables Expanding '<@(check_list_int)' to [7, 8, 9] +VARIABLES:input.py:785:ExpandVariables Expanding 'foo' to 'foo' +VARIABLES:input.py:785:ExpandVariables Expanding 'target' to 'target' +VARIABLES:input.py:785:ExpandVariables Expanding 'none' to 'none' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var6', 'is_array': '', 'replace': '<(var6)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var6' to 'var6' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'echo <(var5', 'is_array': '', 'replace': '<!(echo <(var5)', 'type': '<!', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var5', 'is_array': '', 'replace': '<(var5)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var5' to 'var5' +VARIABLES:input.py:767:ExpandVariables Found output 'echo letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'echo letters_list' to 'echo letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding 'echo <(var5)list' to 'echo letters_list' +VARIABLES:input.py:660:ExpandVariables Executing command 'echo letters_list' in directory 'None' +VARIABLES:input.py:767:ExpandVariables Found output 'letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '<!(echo <(var5)<(var6))' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding 'test_action' to 'test_action' +VARIABLES:input.py:785:ExpandVariables Expanding 'echo' to 'echo' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': '_inputs', 'is_array': '', 'replace': '<(_inputs)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding '_inputs' to '_inputs' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var2', 'is_array': '', 'replace': '<(var2)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var2' to 'var2' +VARIABLES:input.py:767:ExpandVariables Found output '3.14159265359 ABCD', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359 ABCD' to '3.14159265359 ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '<(var2)' to '3.14159265359 ABCD' +VARIABLES:input.py:767:ExpandVariables Found output '"3.14159265359 ABCD"', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding '"3.14159265359 ABCD"' to '"3.14159265359 ABCD"' +VARIABLES:input.py:785:ExpandVariables Expanding '<(_inputs)' to '"3.14159265359 ABCD"' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': '_outputs', 'is_array': '', 'replace': '<(_outputs)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding '_outputs' to '_outputs' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var4', 'is_array': '', 'replace': '<(var4)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var4' to 'var4' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCD', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '<(var4)' to 'ABCD' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'var7', 'is_array': '', 'replace': '<(var7)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'var7' to 'var7' +VARIABLES:input.py:767:ExpandVariables Found output 'letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '<(var7)' to 'letters_list' +VARIABLES:input.py:767:ExpandVariables Found output 'ABCD letters_list', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD letters_list' to 'ABCD letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '<(_outputs)' to 'ABCD letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359 ABCD' to '3.14159265359 ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding 'dummy' to 'dummy' +VARIABLES:input.py:785:ExpandVariables Expanding 'target' to 'target' +VARIABLES:input.py:785:ExpandVariables Expanding 'none' to 'none' +VARIABLES:input.py:785:ExpandVariables Expanding 'commands.gyp' to 'commands.gyp' +VARIABLES:input.py:785:ExpandVariables Expanding 'commands.gypi' to 'commands.gypi' +VARIABLES:input.py:785:ExpandVariables Expanding 'dummy' to 'dummy' +VARIABLES:input.py:785:ExpandVariables Expanding 'target' to 'target' +VARIABLES:input.py:785:ExpandVariables Expanding 'none' to 'none' +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_' to 'letters_' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'list' to 'list' +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359' to '3.14159265359' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359 ABCD' to '3.14159265359 ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding '5blah' to '5blah' +VARIABLES:input.py:785:ExpandVariables Expanding '13.0' to '13.0' +VARIABLES:input.py:785:ExpandVariables Expanding '012' to '012' +VARIABLES:input.py:785:ExpandVariables Expanding '+14' to '+14' +VARIABLES:input.py:785:ExpandVariables Expanding '7 8 9' to '7 8 9' +VARIABLES:input.py:785:ExpandVariables Expanding '11 ' to '11 ' +VARIABLES:input.py:785:ExpandVariables Expanding ' 10' to ' 10' +VARIABLES:input.py:785:ExpandVariables Expanding 'foo' to 'foo' +VARIABLES:input.py:785:ExpandVariables Expanding 'target' to 'target' +VARIABLES:input.py:785:ExpandVariables Expanding 'none' to 'none' +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding 'test_action' to 'test_action' +VARIABLES:input.py:785:ExpandVariables Expanding 'echo' to 'echo' +VARIABLES:input.py:785:ExpandVariables Expanding '"3.14159265359 ABCD"' to '"3.14159265359 ABCD"' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD letters_list' to 'ABCD letters_list' +VARIABLES:input.py:785:ExpandVariables Expanding '3.14159265359 ABCD' to '3.14159265359 ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'ABCD' to 'ABCD' +VARIABLES:input.py:785:ExpandVariables Expanding 'letters_list' to 'letters_list' diff --git a/tools/gyp/test/variables/commands/commands.gypd.golden b/tools/gyp/test/variables/commands/commands.gypd.golden new file mode 100644 index 00000000000..e9aaf0202de --- /dev/null +++ b/tools/gyp/test/variables/commands/commands.gypd.golden @@ -0,0 +1,54 @@ +{'_DEPTH': '.', + 'included_files': ['commands.gyp', 'commands.gypi'], + 'targets': [{'actions': [{'action': ['echo', + '"3.14159265359 ABCD"', + 'ABCD letters_list'], + 'action_name': 'test_action', + 'inputs': ['3.14159265359 ABCD'], + 'outputs': ['ABCD', 'letters_list'], + 'variables': {'var7': 'letters_list'}}], + 'configurations': {'Default': {}}, + 'default_configuration': 'Default', + 'target_name': 'foo', + 'toolset': 'target', + 'type': 'none', + 'variables': {'var1': '3.14159265359', + 'var10': '7 8 9', + 'var11': ['7', '8', '9'], + 'var12': ' 10', + 'var13': '11 ', + 'var14': '012', + 'var15': '13.0', + 'var16': '+14', + 'var17': '-15', + 'var18': '0', + 'var2': '3.14159265359 ABCD', + 'var3': 'ABCD', + 'var4': 'ABCD', + 'var5': 'letters_', + 'var6': 'list', + 'var7': '5', + 'var8': '5blah', + 'var9': '6'}}, + {'configurations': {'Default': {}}, + 'default_configuration': 'Default', + 'target_name': 'dummy', + 'toolset': 'target', + 'type': 'none'}], + 'variables': {'check_included': 'XYZ', + 'check_int': '5', + 'check_list_int': ['7', '8', '9'], + 'check_lists': ['XYZ', 'ABCDEFGHIJK'], + 'check_str_int': '6', + 'included_variable': 'XYZ', + 'letters_list': 'ABCD', + 'negative_int': '-15', + 'not_int_1': ' 10', + 'not_int_2': '11 ', + 'not_int_3': '012', + 'not_int_4': '13.0', + 'not_int_5': '+14', + 'other_letters': 'ABCDEFG', + 'pi': 'import math; print math.pi', + 'third_letters': 'ABCDEFGHIJK', + 'zero_int': '0'}} diff --git a/tools/gyp/test/variables/commands/commands.gypi b/tools/gyp/test/variables/commands/commands.gypi new file mode 100644 index 00000000000..6b224971593 --- /dev/null +++ b/tools/gyp/test/variables/commands/commands.gypi @@ -0,0 +1,16 @@ +# 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. + +# This file is included from commands.gyp to test evaluation order of includes. +{ + 'variables': { + 'included_variable': 'XYZ', + }, + 'targets': [ + { + 'target_name': 'dummy', + 'type': 'none', + }, + ], +} diff --git a/tools/gyp/test/variables/commands/gyptest-commands-ignore-env.py b/tools/gyp/test/variables/commands/gyptest-commands-ignore-env.py new file mode 100755 index 00000000000..cdc051079c5 --- /dev/null +++ b/tools/gyp/test/variables/commands/gyptest-commands-ignore-env.py @@ -0,0 +1,46 @@ +#!/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 that environment variables are ignored when --ignore-environment is +specified. +""" + +import os + +import TestGyp + +test = TestGyp.TestGyp(format='gypd') + +os.environ['GYP_DEFINES'] = 'FOO=BAR' +os.environ['GYP_GENERATORS'] = 'foo' +os.environ['GYP_GENERATOR_FLAGS'] = 'genflag=foo' +os.environ['GYP_GENERATOR_OUTPUT'] = 'somedir' + +expect = test.read('commands.gyp.ignore-env.stdout').replace('\r', '') + +test.run_gyp('commands.gyp', + '--debug', 'variables', '--debug', 'general', + '--ignore-environment', + stdout=expect) + +# Verify the commands.gypd against the checked-in expected contents. +# +# Normally, we should canonicalize line endings in the expected +# contents file setting the Subversion svn:eol-style to native, +# but that would still fail if multiple systems are sharing a single +# workspace on a network-mounted file system. Consequently, we +# massage the Windows line endings ('\r\n') in the output to the +# checked-in UNIX endings ('\n'). + +contents = test.read('commands.gypd').replace('\r', '') +expect = test.read('commands.gypd.golden').replace('\r', '') +if not test.match(contents, expect): + print "Unexpected contents of `commands.gypd'" + test.diff(expect, contents, 'commands.gypd ') + test.fail_test() + +test.pass_test() diff --git a/tools/gyp/test/variables/commands/gyptest-commands-repeated.py b/tools/gyp/test/variables/commands/gyptest-commands-repeated.py new file mode 100755 index 00000000000..ffb17f3b9be --- /dev/null +++ b/tools/gyp/test/variables/commands/gyptest-commands-repeated.py @@ -0,0 +1,40 @@ +#!/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 variable expansion of '<!()' syntax commands where they are evaluated +more then once.. +""" + +import os + +import TestGyp + +test = TestGyp.TestGyp(format='gypd') + +expect = test.read('commands-repeated.gyp.stdout').replace('\r', '') + +test.run_gyp('commands-repeated.gyp', + '--debug', 'variables', '--debug', 'general', + stdout=expect) + +# Verify the commands-repeated.gypd against the checked-in expected contents. +# +# Normally, we should canonicalize line endings in the expected +# contents file setting the Subversion svn:eol-style to native, +# but that would still fail if multiple systems are sharing a single +# workspace on a network-mounted file system. Consequently, we +# massage the Windows line endings ('\r\n') in the output to the +# checked-in UNIX endings ('\n'). + +contents = test.read('commands-repeated.gypd').replace('\r', '') +expect = test.read('commands-repeated.gypd.golden').replace('\r', '') +if not test.match(contents, expect): + print "Unexpected contents of `commands-repeated.gypd'" + test.diff(expect, contents, 'commands-repeated.gypd ') + test.fail_test() + +test.pass_test() diff --git a/tools/gyp/test/variables/commands/gyptest-commands.py b/tools/gyp/test/variables/commands/gyptest-commands.py new file mode 100755 index 00000000000..ccde592168d --- /dev/null +++ b/tools/gyp/test/variables/commands/gyptest-commands.py @@ -0,0 +1,39 @@ +#!/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 variable expansion of '<!()' syntax commands. +""" + +import os + +import TestGyp + +test = TestGyp.TestGyp(format='gypd') + +expect = test.read('commands.gyp.stdout').replace('\r', '') + +test.run_gyp('commands.gyp', + '--debug', 'variables', '--debug', 'general', + stdout=expect) + +# Verify the commands.gypd against the checked-in expected contents. +# +# Normally, we should canonicalize line endings in the expected +# contents file setting the Subversion svn:eol-style to native, +# but that would still fail if multiple systems are sharing a single +# workspace on a network-mounted file system. Consequently, we +# massage the Windows line endings ('\r\n') in the output to the +# checked-in UNIX endings ('\n'). + +contents = test.read('commands.gypd').replace('\r', '') +expect = test.read('commands.gypd.golden').replace('\r', '') +if not test.match(contents, expect): + print "Unexpected contents of `commands.gypd'" + test.diff(expect, contents, 'commands.gypd ') + test.fail_test() + +test.pass_test() diff --git a/tools/gyp/test/variables/commands/update_golden b/tools/gyp/test/variables/commands/update_golden new file mode 100755 index 00000000000..e8da558a28e --- /dev/null +++ b/tools/gyp/test/variables/commands/update_golden @@ -0,0 +1,11 @@ +#!/bin/bash + +# 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. + +python ../../../gyp --debug variables --debug general --format gypd --depth . commands.gyp > commands.gyp.stdout +python ../../../gyp --ignore-environment --debug variables --debug general --format gypd --depth . commands.gyp > commands.gyp.ignore-env.stdout +cp -f commands.gypd commands.gypd.golden +python ../../../gyp --debug variables --debug general --format gypd --depth . commands-repeated.gyp > commands-repeated.gyp.stdout +cp -f commands-repeated.gypd commands-repeated.gypd.golden diff --git a/tools/gyp/test/variables/filelist/filelist.gyp.stdout b/tools/gyp/test/variables/filelist/filelist.gyp.stdout new file mode 100644 index 00000000000..910b76762f4 --- /dev/null +++ b/tools/gyp/test/variables/filelist/filelist.gyp.stdout @@ -0,0 +1,174 @@ +GENERAL:__init__.py:356:main running with these options: +GENERAL:__init__.py:363:main check: None +GENERAL:__init__.py:363:main circular_check: True +GENERAL:__init__.py:363:main debug: ['variables', 'general'] +GENERAL:__init__.py:363:main defines: None +GENERAL:__init__.py:361:main depth: '.' +GENERAL:__init__.py:363:main formats: ['gypd'] +GENERAL:__init__.py:363:main generator_flags: [] +GENERAL:__init__.py:363:main generator_output: None +GENERAL:__init__.py:363:main includes: None +GENERAL:__init__.py:363:main msvs_version: None +GENERAL:__init__.py:361:main suffix: '' +GENERAL:__init__.py:363:main toplevel_dir: None +GENERAL:__init__.py:363:main use_environment: True +GENERAL:__init__.py:417:main cmdline_default_variables: {} +GENERAL:__init__.py:443:main generator_flags: {} +VARIABLES:input.py:785:ExpandVariables Expanding 'exclude' to 'exclude' +VARIABLES:input.py:785:ExpandVariables Expanding 'Sch.*' to 'Sch.*' +VARIABLES:input.py:785:ExpandVariables Expanding 'include' to 'include' +VARIABLES:input.py:785:ExpandVariables Expanding '.*dt' to '.*dt' +VARIABLES:input.py:785:ExpandVariables Expanding 'exclude' to 'exclude' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jer.*' to 'Jer.*' +VARIABLES:input.py:785:ExpandVariables Expanding 'John' to 'John' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jacob' to 'Jacob' +VARIABLES:input.py:785:ExpandVariables Expanding 'Astor' to 'Astor' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jingleheimer' to 'Jingleheimer' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jerome' to 'Jerome' +VARIABLES:input.py:785:ExpandVariables Expanding 'Schmidt' to 'Schmidt' +VARIABLES:input.py:785:ExpandVariables Expanding 'Schultz' to 'Schultz' +VARIABLES:input.py:785:ExpandVariables Expanding 'Astor' to 'Astor' +VARIABLES:input.py:785:ExpandVariables Expanding '.' to '.' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'names.txt <@(names', 'is_array': '', 'replace': '<|(names.txt <@(names)', 'type': '<|', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'names', 'is_array': '', 'replace': '<@(names)', 'type': '<@', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'names' to 'names' +VARIABLES:input.py:785:ExpandVariables Expanding 'John' to 'John' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jacob' to 'Jacob' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jingleheimer' to 'Jingleheimer' +VARIABLES:input.py:785:ExpandVariables Expanding 'Schmidt' to 'Schmidt' +VARIABLES:input.py:767:ExpandVariables Found output 'names.txt John Jacob Jingleheimer Schmidt', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'names.txt John Jacob Jingleheimer Schmidt' to 'names.txt John Jacob Jingleheimer Schmidt' +VARIABLES:input.py:785:ExpandVariables Expanding 'names.txt <@(names)' to 'names.txt John Jacob Jingleheimer Schmidt' +VARIABLES:input.py:767:ExpandVariables Found output 'names.txt', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'names.txt' to 'names.txt' +VARIABLES:input.py:785:ExpandVariables Expanding '<|(names.txt <@(names))' to 'names.txt' +VARIABLES:input.py:785:ExpandVariables Expanding 'foo' to 'foo' +VARIABLES:input.py:785:ExpandVariables Expanding 'target' to 'target' +VARIABLES:input.py:785:ExpandVariables Expanding 'none' to 'none' +VARIABLES:input.py:785:ExpandVariables Expanding 'test_action' to 'test_action' +VARIABLES:input.py:785:ExpandVariables Expanding 'python' to 'python' +VARIABLES:input.py:785:ExpandVariables Expanding 'dummy.py' to 'dummy.py' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'names_listfile', 'is_array': '', 'replace': '<(names_listfile)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'names_listfile' to 'names_listfile' +VARIABLES:input.py:767:ExpandVariables Found output 'names.txt', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'names.txt' to 'names.txt' +VARIABLES:input.py:785:ExpandVariables Expanding '<(names_listfile)' to 'names.txt' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'names_listfile', 'is_array': '', 'replace': '<(names_listfile)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'names_listfile' to 'names_listfile' +VARIABLES:input.py:767:ExpandVariables Found output 'names.txt', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'names.txt' to 'names.txt' +VARIABLES:input.py:785:ExpandVariables Expanding '<(names_listfile)' to 'names.txt' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'cat <(names_listfile', 'is_array': '', 'replace': '<!@(cat <(names_listfile)', 'type': '<!@', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'names_listfile', 'is_array': '', 'replace': '<(names_listfile)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'names_listfile' to 'names_listfile' +VARIABLES:input.py:767:ExpandVariables Found output 'cat names.txt', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'cat names.txt' to 'cat names.txt' +VARIABLES:input.py:785:ExpandVariables Expanding 'cat <(names_listfile)' to 'cat names.txt' +VARIABLES:input.py:660:ExpandVariables Executing command 'cat names.txt' in directory 'src' +VARIABLES:input.py:767:ExpandVariables Found output ['John', 'Jacob', 'Jingleheimer', 'Schmidt'], recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'John' to 'John' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jacob' to 'Jacob' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jingleheimer' to 'Jingleheimer' +VARIABLES:input.py:785:ExpandVariables Expanding 'Schmidt' to 'Schmidt' +VARIABLES:input.py:785:ExpandVariables Expanding '<!@(cat <(names_listfile))' to ['John', 'Jacob', 'Jingleheimer', 'Schmidt'] +VARIABLES:input.py:785:ExpandVariables Expanding 'dummy_foo' to 'dummy_foo' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'sources.txt <@(_sources', 'is_array': '', 'replace': '<|(sources.txt <@(_sources)', 'type': '<|', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': '_sources', 'is_array': '', 'replace': '<@(_sources)', 'type': '<@', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding '_sources' to '_sources' +VARIABLES:input.py:785:ExpandVariables Expanding 'John' to 'John' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jacob' to 'Jacob' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jingleheimer' to 'Jingleheimer' +VARIABLES:input.py:785:ExpandVariables Expanding 'Schmidt' to 'Schmidt' +VARIABLES:input.py:767:ExpandVariables Found output 'sources.txt John Jacob Jingleheimer Schmidt', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'sources.txt John Jacob Jingleheimer Schmidt' to 'sources.txt John Jacob Jingleheimer Schmidt' +VARIABLES:input.py:785:ExpandVariables Expanding 'sources.txt <@(_sources)' to 'sources.txt John Jacob Jingleheimer Schmidt' +VARIABLES:input.py:767:ExpandVariables Found output 'sources.txt', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'sources.txt' to 'sources.txt' +VARIABLES:input.py:785:ExpandVariables Expanding '<|(sources.txt <@(_sources))' to 'sources.txt' +VARIABLES:input.py:785:ExpandVariables Expanding 'bar' to 'bar' +VARIABLES:input.py:785:ExpandVariables Expanding 'target' to 'target' +VARIABLES:input.py:785:ExpandVariables Expanding 'none' to 'none' +VARIABLES:input.py:785:ExpandVariables Expanding 'exclude' to 'exclude' +VARIABLES:input.py:785:ExpandVariables Expanding 'Sch.*' to 'Sch.*' +VARIABLES:input.py:785:ExpandVariables Expanding 'include' to 'include' +VARIABLES:input.py:785:ExpandVariables Expanding '.*dt' to '.*dt' +VARIABLES:input.py:785:ExpandVariables Expanding 'exclude' to 'exclude' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jer.*' to 'Jer.*' +VARIABLES:input.py:785:ExpandVariables Expanding 'Astor' to 'Astor' +VARIABLES:input.py:785:ExpandVariables Expanding 'test_action' to 'test_action' +VARIABLES:input.py:785:ExpandVariables Expanding 'python' to 'python' +VARIABLES:input.py:785:ExpandVariables Expanding 'dummy.py' to 'dummy.py' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'sources_listfile', 'is_array': '', 'replace': '<(sources_listfile)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'sources_listfile' to 'sources_listfile' +VARIABLES:input.py:767:ExpandVariables Found output 'sources.txt', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'sources.txt' to 'sources.txt' +VARIABLES:input.py:785:ExpandVariables Expanding '<(sources_listfile)' to 'sources.txt' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'sources_listfile', 'is_array': '', 'replace': '<(sources_listfile)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'sources_listfile' to 'sources_listfile' +VARIABLES:input.py:767:ExpandVariables Found output 'sources.txt', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'sources.txt' to 'sources.txt' +VARIABLES:input.py:785:ExpandVariables Expanding '<(sources_listfile)' to 'sources.txt' +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'cat <(sources_listfile', 'is_array': '', 'replace': '<!@(cat <(sources_listfile)', 'type': '<!@', 'command_string': None} +VARIABLES:input.py:546:ExpandVariables Matches: {'content': 'sources_listfile', 'is_array': '', 'replace': '<(sources_listfile)', 'type': '<', 'command_string': None} +VARIABLES:input.py:785:ExpandVariables Expanding 'sources_listfile' to 'sources_listfile' +VARIABLES:input.py:767:ExpandVariables Found output 'cat sources.txt', recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'cat sources.txt' to 'cat sources.txt' +VARIABLES:input.py:785:ExpandVariables Expanding 'cat <(sources_listfile)' to 'cat sources.txt' +VARIABLES:input.py:660:ExpandVariables Executing command 'cat sources.txt' in directory 'src' +VARIABLES:input.py:767:ExpandVariables Found output ['John', 'Jacob', 'Jingleheimer', 'Schmidt'], recursing. +VARIABLES:input.py:785:ExpandVariables Expanding 'John' to 'John' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jacob' to 'Jacob' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jingleheimer' to 'Jingleheimer' +VARIABLES:input.py:785:ExpandVariables Expanding 'Schmidt' to 'Schmidt' +VARIABLES:input.py:785:ExpandVariables Expanding '<!@(cat <(sources_listfile))' to ['John', 'Jacob', 'Jingleheimer', 'Schmidt'] +VARIABLES:input.py:785:ExpandVariables Expanding 'dummy_foo' to 'dummy_foo' +VARIABLES:input.py:785:ExpandVariables Expanding 'John' to 'John' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jacob' to 'Jacob' +VARIABLES:input.py:785:ExpandVariables Expanding 'Astor' to 'Astor' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jingleheimer' to 'Jingleheimer' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jerome' to 'Jerome' +VARIABLES:input.py:785:ExpandVariables Expanding 'Schmidt' to 'Schmidt' +VARIABLES:input.py:785:ExpandVariables Expanding 'Schultz' to 'Schultz' +VARIABLES:input.py:785:ExpandVariables Expanding 'filelist.gyp' to 'filelist.gyp' +VARIABLES:input.py:785:ExpandVariables Expanding 'names.txt' to 'names.txt' +VARIABLES:input.py:785:ExpandVariables Expanding 'foo' to 'foo' +VARIABLES:input.py:785:ExpandVariables Expanding 'target' to 'target' +VARIABLES:input.py:785:ExpandVariables Expanding 'none' to 'none' +VARIABLES:input.py:785:ExpandVariables Expanding 'test_action' to 'test_action' +VARIABLES:input.py:785:ExpandVariables Expanding 'python' to 'python' +VARIABLES:input.py:785:ExpandVariables Expanding 'dummy.py' to 'dummy.py' +VARIABLES:input.py:785:ExpandVariables Expanding 'names.txt' to 'names.txt' +VARIABLES:input.py:785:ExpandVariables Expanding 'names.txt' to 'names.txt' +VARIABLES:input.py:785:ExpandVariables Expanding 'John' to 'John' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jacob' to 'Jacob' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jingleheimer' to 'Jingleheimer' +VARIABLES:input.py:785:ExpandVariables Expanding 'Schmidt' to 'Schmidt' +VARIABLES:input.py:785:ExpandVariables Expanding 'dummy_foo' to 'dummy_foo' +VARIABLES:input.py:785:ExpandVariables Expanding 'sources.txt' to 'sources.txt' +VARIABLES:input.py:785:ExpandVariables Expanding 'bar' to 'bar' +VARIABLES:input.py:785:ExpandVariables Expanding 'target' to 'target' +VARIABLES:input.py:785:ExpandVariables Expanding 'none' to 'none' +VARIABLES:input.py:785:ExpandVariables Expanding 'exclude' to 'exclude' +VARIABLES:input.py:785:ExpandVariables Expanding 'Sch.*' to 'Sch.*' +VARIABLES:input.py:785:ExpandVariables Expanding 'include' to 'include' +VARIABLES:input.py:785:ExpandVariables Expanding '.*dt' to '.*dt' +VARIABLES:input.py:785:ExpandVariables Expanding 'exclude' to 'exclude' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jer.*' to 'Jer.*' +VARIABLES:input.py:785:ExpandVariables Expanding 'Astor' to 'Astor' +VARIABLES:input.py:785:ExpandVariables Expanding 'test_action' to 'test_action' +VARIABLES:input.py:785:ExpandVariables Expanding 'python' to 'python' +VARIABLES:input.py:785:ExpandVariables Expanding 'dummy.py' to 'dummy.py' +VARIABLES:input.py:785:ExpandVariables Expanding 'sources.txt' to 'sources.txt' +VARIABLES:input.py:785:ExpandVariables Expanding 'sources.txt' to 'sources.txt' +VARIABLES:input.py:785:ExpandVariables Expanding 'John' to 'John' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jacob' to 'Jacob' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jingleheimer' to 'Jingleheimer' +VARIABLES:input.py:785:ExpandVariables Expanding 'Schmidt' to 'Schmidt' +VARIABLES:input.py:785:ExpandVariables Expanding 'dummy_foo' to 'dummy_foo' +VARIABLES:input.py:785:ExpandVariables Expanding 'John' to 'John' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jacob' to 'Jacob' +VARIABLES:input.py:785:ExpandVariables Expanding 'Astor' to 'Astor' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jingleheimer' to 'Jingleheimer' +VARIABLES:input.py:785:ExpandVariables Expanding 'Jerome' to 'Jerome' +VARIABLES:input.py:785:ExpandVariables Expanding 'Schmidt' to 'Schmidt' +VARIABLES:input.py:785:ExpandVariables Expanding 'Schultz' to 'Schultz' diff --git a/tools/gyp/test/variables/filelist/filelist.gypd.golden b/tools/gyp/test/variables/filelist/filelist.gypd.golden new file mode 100644 index 00000000000..09d9116047e --- /dev/null +++ b/tools/gyp/test/variables/filelist/filelist.gypd.golden @@ -0,0 +1,43 @@ +{'_DEPTH': '.', + 'included_files': ['filelist.gyp'], + 'targets': [{'actions': [{'action': ['python', 'dummy.py', 'names.txt'], + 'action_name': 'test_action', + 'inputs': ['names.txt', + 'John', + 'Jacob', + 'Jingleheimer', + 'Schmidt'], + 'outputs': ['dummy_foo']}], + 'configurations': {'Default': {}}, + 'default_configuration': 'Default', + 'target_name': 'foo', + 'toolset': 'target', + 'type': 'none', + 'variables': {'names_listfile': 'names.txt'}}, + {'actions': [{'action': ['python', 'dummy.py', 'sources.txt'], + 'action_name': 'test_action', + 'inputs': ['sources.txt', + 'John', + 'Jacob', + 'Jingleheimer', + 'Schmidt'], + 'outputs': ['dummy_foo']}], + 'configurations': {'Default': {}}, + 'default_configuration': 'Default', + 'sources': ['John', 'Jacob', 'Jingleheimer', 'Schmidt'], + 'sources_excluded': ['Astor', 'Jerome', 'Schultz'], + 'target_name': 'bar', + 'toolset': 'target', + 'type': 'none', + 'variables': {'sources_listfile': 'sources.txt'}}], + 'variables': {'names': ['John', + 'Jacob', + 'Astor', + 'Jingleheimer', + 'Jerome', + 'Schmidt', + 'Schultz'], + 'names!': ['Astor'], + 'names/': [['exclude', 'Sch.*'], + ['include', '.*dt'], + ['exclude', 'Jer.*']]}} diff --git a/tools/gyp/test/variables/filelist/gyptest-filelist.py b/tools/gyp/test/variables/filelist/gyptest-filelist.py new file mode 100755 index 00000000000..ac57355418c --- /dev/null +++ b/tools/gyp/test/variables/filelist/gyptest-filelist.py @@ -0,0 +1,50 @@ +#!/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 variable expansion of '<|(list.txt ...)' syntax commands. +""" + +import os +import sys + +import TestGyp + +test = TestGyp.TestGyp(format='gypd') + +expect = test.read('filelist.gyp.stdout') +if sys.platform == 'win32': + expect = expect.replace('/', r'\\').replace('\r', '') + +test.run_gyp('src/filelist.gyp', + '--debug', 'variables', '--debug', 'general', + stdout=expect) + +# Verify the filelist.gypd against the checked-in expected contents. +# +# Normally, we should canonicalize line endings in the expected +# contents file setting the Subversion svn:eol-style to native, +# but that would still fail if multiple systems are sharing a single +# workspace on a network-mounted file system. Consequently, we +# massage the Windows line endings ('\r\n') in the output to the +# checked-in UNIX endings ('\n'). + +contents = test.read('src/filelist.gypd').replace( + '\r', '').replace('\\\\', '/') +expect = test.read('filelist.gypd.golden').replace('\r', '') +if not test.match(contents, expect): + print "Unexpected contents of `src/filelist.gypd'" + test.diff(expect, contents, 'src/filelist.gypd ') + test.fail_test() + +contents = test.read('src/names.txt') +expect = 'John\nJacob\nJingleheimer\nSchmidt\n' +if not test.match(contents, expect): + print "Unexpected contents of `src/names.txt'" + test.diff(expect, contents, 'src/names.txt ') + test.fail_test() + +test.pass_test() diff --git a/tools/gyp/test/variables/filelist/src/filelist.gyp b/tools/gyp/test/variables/filelist/src/filelist.gyp new file mode 100644 index 00000000000..df48eb3e4a6 --- /dev/null +++ b/tools/gyp/test/variables/filelist/src/filelist.gyp @@ -0,0 +1,93 @@ +# 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. + +# This is a test to make sure that <|(foo.txt a b c) generates +# a pre-calculated file list at gyp time and returns foo.txt. +# This feature is useful to work around limits in the number of arguments that +# can be passed to rule/action. + +{ + 'variables': { + 'names': [ + 'John', + 'Jacob', + 'Astor', + 'Jingleheimer', + 'Jerome', + 'Schmidt', + 'Schultz', + ], + 'names!': [ + 'Astor', + ], + 'names/': [ + ['exclude', 'Sch.*'], + ['include', '.*dt'], + ['exclude', 'Jer.*'], + ], + }, + 'targets': [ + { + 'target_name': 'foo', + 'type': 'none', + 'variables': { + 'names_listfile': '<|(names.txt <@(names))', + }, + 'actions': [ + { + 'action_name': 'test_action', + 'inputs' : [ + '<(names_listfile)', + '<!@(cat <(names_listfile))', + ], + 'outputs': [ + 'dummy_foo', + ], + 'action': [ + 'python', 'dummy.py', '<(names_listfile)', + ], + }, + ], + }, + { + 'target_name': 'bar', + 'type': 'none', + 'sources': [ + 'John', + 'Jacob', + 'Astor', + 'Jingleheimer', + 'Jerome', + 'Schmidt', + 'Schultz', + ], + 'sources!': [ + 'Astor', + ], + 'sources/': [ + ['exclude', 'Sch.*'], + ['include', '.*dt'], + ['exclude', 'Jer.*'], + ], + 'variables': { + 'sources_listfile': '<|(sources.txt <@(_sources))', + }, + 'actions': [ + { + 'action_name': 'test_action', + 'inputs' : [ + '<(sources_listfile)', + '<!@(cat <(sources_listfile))', + ], + 'outputs': [ + 'dummy_foo', + ], + 'action': [ + 'python', 'dummy.py', '<(sources_listfile)', + ], + }, + ], + }, + ], +} diff --git a/tools/gyp/test/variables/filelist/update_golden b/tools/gyp/test/variables/filelist/update_golden new file mode 100755 index 00000000000..b4d489a3423 --- /dev/null +++ b/tools/gyp/test/variables/filelist/update_golden @@ -0,0 +1,8 @@ +#!/bin/bash + +# 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. + +python ../../../gyp --debug variables --debug general --format gypd --depth . src/filelist.gyp > filelist.gyp.stdout +cp -f src/filelist.gypd filelist.gypd.golden diff --git a/tools/gyp/test/variants/gyptest-variants.py b/tools/gyp/test/variants/gyptest-variants.py new file mode 100755 index 00000000000..ce2455f663f --- /dev/null +++ b/tools/gyp/test/variants/gyptest-variants.py @@ -0,0 +1,45 @@ +#!/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 handling of build variants. + +TODO: Right now, only the SCons generator supports this, so the +test case is SCons-specific. In particular, it relise on SCons' +ability to rebuild in response to changes on the command line. It +may be simpler to just drop this feature if the other generators +can't be made to behave the same way. +""" + +import TestGyp + +test = TestGyp.TestGyp(formats=['scons']) + +test.run_gyp('variants.gyp', chdir='src') + +test.relocate('src', 'relocate/src') + +test.build('variants.gyp', chdir='relocate/src') + +test.run_built_executable('variants', + chdir='relocate/src', + stdout="Hello, world!\n") + +test.sleep() +test.build('variants.gyp', 'VARIANT1=1', chdir='relocate/src') + +test.run_built_executable('variants', + chdir='relocate/src', + stdout="Hello from VARIANT1\n") + +test.sleep() +test.build('variants.gyp', 'VARIANT2=1', chdir='relocate/src') + +test.run_built_executable('variants', + chdir='relocate/src', + stdout="Hello from VARIANT2\n") + +test.pass_test() diff --git a/tools/gyp/test/variants/src/variants.c b/tools/gyp/test/variants/src/variants.c new file mode 100644 index 00000000000..3018e40df2c --- /dev/null +++ b/tools/gyp/test/variants/src/variants.c @@ -0,0 +1,13 @@ +#include <stdio.h> + +int main(int argc, char *argv[]) +{ +#if defined(VARIANT1) + printf("Hello from VARIANT1\n"); +#elif defined(VARIANT2) + printf("Hello from VARIANT2\n"); +#else + printf("Hello, world!\n"); +#endif + return 0; +} diff --git a/tools/gyp/test/variants/src/variants.gyp b/tools/gyp/test/variants/src/variants.gyp new file mode 100644 index 00000000000..0305ca74731 --- /dev/null +++ b/tools/gyp/test/variants/src/variants.gyp @@ -0,0 +1,27 @@ +# 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': 'variants', + 'type': 'executable', + 'sources': [ + 'variants.c', + ], + 'variants': { + 'variant1' : { + 'defines': [ + 'VARIANT1', + ], + }, + 'variant2' : { + 'defines': [ + 'VARIANT2', + ], + }, + }, + }, + ], +} diff --git a/tools/gyp/tools/graphviz.py b/tools/gyp/tools/graphviz.py index 7f7166802b7..326ae221cf8 100755 --- a/tools/gyp/tools/graphviz.py +++ b/tools/gyp/tools/graphviz.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/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 @@ -83,13 +83,18 @@ def WriteGraph(edges): print '}' -if __name__ == '__main__': +def main(): if len(sys.argv) < 2: print >>sys.stderr, __doc__ print >>sys.stderr print >>sys.stderr, 'usage: %s target1 target2...' % (sys.argv[0]) - sys.exit(1) + return 1 edges = LoadEdges('dump.json', sys.argv[1:]) WriteGraph(edges) + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/tools/gyp/tools/pretty_gyp.py b/tools/gyp/tools/pretty_gyp.py index 04c79012ee1..3749792aacc 100644..100755 --- a/tools/gyp/tools/pretty_gyp.py +++ b/tools/gyp/tools/pretty_gyp.py @@ -1,142 +1,154 @@ -#!/usr/bin/env python
-# Copyright (c) 2009 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This file pretty-prints the contents of a GYP file.
-
-import sys
-import re
-
-input = []
-if len(sys.argv) > 1:
- input_file = open(sys.argv[1])
- input = input_file.read().splitlines()
- input_file.close()
-else:
- input = sys.stdin.read().splitlines()
-
-# This is used to remove comments when we're counting braces.
-comment_re = re.compile(r'\s*#.*')
-
-# This is used to remove quoted strings when we're counting braces.
-# It takes into account quoted quotes, and makes sure that the quotes
-# match.
-# NOTE: It does not handle quotes that span more than one line, or
-# cases where an escaped quote is preceeded by an escaped backslash.
-quote_re_str = r'(?P<q>[\'"])(.*?)(?<![^\\][\\])(?P=q)'
-quote_re = re.compile(quote_re_str)
-
-def comment_replace(matchobj):
- return matchobj.group(1) + matchobj.group(2) + '#' * len(matchobj.group(3))
-
-def mask_comments(input):
- # This is used to mask the quoted strings so we skip braces inside
- # quoted strings.
- search_re = re.compile(r'(.*?)(#)(.*)')
- return [search_re.sub(comment_replace, line) for line in input]
-
-def quote_replace(matchobj):
- return "%s%s%s%s" % (matchobj.group(1),
- matchobj.group(2),
- 'x'*len(matchobj.group(3)),
- matchobj.group(2))
-
-def mask_quotes(input):
- # This is used to mask the quoted strings so we skip braces inside
- # quoted strings.
- search_re = re.compile(r'(.*?)' + quote_re_str)
- return [search_re.sub(quote_replace, line) for line in input]
-
-def do_split(input, masked_input, search_re):
- output = []
- mask_output = []
- for (line, masked_line) in zip(input, masked_input):
- m = search_re.match(masked_line)
- while m:
- split = len(m.group(1))
- line = line[:split] + r'\n' + line[split:]
- masked_line = masked_line[:split] + r'\n' + masked_line[split:]
- m = search_re.match(masked_line)
- output.extend(line.split(r'\n'))
- mask_output.extend(masked_line.split(r'\n'))
- return (output, mask_output)
-
-# This masks out the quotes and comments, and then splits appropriate
-# lines (lines that matche the double_*_brace re's above) before
-# indenting them below.
-def split_double_braces(input):
- # These are used to split lines which have multiple braces on them, so
- # that the indentation looks prettier when all laid out (e.g. closing
- # braces make a nice diagonal line).
- double_open_brace_re = re.compile(r'(.*?[\[\{\(,])(\s*)([\[\{\(])')
- double_close_brace_re = re.compile(r'(.*?[\]\}\)],?)(\s*)([\]\}\)])')
-
- masked_input = mask_quotes(input)
- masked_input = mask_comments(masked_input)
-
- (output, mask_output) = do_split(input, masked_input, double_open_brace_re)
- (output, mask_output) = do_split(output, mask_output, double_close_brace_re)
-
- return output
-
-# This keeps track of the number of braces on a given line and returns
-# the result. It starts at zero and subtracts for closed braces, and
-# adds for open braces.
-def count_braces(line):
- open_braces = ['[', '(', '{']
- close_braces = [']', ')', '}']
- closing_prefix_re = re.compile(r'(.*?[^\s\]\}\)]+.*?)([\]\}\)],?)\s*$')
- cnt = 0
- stripline = comment_re.sub(r'', line)
- stripline = quote_re.sub(r"''", stripline)
- for char in stripline:
- for brace in open_braces:
- if char == brace:
- cnt += 1
- for brace in close_braces:
- if char == brace:
- cnt -= 1
-
- after = False
- if cnt > 0:
- after = True
-
- # This catches the special case of a closing brace having something
- # other than just whitespace ahead of it -- we don't want to
- # unindent that until after this line is printed so it stays with
- # the previous indentation level.
- if cnt < 0 and closing_prefix_re.match(stripline):
- after = True
- return (cnt, after)
-
-# This does the main work of indenting the input based on the brace counts.
-def prettyprint_input(lines):
- indent = 0
- basic_offset = 2
- last_line = ""
- for line in lines:
- if comment_re.match(line):
- print line
- else:
- line = line.strip('\r\n\t ') # Otherwise doesn't strip \r on Unix.
- if len(line) > 0:
- (brace_diff, after) = count_braces(line)
- if brace_diff != 0:
- if after:
- print " " * (basic_offset * indent) + line
- indent += brace_diff
- else:
- indent += brace_diff
- print " " * (basic_offset * indent) + line
- else:
- print " " * (basic_offset * indent) + line
- else:
- print ""
- last_line = line
-
-# Split up the double braces.
-lines = split_double_braces(input)
-
-# Indent and print the output.
-prettyprint_input(lines)
+#!/usr/bin/env python +# Copyright (c) 2011 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Pretty-prints the contents of a GYP file.""" + +import sys +import re + + +# Regex to remove comments when we're counting braces. +COMMENT_RE = re.compile(r'\s*#.*') + +# Regex to remove quoted strings when we're counting braces. +# It takes into account quoted quotes, and makes sure that the quotes match. +# NOTE: It does not handle quotes that span more than one line, or +# cases where an escaped quote is preceeded by an escaped backslash. +quote_re_str = r'(?P<q>[\'"])(.*?)(?<![^\\][\\])(?P=q)' +QUOTE_RE = re.compile(QUOTE_RE_STR) + + +def comment_replace(matchobj): + return matchobj.group(1) + matchobj.group(2) + '#' * len(matchobj.group(3)) + + +def mask_comments(input): + """Mask the quoted strings so we skip braces inside quoted strings.""" + search_re = re.compile(r'(.*?)(#)(.*)') + return [search_re.sub(comment_replace, line) for line in input] + + +def quote_replace(matchobj): + return "%s%s%s%s" % (matchobj.group(1), + matchobj.group(2), + 'x'*len(matchobj.group(3)), + matchobj.group(2)) + + +def mask_quotes(input): + """Mask the quoted strings so we skip braces inside quoted strings.""" + search_re = re.compile(r'(.*?)' + QUOTE_RE_STR) + return [search_re.sub(quote_replace, line) for line in input] + + +def do_split(input, masked_input, search_re): + output = [] + mask_output = [] + for (line, masked_line) in zip(input, masked_input): + m = search_re.match(masked_line) + while m: + split = len(m.group(1)) + line = line[:split] + r'\n' + line[split:] + masked_line = masked_line[:split] + r'\n' + masked_line[split:] + m = search_re.match(masked_line) + output.extend(line.split(r'\n')) + mask_output.extend(masked_line.split(r'\n')) + return (output, mask_output) + + +def split_double_braces(input): + """Masks out the quotes and comments, and then splits appropriate + lines (lines that matche the double_*_brace re's above) before + indenting them below. + + These are used to split lines which have multiple braces on them, so + that the indentation looks prettier when all laid out (e.g. closing + braces make a nice diagonal line). + """ + double_open_brace_re = re.compile(r'(.*?[\[\{\(,])(\s*)([\[\{\(])') + double_close_brace_re = re.compile(r'(.*?[\]\}\)],?)(\s*)([\]\}\)])') + + masked_input = mask_quotes(input) + masked_input = mask_comments(masked_input) + + (output, mask_output) = do_split(input, masked_input, double_open_brace_re) + (output, mask_output) = do_split(output, mask_output, double_close_brace_re) + + return output + + +def count_braces(line): + """keeps track of the number of braces on a given line and returns the result. + + It starts at zero and subtracts for closed braces, and adds for open braces. + """ + open_braces = ['[', '(', '{'] + close_braces = [']', ')', '}'] + closing_prefix_re = re.compile(r'(.*?[^\s\]\}\)]+.*?)([\]\}\)],?)\s*$') + cnt = 0 + stripline = COMMENT_RE.sub(r'', line) + stripline = QUOTE_RE.sub(r"''", stripline) + for char in stripline: + for brace in open_braces: + if char == brace: + cnt += 1 + for brace in close_braces: + if char == brace: + cnt -= 1 + + after = False + if cnt > 0: + after = True + + # This catches the special case of a closing brace having something + # other than just whitespace ahead of it -- we don't want to + # unindent that until after this line is printed so it stays with + # the previous indentation level. + if cnt < 0 and closing_prefix_re.match(stripline): + after = True + return (cnt, after) + + +def prettyprint_input(lines): + """Does the main work of indenting the input based on the brace counts.""" + indent = 0 + basic_offset = 2 + last_line = "" + for line in lines: + if COMMENT_RE.match(line): + print line + else: + line = line.strip('\r\n\t ') # Otherwise doesn't strip \r on Unix. + if len(line) > 0: + (brace_diff, after) = count_braces(line) + if brace_diff != 0: + if after: + print " " * (basic_offset * indent) + line + indent += brace_diff + else: + indent += brace_diff + print " " * (basic_offset * indent) + line + else: + print " " * (basic_offset * indent) + line + else: + print "" + last_line = line + + +def main(): + if len(sys.argv) > 1: + data = open(sys.argv[1]).read().splitlines() + else: + data = sys.stdin.read().splitlines() + # Split up the double braces. + lines = split_double_braces(data) + + # Indent and print the output. + prettyprint_input(lines) + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/tools/gyp/tools/pretty_sln.py b/tools/gyp/tools/pretty_sln.py index 0741fff1776..7013f2b660c 100755 --- a/tools/gyp/tools/pretty_sln.py +++ b/tools/gyp/tools/pretty_sln.py @@ -1,4 +1,4 @@ -#!/usr/bin/python2.5 +#!/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 @@ -153,7 +153,7 @@ def main(): # check if we have exactly 1 parameter. if len(sys.argv) < 2: print 'Usage: %s "c:\\path\\to\\project.sln"' % sys.argv[0] - return + return 1 (projects, deps) = ParseSolution(sys.argv[1]) PrintDependencies(projects, deps) @@ -161,7 +161,8 @@ def main(): if '--recursive' in sys.argv: PrintVCProj(projects) + return 0 -if __name__ == '__main__': - main() +if __name__ == '__main__': + sys.exit(main()) diff --git a/tools/gyp/tools/pretty_vcproj.py b/tools/gyp/tools/pretty_vcproj.py index 292a39f7cf3..ba65bf23867 100755 --- a/tools/gyp/tools/pretty_vcproj.py +++ b/tools/gyp/tools/pretty_vcproj.py @@ -1,4 +1,4 @@ -#!/usr/bin/python2.5 +#!/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 @@ -23,14 +23,16 @@ from xml.dom.minidom import Node REPLACEMENTS = dict() ARGUMENTS = None -class CmpTuple: + +class CmpTuple(object): """Compare function between 2 tuple.""" def __call__(self, x, y): (key1, value1) = x (key2, value2) = y return cmp(key1, key2) -class CmpNode: + +class CmpNode(object): """Compare function between 2 xml nodes.""" def get_string(self, node): @@ -57,6 +59,7 @@ class CmpNode: def __call__(self, x, y): return cmp(self.get_string(x), self.get_string(y)) + def PrettyPrintNode(node, indent=0): if node.nodeType == Node.TEXT_NODE: if node.data.strip(): @@ -90,6 +93,7 @@ def PrettyPrintNode(node, indent=0): PrettyPrintNode(sub_node, indent=indent+2) print '%s</%s>' % (' '*indent, node.nodeName) + def FlattenFilter(node): """Returns a list of all the node and sub nodes.""" node_list = [] @@ -107,6 +111,7 @@ def FlattenFilter(node): return node_list + def FixFilenames(filenames, current_directory): new_list = [] for filename in filenames: @@ -121,8 +126,9 @@ def FixFilenames(filenames, current_directory): new_list.append(os.path.abspath(filename)) return new_list + def AbsoluteNode(node): - # Make all the properties we know about in this node absolute. + """Makes all the properties we know about in this node absolute.""" if node.attributes: for (name, value) in node.attributes.items(): if name in ['InheritedPropertySheets', 'RelativePath', @@ -136,8 +142,9 @@ def AbsoluteNode(node): if not value: node.removeAttribute(name) + def CleanupVcproj(node): - # For each sub node, we call recursively this function. + """For each sub node, we call recursively this function.""" for sub_node in node.childNodes: AbsoluteNode(sub_node) CleanupVcproj(sub_node) @@ -192,6 +199,7 @@ def CleanupVcproj(node): continue node.appendChild(new_node) + def GetConfiguationNodes(vcproj): #TODO(nsylvain): Find a better way to navigate the xml. nodes = [] @@ -203,6 +211,7 @@ def GetConfiguationNodes(vcproj): return nodes + def GetChildrenVsprops(filename): dom = parse(filename) if dom.documentElement.attributes: @@ -231,6 +240,7 @@ def SeekToNode(node1, child2): # No match. We give up. return None + def MergeAttributes(node1, node2): # No attributes to merge? if not node2.attributes: @@ -255,6 +265,7 @@ def MergeAttributes(node1, node2): if name == 'InheritedPropertySheets': node1.removeAttribute(name) + def MergeProperties(node1, node2): MergeAttributes(node1, node2) for child2 in node2.childNodes: @@ -264,6 +275,7 @@ def MergeProperties(node1, node2): else: node1.appendChild(child2.cloneNode(True)) + def main(argv): global REPLACEMENTS global ARGUMENTS @@ -274,7 +286,7 @@ def main(argv): if len(argv) < 2: print ('Usage: %s "c:\\path\\to\\vcproj.vcproj" [key1=value1] ' '[key2=value2]' % argv[0]) - return + return 1 # Parse the keys for i in range(2, len(argv)): @@ -311,6 +323,8 @@ def main(argv): # user. #print dom.toprettyxml(newl="\n") PrettyPrintNode(dom.documentElement) + return 0 + if __name__ == '__main__': - main(sys.argv) + sys.exit(main(sys.argv)) |