summaryrefslogtreecommitdiff
path: root/tools/gyp
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2011-12-21 12:39:36 -0800
committerRyan Dahl <ry@tinyclouds.org>2011-12-21 12:39:36 -0800
commit60a9e1e40fd520a224b4a971a464227e6838e7af (patch)
treeba39e4f3af1303045a00c77c9b3ac8a491dbf047 /tools/gyp
parentf7f8af842077be4e6cc580ddedcccea71e073bbb (diff)
downloadandroid-node-v8-60a9e1e40fd520a224b4a971a464227e6838e7af.tar.gz
android-node-v8-60a9e1e40fd520a224b4a971a464227e6838e7af.tar.bz2
android-node-v8-60a9e1e40fd520a224b4a971a464227e6838e7af.zip
Upgrade GYP to r1115
Diffstat (limited to 'tools/gyp')
-rwxr-xr-xtools/gyp/buildbot/buildbot_run.py81
-rwxr-xr-xtools/gyp/gyptest.py2
-rw-r--r--tools/gyp/pylib/gyp/common.py12
-rw-r--r--tools/gyp/pylib/gyp/generator/dump_dependency_json.py15
-rw-r--r--tools/gyp/pylib/gyp/generator/make.py16
-rw-r--r--tools/gyp/pylib/gyp/generator/ninja.py166
-rw-r--r--tools/gyp/pylib/gyp/input.py9
-rw-r--r--tools/gyp/pylib/gyp/ninja_syntax.py67
-rwxr-xr-xtools/gyp/test/dependencies/b/b.gyp7
-rwxr-xr-xtools/gyp/test/dependencies/b/b3.c9
-rwxr-xr-xtools/gyp/test/dependencies/gyptest-lib-only.py2
-rwxr-xr-xtools/gyp/test/dependencies/gyptest-none-traversal.py25
-rw-r--r--tools/gyp/test/dependencies/main.c14
-rwxr-xr-xtools/gyp/test/dependencies/none_traversal.gyp46
-rw-r--r--tools/gyp/test/lib/TestGyp.py23
15 files changed, 399 insertions, 95 deletions
diff --git a/tools/gyp/buildbot/buildbot_run.py b/tools/gyp/buildbot/buildbot_run.py
index df1cc8ad5e..a8531258b2 100755
--- a/tools/gyp/buildbot/buildbot_run.py
+++ b/tools/gyp/buildbot/buildbot_run.py
@@ -13,7 +13,45 @@ import subprocess
import sys
-def GypTestFormat(title, format, msvs_version=None):
+if sys.platform in ['win32', 'cygwin']:
+ EXE_SUFFIX = '.exe'
+else:
+ EXE_SUFFIX = ''
+
+
+BUILDBOT_DIR = os.path.dirname(os.path.abspath(__file__))
+TRUNK_DIR = os.path.dirname(BUILDBOT_DIR)
+ROOT_DIR = os.path.dirname(TRUNK_DIR)
+OUT_DIR = os.path.join(TRUNK_DIR, 'out')
+NINJA_PATH = os.path.join(TRUNK_DIR, 'ninja' + EXE_SUFFIX)
+NINJA_WORK_DIR = os.path.join(ROOT_DIR, 'ninja_work')
+
+
+def InstallNinja():
+ """Install + build ninja.
+
+ Returns:
+ 0 for success, 1 for failure.
+ """
+ print '@@@BUILD_STEP install ninja@@@'
+ # Delete old version if any.
+ try:
+ shutil.rmtree(NINJA_WORK_DIR, ignore_errors=True)
+ except:
+ pass
+ # Sync new copy from git.
+ subprocess.check_call(
+ 'git clone https://github.com/martine/ninja.git ' + NINJA_WORK_DIR,
+ shell=True)
+ # Bootstrap.
+ subprocess.check_call('./bootstrap.sh', cwd=NINJA_WORK_DIR, shell=True)
+ # Copy out ninja.
+ shutil.copyfile(os.path.join(NINJA_WORK_DIR, 'ninja' + EXE_SUFFIX),
+ NINJA_PATH)
+ os.chmod(NINJA_PATH, 0777)
+
+
+def GypTestFormat(title, format=None, msvs_version=None):
"""Run the gyp tests for a given format, emitting annotator tags.
See annotator docs at:
@@ -23,12 +61,27 @@ def GypTestFormat(title, format, msvs_version=None):
Returns:
0 for sucesss, 1 for failure.
"""
+ if not format:
+ format = title
+
+ # Install ninja if needed.
+ # NOTE: as ninja gets installed each time, regressions to ninja can come
+ # either from changes to ninja itself, or changes to gyp.
+ if format == 'ninja':
+ try:
+ InstallNinja()
+ except Exception, e:
+ print '@@@STEP_FAILURE@@@'
+ print str(e)
+ return 1
+
print '@@@BUILD_STEP ' + title + '@@@'
sys.stdout.flush()
- buildbot_dir = os.path.dirname(os.path.abspath(__file__))
- trunk_dir = os.path.dirname(buildbot_dir)
- root_dir = os.path.dirname(trunk_dir)
env = os.environ.copy()
+ # TODO(bradnelson): remove this when this issue is resolved:
+ # http://code.google.com/p/chromium/issues/detail?id=108251
+ if format == 'ninja':
+ env['NOGOLD'] = '1'
if msvs_version:
env['GYP_MSVS_VERSION'] = msvs_version
retcode = subprocess.call(' '.join(
@@ -38,7 +91,7 @@ def GypTestFormat(title, format, msvs_version=None):
'--format', format,
'--chdir', 'trunk',
'--path', '../scons']),
- cwd=root_dir, env=env, shell=True)
+ cwd=ROOT_DIR, env=env, shell=True)
if retcode:
# Emit failure tag, and keep going.
print '@@@STEP_FAILURE@@@'
@@ -49,17 +102,23 @@ def GypTestFormat(title, format, msvs_version=None):
def GypBuild():
# Dump out/ directory.
print '@@@BUILD_STEP cleanup@@@'
- print 'Removing out/ ...'
- shutil.rmtree('out', ignore_errors=True)
+ print 'Removing %s...' % OUT_DIR
+ shutil.rmtree(OUT_DIR, ignore_errors=True)
+ print 'Removing %s...' % NINJA_WORK_DIR
+ shutil.rmtree(NINJA_WORK_DIR, ignore_errors=True)
+ print 'Removing %s...' % NINJA_PATH
+ shutil.rmtree(NINJA_PATH, ignore_errors=True)
print 'Done.'
retcode = 0
if sys.platform.startswith('linux'):
- retcode += GypTestFormat('scons', format='scons')
- retcode += GypTestFormat('make', format='make')
+ retcode += GypTestFormat('ninja')
+ retcode += GypTestFormat('scons')
+ retcode += GypTestFormat('make')
elif sys.platform == 'darwin':
- retcode += GypTestFormat('xcode', format='xcode')
- retcode += GypTestFormat('make', format='make')
+ retcode += GypTestFormat('ninja')
+ retcode += GypTestFormat('xcode')
+ retcode += GypTestFormat('make')
elif sys.platform == 'win32':
retcode += GypTestFormat('msvs-2008', format='msvs', msvs_version='2008')
if os.environ['BUILDBOT_BUILDERNAME'] == 'gyp-win64':
diff --git a/tools/gyp/gyptest.py b/tools/gyp/gyptest.py
index 0cf38b15c5..e8bf482d99 100755
--- a/tools/gyp/gyptest.py
+++ b/tools/gyp/gyptest.py
@@ -212,7 +212,7 @@ def main(argv=None):
'win32': ['msvs'],
'linux2': ['make', 'ninja'],
'linux3': ['make', 'ninja'],
- 'darwin': ['make', 'xcode'],
+ 'darwin': ['make', 'ninja', 'xcode'],
}[sys.platform]
for format in format_list:
diff --git a/tools/gyp/pylib/gyp/common.py b/tools/gyp/pylib/gyp/common.py
index b44b0956f7..97594cd5d6 100644
--- a/tools/gyp/pylib/gyp/common.py
+++ b/tools/gyp/pylib/gyp/common.py
@@ -344,6 +344,18 @@ def WriteOnDiff(filename):
return Writer()
+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)
+
+
# From Alex Martelli,
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52560
# ASPN: Python Cookbook: Remove duplicates from a sequence
diff --git a/tools/gyp/pylib/gyp/generator/dump_dependency_json.py b/tools/gyp/pylib/gyp/generator/dump_dependency_json.py
index ada1d35b07..1e0900a231 100644
--- a/tools/gyp/pylib/gyp/generator/dump_dependency_json.py
+++ b/tools/gyp/pylib/gyp/generator/dump_dependency_json.py
@@ -25,21 +25,10 @@ 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', GetFlavor(params))
+ default_variables['OS'] = generator_flags.get(
+ 'os', gyp.common.GetFlavor(params))
def CalculateGeneratorInputInfo(params):
diff --git a/tools/gyp/pylib/gyp/generator/make.py b/tools/gyp/pylib/gyp/generator/make.py
index 31c016e4c8..87ad79a675 100644
--- a/tools/gyp/pylib/gyp/generator/make.py
+++ b/tools/gyp/pylib/gyp/generator/make.py
@@ -55,25 +55,13 @@ generator_supports_multiple_toolsets = True
generator_wants_sorted_dependencies = False
-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):
"""Calculate additional variables for use in the build (called by gyp)."""
cc_target = os.environ.get('CC.target', os.environ.get('CC', 'cc'))
default_variables['LINKER_SUPPORTS_ICF'] = \
gyp.system_test.TestLinkerSupportsICF(cc_command=cc_target)
- flavor = GetFlavor(params)
+ flavor = gyp.common.GetFlavor(params)
if flavor == 'mac':
default_variables.setdefault('OS', 'mac')
default_variables.setdefault('SHARED_LIB_SUFFIX', '.dylib')
@@ -2722,7 +2710,7 @@ def CopyTool(flavor, out_path):
def GenerateOutput(target_list, target_dicts, data, params):
options = params['options']
- flavor = GetFlavor(params)
+ flavor = gyp.common.GetFlavor(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)
diff --git a/tools/gyp/pylib/gyp/generator/ninja.py b/tools/gyp/pylib/gyp/generator/ninja.py
index b307da650d..193f295a55 100644
--- a/tools/gyp/pylib/gyp/generator/ninja.py
+++ b/tools/gyp/pylib/gyp/generator/ninja.py
@@ -13,18 +13,15 @@ import sys
import gyp.ninja_syntax as ninja_syntax
generator_default_variables = {
- 'OS': 'linux',
-
'EXECUTABLE_PREFIX': '',
'EXECUTABLE_SUFFIX': '',
'STATIC_LIB_PREFIX': '',
'STATIC_LIB_SUFFIX': '.a',
'SHARED_LIB_PREFIX': 'lib',
- 'SHARED_LIB_SUFFIX': '.so',
# Gyp expects the following variables to be expandable by the build
# system to the appropriate locations. Ninja prefers paths to be
- # known at compile time. To resolve this, introduce special
+ # known at gyp time. To resolve this, introduce special
# variables starting with $! (which begin with a $ so gyp knows it
# should be treated as a path, but is otherwise an invalid
# ninja/shell variable) that are passed to gyp here but expanded
@@ -103,7 +100,7 @@ def InvertRelativePath(path):
# to the input file name as well as the output target name.
class NinjaWriter:
- def __init__(self, target_outputs, base_dir, build_dir, output_file):
+ def __init__(self, target_outputs, base_dir, build_dir, output_file, flavor):
"""
base_dir: path from source root to directory containing this gyp file,
by gyp semantics, all input paths are relative to this
@@ -114,6 +111,7 @@ class NinjaWriter:
self.base_dir = base_dir
self.build_dir = build_dir
self.ninja = ninja_syntax.Writer(output_file)
+ self.flavor = flavor
# Relative path from build output dir to base dir.
self.build_to_base = os.path.join(InvertRelativePath(build_dir), base_dir)
@@ -422,18 +420,32 @@ class NinjaWriter:
self.ninja.variable('cc', '$cc_host')
self.ninja.variable('cxx', '$cxx_host')
+ if self.flavor == 'mac':
+ # TODO(jeremya/thakis): Extract these from XcodeSettings instead.
+ cflags = []
+ cflags_c = []
+ cflags_cc = []
+ cflags_objc = []
+ cflags_objcc = []
+ else:
+ cflags = config.get('cflags', [])
+ cflags_c = config.get('cflags_c', [])
+ cflags_cc = config.get('cflags_cc', [])
+
self.WriteVariableList('defines',
[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', 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.WriteVariableList('cflags', map(self.ExpandSpecial, cflags))
+ self.WriteVariableList('cflags_c', map(self.ExpandSpecial, cflags_c))
+ self.WriteVariableList('cflags_cc', map(self.ExpandSpecial, cflags_cc))
+ if self.flavor == 'mac':
+ self.WriteVariableList('cflags_objc', map(self.ExpandSpecial,
+ cflags_objc))
+ self.WriteVariableList('cflags_objcc', map(self.ExpandSpecial,
+ cflags_objcc))
self.ninja.newline()
outputs = []
for source in sources:
@@ -443,6 +455,10 @@ class NinjaWriter:
command = 'cxx'
elif ext in ('c', 's', 'S'):
command = 'cc'
+ elif self.flavor == 'mac' and ext == 'm':
+ command = 'objc'
+ elif self.flavor == 'mac' and ext == 'mm':
+ command = 'objcxx'
else:
# TODO: should we assert here on unexpected extensions?
continue
@@ -498,9 +514,14 @@ class NinjaWriter:
command = command_map[spec['type']]
if output_uses_linker:
+ if self.flavor == 'mac':
+ # TODO(jeremya/thakis): Get this from XcodeSettings.
+ ldflags = []
+ else:
+ ldflags = config.get('ldflags', [])
self.WriteVariableList('ldflags',
gyp.common.uniquer(map(self.ExpandSpecial,
- config.get('ldflags', []))))
+ ldflags)))
self.WriteVariableList('libs',
gyp.common.uniquer(map(self.ExpandSpecial,
spec.get('libraries', []))))
@@ -534,6 +555,10 @@ class NinjaWriter:
'loadable_module': 'so',
'shared_library': 'so',
}
+ # TODO(thakis/jeremya): Remove once the mac path name computation is done
+ # by XcodeSettings.
+ if self.flavor == 'mac':
+ DEFAULT_EXTENSION['shared_library'] = 'dylib'
extension = spec.get('product_extension',
DEFAULT_EXTENSION.get(spec['type'], ''))
if extension:
@@ -576,6 +601,10 @@ class NinjaWriter:
if self.toolset != 'target':
libdir = 'lib/%s' % self.toolset
return os.path.join(libdir, filename)
+ # TODO(thakis/jeremya): Remove once the mac path name computation is done
+ # by XcodeSettings.
+ elif spec['type'] == 'static_library' and self.flavor == 'mac':
+ return filename
else:
return self.GypPathToUniqueOutput(filename, qualified=False)
@@ -619,6 +648,32 @@ def CalculateVariables(default_variables, params):
default_variables['LINKER_SUPPORTS_ICF'] = \
gyp.system_test.TestLinkerSupportsICF(cc_command=cc_target)
+ flavor = gyp.common.GetFlavor(params)
+ if flavor == 'mac':
+ default_variables.setdefault('OS', 'mac')
+ default_variables.setdefault('SHARED_LIB_SUFFIX', '.dylib')
+
+ # TODO(jeremya/thakis): Set SHARED_LIB_DIR / LIB_DIR.
+
+ # Copy additional generator configuration data from Xcode, which is shared
+ # by the Mac Ninja generator.
+ import gyp.generator.xcode as xcode_generator
+ global generator_additional_non_configuration_keys
+ generator_additional_non_configuration_keys = getattr(xcode_generator,
+ 'generator_additional_non_configuration_keys', [])
+ global generator_additional_path_sections
+ generator_additional_path_sections = getattr(xcode_generator,
+ 'generator_additional_path_sections', [])
+ global generator_extra_sources_for_rules
+ generator_extra_sources_for_rules = getattr(xcode_generator,
+ 'generator_extra_sources_for_rules', [])
+ else:
+ operating_system = flavor
+ if flavor == 'android':
+ operating_system = 'linux' # Keep this legacy behavior for now.
+ default_variables.setdefault('OS', operating_system)
+ default_variables.setdefault('SHARED_LIB_SUFFIX', '.so')
+
def OpenOutput(path):
"""Open |path| for writing, creating directories if necessary."""
@@ -631,6 +686,7 @@ def OpenOutput(path):
def GenerateOutput(target_list, target_dicts, data, params):
options = params['options']
+ flavor = gyp.common.GetFlavor(params)
generator_flags = params.get('generator_flags', {})
if options.generator_output:
@@ -653,7 +709,13 @@ def GenerateOutput(target_list, target_dicts, data, params):
# TODO: compute cc/cxx/ld/etc. by command-line arguments and system tests.
master_ninja.variable('cc', os.environ.get('CC', 'gcc'))
master_ninja.variable('cxx', os.environ.get('CXX', 'g++'))
- master_ninja.variable('ld', '$cxx -Wl,--threads -Wl,--thread-count=4')
+ # TODO(bradnelson): remove NOGOLD when this is resolved:
+ # http://code.google.com/p/chromium/issues/detail?id=108251
+ if flavor != 'mac' and not os.environ.get('NOGOLD'):
+ master_ninja.variable('ld', '$cxx -Wl,--threads -Wl,--thread-count=4')
+ else:
+ # TODO(jeremya/thakis): flock
+ master_ninja.variable('ld', '$cxx')
master_ninja.variable('cc_host', '$cc')
master_ninja.variable('cxx_host', '$cxx')
master_ninja.newline()
@@ -670,25 +732,60 @@ def GenerateOutput(target_list, target_dicts, data, params):
command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_cc '
'-c $in -o $out'),
depfile='$out.d')
- master_ninja.rule(
- 'alink',
- description='AR $out',
- command='rm -f $out && ar rcsT $out $in')
- master_ninja.rule(
- 'solink',
- description='SOLINK $out',
- command=('$ld -shared $ldflags -o $out -Wl,-soname=$soname '
- '-Wl,--whole-archive $in -Wl,--no-whole-archive $libs'))
- master_ninja.rule(
- 'solink_module',
- description='SOLINK(module) $out',
- command=('$ld -shared $ldflags -o $out -Wl,-soname=$soname '
- '-Wl,--start-group $in -Wl,--end-group $libs'))
- master_ninja.rule(
- 'link',
- description='LINK $out',
- command=('$ld $ldflags -o $out -Wl,-rpath=\$$ORIGIN/lib '
- '-Wl,--start-group $in -Wl,--end-group $libs'))
+ if flavor != 'mac':
+ master_ninja.rule(
+ 'alink',
+ description='AR $out',
+ command='rm -f $out && ar rcsT $out $in')
+ master_ninja.rule(
+ 'solink',
+ description='SOLINK $out',
+ command=('$ld -shared $ldflags -o $out -Wl,-soname=$soname '
+ '-Wl,--whole-archive $in -Wl,--no-whole-archive $libs'))
+ master_ninja.rule(
+ 'solink_module',
+ description='SOLINK(module) $out',
+ command=('$ld -shared $ldflags -o $out -Wl,-soname=$soname '
+ '-Wl,--start-group $in -Wl,--end-group $libs'))
+ master_ninja.rule(
+ 'link',
+ description='LINK $out',
+ command=('$ld $ldflags -o $out -Wl,-rpath=\$$ORIGIN/lib '
+ '-Wl,--start-group $in -Wl,--end-group $libs'))
+ else:
+ master_ninja.rule(
+ 'objc',
+ description='OBJC $out',
+ command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_c '
+ '$cflags_objc -c $in -o $out'),
+ depfile='$out.d')
+ master_ninja.rule(
+ 'objcxx',
+ description='OBJCXX $out',
+ command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_cc '
+ '$cflags_objcc -c $in -o $out'),
+ depfile='$out.d')
+ master_ninja.rule(
+ 'alink',
+ description='LIBTOOL-STATIC $out',
+ command='rm -f $out && libtool -static -o $out $in')
+ # TODO(thakis): The solink_module rule is likely wrong. Xcode seems to pass
+ # -bundle -single_module here (for osmesa.so).
+ master_ninja.rule(
+ 'solink',
+ description='SOLINK $out',
+ command=('$ld -shared $ldflags -o $out '
+ '$in $libs'))
+ master_ninja.rule(
+ 'solink_module',
+ description='SOLINK(module) $out',
+ command=('$ld -shared $ldflags -o $out '
+ '$in $libs'))
+ master_ninja.rule(
+ 'link',
+ description='LINK $out',
+ command=('$ld $ldflags -o $out '
+ '$in $libs'))
master_ninja.rule(
'stamp',
description='STAMP $out',
@@ -696,7 +793,7 @@ def GenerateOutput(target_list, target_dicts, data, params):
master_ninja.rule(
'copy',
description='COPY $in $out',
- command='ln -f $in $out 2>/dev/null || cp -af $in $out')
+ command='ln -f $in $out 2>/dev/null || (rm -rf $out && cp -af $in $out)')
master_ninja.newline()
all_targets = set()
@@ -726,7 +823,8 @@ def GenerateOutput(target_list, target_dicts, data, params):
writer = NinjaWriter(target_outputs, base_path, builddir,
OpenOutput(os.path.join(options.toplevel_dir,
builddir,
- output_file)))
+ output_file)),
+ flavor)
master_ninja.subninja(output_file)
output, compile_depends = writer.WriteSpec(spec, config)
diff --git a/tools/gyp/pylib/gyp/input.py b/tools/gyp/pylib/gyp/input.py
index ef30efa4da..19a16288cd 100644
--- a/tools/gyp/pylib/gyp/input.py
+++ b/tools/gyp/pylib/gyp/input.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2011 The Chromium Authors. 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.
@@ -1358,6 +1358,13 @@ class DependencyGraphNode(object):
# True) and this target won't be linked.
return dependencies
+ # Don't traverse 'none' targets if explicitly excluded.
+ if (target_type == 'none' and
+ not targets[self.ref].get('dependencies_traverse', True)):
+ if self.ref not in dependencies:
+ dependencies.append(self.ref)
+ return dependencies
+
# Executables and loadable modules are already fully and finally linked.
# Nothing else can be a link dependency of them, there can only be
# dependencies in the sense that a dependent target might run an
diff --git a/tools/gyp/pylib/gyp/ninja_syntax.py b/tools/gyp/pylib/gyp/ninja_syntax.py
index d4776fb236..35cda05707 100644
--- a/tools/gyp/pylib/gyp/ninja_syntax.py
+++ b/tools/gyp/pylib/gyp/ninja_syntax.py
@@ -10,6 +10,10 @@ use Python.
"""
import textwrap
+import re
+
+def escape_spaces(word):
+ return word.replace('$ ','$$ ').replace(' ','$ ')
class Writer(object):
def __init__(self, output, width=78):
@@ -24,29 +28,40 @@ class Writer(object):
self.output.write('# ' + line + '\n')
def variable(self, key, value, indent=0):
+ if value is None:
+ return
+ if isinstance(value, list):
+ value = ' '.join(value)
self._line('%s = %s' % (key, value), indent)
- def rule(self, name, command, description=None, depfile=None):
+ def rule(self, name, command, description=None, depfile=None,
+ generator=False):
self._line('rule %s' % name)
self.variable('command', command, indent=1)
if description:
self.variable('description', description, indent=1)
if depfile:
self.variable('depfile', depfile, indent=1)
+ if generator:
+ self.variable('generator', '1', indent=1)
def build(self, outputs, rule, inputs=None, implicit=None, order_only=None,
variables=None):
outputs = self._as_list(outputs)
all_inputs = self._as_list(inputs)[:]
+ out_outputs = map(escape_spaces, outputs)
+ all_inputs = map(escape_spaces, all_inputs)
if implicit:
+ implicit = map(escape_spaces, self._as_list(implicit))
all_inputs.append('|')
- all_inputs.extend(self._as_list(implicit))
+ all_inputs.extend(implicit)
if order_only:
+ order_only = map(escape_spaces, self._as_list(order_only))
all_inputs.append('||')
- all_inputs.extend(self._as_list(order_only))
+ all_inputs.extend(order_only)
- self._line('build %s: %s %s' % (' '.join(outputs),
+ self._line('build %s: %s %s' % (' '.join(out_outputs),
rule,
' '.join(all_inputs)))
@@ -62,28 +77,52 @@ class Writer(object):
def subninja(self, path):
self._line('subninja %s' % path)
+ def default(self, paths):
+ self._line('default %s' % ' '.join(self._as_list(paths)))
+
def _line(self, text, indent=0):
"""Write 'text' word-wrapped at self.width characters."""
leading_space = ' ' * indent
while len(text) > self.width:
# The text is too wide; wrap if possible.
- # Find the rightmost space that would obey our width constraint.
+ self.output.write(leading_space)
+
available_space = self.width - len(leading_space) - len(' $')
- space = text.rfind(' ', 0, available_space)
- if space < 0:
- # No such space; just use the first space we can find.
- space = text.find(' ', available_space)
- if space < 0:
- # Give up on breaking.
- break
- self.output.write(leading_space + text[0:space] + ' $\n')
- text = text[space+1:]
+ # Write as much as we can into this line.
+ done = False
+ written_stuff = False
+ while available_space > 0:
+ space = re.search('((\$\$)+([^$]|^)|[^$]|^) ', text)
+ if space:
+ space_idx = space.start() + 1
+ else:
+ # No spaces left.
+ done = True
+ break
+
+ if space_idx > available_space:
+ # We're out of space.
+ if written_stuff:
+ # See if we can fit it on the next line.
+ break
+ # If we haven't written anything yet on this line, don't
+ # try to wrap.
+ self.output.write(text[0:space_idx] + ' ')
+ written_stuff = True
+ text = text[space_idx+1:]
+ available_space -= space_idx+1
+
+ self.output.write('$\n')
# Subsequent lines are continuations, so indent them.
leading_space = ' ' * (indent+2)
+ if done:
+ # No more spaces, so bail.
+ break
+
self.output.write(leading_space + text + '\n')
def _as_list(self, input):
diff --git a/tools/gyp/test/dependencies/b/b.gyp b/tools/gyp/test/dependencies/b/b.gyp
index f09e1ff13c..893dc64d65 100755
--- a/tools/gyp/test/dependencies/b/b.gyp
+++ b/tools/gyp/test/dependencies/b/b.gyp
@@ -11,5 +11,12 @@
'b.c',
],
},
+ {
+ 'target_name': 'b3',
+ 'type': 'static_library',
+ 'sources': [
+ 'b3.c',
+ ],
+ },
],
}
diff --git a/tools/gyp/test/dependencies/b/b3.c b/tools/gyp/test/dependencies/b/b3.c
new file mode 100755
index 0000000000..287f67ff31
--- /dev/null
+++ b/tools/gyp/test/dependencies/b/b3.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.
+ */
+
+int funcB() {
+ return 3;
+}
diff --git a/tools/gyp/test/dependencies/gyptest-lib-only.py b/tools/gyp/test/dependencies/gyptest-lib-only.py
index 4355d578ae..02159f5f15 100755
--- a/tools/gyp/test/dependencies/gyptest-lib-only.py
+++ b/tools/gyp/test/dependencies/gyptest-lib-only.py
@@ -29,7 +29,7 @@ if sys.platform == 'darwin':
if test.format == 'xcode':
test.built_file_must_not_exist('b', type=test.STATIC_LIB)
else:
- assert test.format == 'make'
+ assert test.format in ('make', 'ninja')
test.built_file_must_exist('b', type=test.STATIC_LIB)
else:
# Make puts the resulting library in a directory matching the input gyp file;
diff --git a/tools/gyp/test/dependencies/gyptest-none-traversal.py b/tools/gyp/test/dependencies/gyptest-none-traversal.py
new file mode 100755
index 0000000000..c09063dad3
--- /dev/null
+++ b/tools/gyp/test/dependencies/gyptest-none-traversal.py
@@ -0,0 +1,25 @@
+#!/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 static library dependencies don't traverse none targets, unless
+explicitly specified.
+"""
+
+import TestGyp
+
+import sys
+
+test = TestGyp.TestGyp()
+
+test.run_gyp('none_traversal.gyp')
+
+test.build('none_traversal.gyp', test.ALL)
+
+test.run_built_executable('needs_chain', stdout="2\n")
+test.run_built_executable('doesnt_need_chain', stdout="3\n")
+
+test.pass_test()
diff --git a/tools/gyp/test/dependencies/main.c b/tools/gyp/test/dependencies/main.c
new file mode 100644
index 0000000000..185bd482f2
--- /dev/null
+++ b/tools/gyp/test/dependencies/main.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.
+ */
+
+#include <stdio.h>
+
+extern int funcA();
+
+int main() {
+ printf("%d\n", funcA());
+ return 0;
+}
diff --git a/tools/gyp/test/dependencies/none_traversal.gyp b/tools/gyp/test/dependencies/none_traversal.gyp
new file mode 100755
index 0000000000..3d8ab30aff
--- /dev/null
+++ b/tools/gyp/test/dependencies/none_traversal.gyp
@@ -0,0 +1,46 @@
+# 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': 'needs_chain',
+ 'type': 'executable',
+ 'sources': [
+ 'a.c',
+ 'main.c',
+ ],
+ 'dependencies': ['chain'],
+ },
+ {
+ 'target_name': 'chain',
+ 'type': 'none',
+ 'dependencies': ['b/b.gyp:b'],
+ },
+ {
+ 'target_name': 'doesnt_need_chain',
+ 'type': 'executable',
+ 'sources': [
+ 'main.c',
+ ],
+ 'dependencies': ['no_chain', 'other_chain'],
+ },
+ {
+ 'target_name': 'no_chain',
+ 'type': 'none',
+ 'sources': [
+ ],
+ 'dependencies': ['b/b.gyp:b'],
+ 'dependencies_traverse': 0,
+ },
+ {
+ 'target_name': 'other_chain',
+ 'type': 'static_library',
+ 'sources': [
+ 'a.c',
+ ],
+ 'dependencies': ['b/b.gyp:b3'],
+ },
+ ],
+}
diff --git a/tools/gyp/test/lib/TestGyp.py b/tools/gyp/test/lib/TestGyp.py
index a65c3e2440..2b4b0db967 100644
--- a/tools/gyp/test/lib/TestGyp.py
+++ b/tools/gyp/test/lib/TestGyp.py
@@ -449,6 +449,11 @@ class TestGypNinja(TestGypBase):
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)]
+ if sys.platform == 'darwin':
+ libdir = os.path.join('out', 'Default', 'lib')
+ if self.configuration:
+ libdir = os.path.join('out', self.configuration, 'lib')
+ os.environ['DYLD_LIBRARY_PATH'] = libdir
return self.run(program=program, *args, **kw)
def built_file_path(self, name, type=None, **kw):
@@ -458,9 +463,10 @@ class TestGypNinja(TestGypBase):
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,):
+ if type == self.STATIC_LIB:
+ if sys.platform != 'darwin':
+ result.append('obj')
+ elif type == self.SHARED_LIB:
result.append('lib')
subdir = kw.get('subdir')
if subdir:
@@ -469,8 +475,13 @@ class TestGypNinja(TestGypBase):
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)
+ result = self.build(gyp_file, target, **kw)
+ if not result:
+ stdout = self.stdout()
+ if 'ninja: no work to do' not in stdout:
+ self.report_not_up_to_date()
+ self.fail_test()
+ return result
class TestGypMSVS(TestGypBase):
@@ -569,7 +580,7 @@ class TestGypMSVS(TestGypBase):
'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')
"""