summaryrefslogtreecommitdiff
path: root/tools/gyp/pylib
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2011-09-18 12:08:43 -0700
committerRyan Dahl <ry@tinyclouds.org>2011-09-18 12:25:30 -0700
commit100fc27ebb071b7833e0c6f0c10145206ad257e7 (patch)
treedb435f0eaf81de870ed8af9f602063b0990a2283 /tools/gyp/pylib
parentf90264d2462e0e24b9a4479b23443c518d24ef0d (diff)
downloadnode-new-100fc27ebb071b7833e0c6f0c10145206ad257e7.tar.gz
Upgrade gyp to r1046
Diffstat (limited to 'tools/gyp/pylib')
-rw-r--r--tools/gyp/pylib/gyp/generator/make.py142
-rw-r--r--tools/gyp/pylib/gyp/generator/msvs.py34
-rw-r--r--tools/gyp/pylib/gyp/generator/ninja.py49
-rw-r--r--tools/gyp/pylib/gyp/input.py8
4 files changed, 135 insertions, 98 deletions
diff --git a/tools/gyp/pylib/gyp/generator/make.py b/tools/gyp/pylib/gyp/generator/make.py
index 24037ab177..2413b6a924 100644
--- a/tools/gyp/pylib/gyp/generator/make.py
+++ b/tools/gyp/pylib/gyp/generator/make.py
@@ -61,12 +61,7 @@ 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',
- }
- flavor = flavors.get(sys.platform, 'linux')
- return params.get('flavor', flavor)
+ return params.get('flavor', 'mac' if sys.platform == 'darwin' else 'linux')
def CalculateVariables(default_variables, params):
@@ -75,8 +70,7 @@ def CalculateVariables(default_variables, params):
default_variables['LINKER_SUPPORTS_ICF'] = \
gyp.system_test.TestLinkerSupportsICF(cc_command=cc_target)
- flavor = GetFlavor(params)
- if flavor == 'mac':
+ if GetFlavor(params) == 'mac':
default_variables.setdefault('OS', 'mac')
default_variables.setdefault('SHARED_LIB_SUFFIX', '.dylib')
default_variables.setdefault('SHARED_LIB_DIR',
@@ -99,7 +93,7 @@ def CalculateVariables(default_variables, params):
global COMPILABLE_EXTENSIONS
COMPILABLE_EXTENSIONS.update({'.m': 'objc', '.mm' : 'objcxx'})
else:
- default_variables.setdefault('OS', flavor)
+ default_variables.setdefault('OS', 'linux')
default_variables.setdefault('SHARED_LIB_SUFFIX', '.so')
default_variables.setdefault('SHARED_LIB_DIR','$(builddir)/lib.$(TOOLSET)')
default_variables.setdefault('LIB_DIR', '$(obj).$(TOOLSET)')
@@ -186,6 +180,31 @@ quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS)
"""
+LINK_COMMANDS_ANDROID = """\
+quiet_cmd_alink = AR($(TOOLSET)) $@
+cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) $(ARFLAGS.$(TOOLSET)) $@ $(filter %.o,$^)
+
+# Due to circular dependencies between libraries :(, we wrap the
+# special "figure out circular dependencies" flags around the entire
+# input list during linking.
+quiet_cmd_link = LINK($(TOOLSET)) $@
+quiet_cmd_link_host = LINK($(TOOLSET)) $@
+cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS)
+cmd_link_host = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS)
+
+# Other shared-object link notes:
+# - Set SONAME to the library filename so our binaries don't reference
+# the local, absolute paths used on the link command-line.
+quiet_cmd_solink = SOLINK($(TOOLSET)) $@
+cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS)
+
+quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
+cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS)
+quiet_cmd_solink_module_host = SOLINK_MODULE($(TOOLSET)) $@
+cmd_solink_module_host = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS)
+"""
+
+
# Header of toplevel Makefile.
# This should go into the build tree, but it's easier to keep it here for now.
SHARED_HEADER = ("""\
@@ -228,16 +247,16 @@ abs_obj := $(abspath $(obj))
# generated dependency rule Makefiles in one pass.
all_deps :=
-# C++ apps need to be linked with g++. Not sure what's appropriate.
+# C++ apps need to be linked with g++.
#
-# Note, the flock is used to seralize linking. Linking is a memory-intensive
+# Note: flock is used to seralize linking. Linking is a memory-intensive
# process so running parallel links can often lead to thrashing. To disable
-# the serialization, override FLOCK via an envrionment variable as follows:
+# the serialization, override LINK via an envrionment variable as follows:
#
-# export FLOCK=
+# export LINK=g++
#
# This will allow make to invoke N linker processes as specified in -jN.
-FLOCK ?= %(flock)s $(builddir)/linker.lock
+LINK ?= %(flock)s $(builddir)/linker.lock $(CXX)
%(make_global_settings)s
@@ -330,7 +349,7 @@ cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $
quiet_cmd_cxx = CXX($(TOOLSET)) $@
cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
-%(extra_commands)s
+%(mac_commands)s
quiet_cmd_touch = TOUCH $@
cmd_touch = touch $@
@@ -444,14 +463,6 @@ quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@
cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4)
"""
-SHARED_HEADER_SUN_COMMANDS = """
-# gyp-sun-tool is written next to the root Makefile by gyp.
-# Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd
-# already.
-quiet_cmd_sun_tool = SUNTOOL $(4) $<
-cmd_sun_tool = ./gyp-sun-tool $(4) $< "$@"
-"""
-
def WriteRootHeaderSuffixRules(writer):
extensions = sorted(COMPILABLE_EXTENSIONS.keys(), key=str.lower)
@@ -1023,24 +1034,29 @@ class MacPrefixHeader(object):
# This doesn't support per-configuration prefix headers. Good enough
# for now.
self.header = None
+ self.compile_headers = False
if path_provider.flavor == 'mac':
self.header = path_provider.xcode_settings.GetPerTargetSetting(
'GCC_PREFIX_HEADER')
+ self.compile_headers = path_provider.xcode_settings.GetPerTargetSetting(
+ 'GCC_PRECOMPILE_PREFIX_HEADER', default='NO') != 'NO'
self.compiled_headers = {}
if self.header:
self.header = path_provider.Absolutify(self.header)
- for lang in ['c', 'cc', 'm', 'mm']:
- self.compiled_headers[lang] = path_provider.Pchify(self.header, lang)
+ if self.compile_headers:
+ for lang in ['c', 'cc', 'm', 'mm']:
+ self.compiled_headers[lang] = path_provider.Pchify(self.header, lang)
def _Gch(self, lang):
"""Returns the actual file name of the prefix header for language |lang|."""
+ assert self.compile_headers
return self.compiled_headers[lang] + '.gch'
def WriteObjDependencies(self, compilable, objs, writer):
"""Writes dependencies from the object files in |objs| to the corresponding
precompiled header file. |compilable[i]| has to be the source file belonging
to |objs[i]|."""
- if not self.header:
+ if not self.header or not self.compile_headers:
return
writer.WriteLn('# Dependencies from obj files to their precompiled headers')
@@ -1058,13 +1074,16 @@ class MacPrefixHeader(object):
def GetInclude(self, lang):
"""Gets the cflags to include the prefix header for language |lang|."""
- if lang not in self.compiled_headers:
+ if self.compile_headers and lang in self.compiled_headers:
+ return '-include %s ' % self.compiled_headers[lang]
+ elif self.header:
+ return '-include %s ' % self.header
+ else:
return ''
- return '-include %s ' % self.compiled_headers[lang]
def WritePchTargets(self, writer):
"""Writes make rules to compile the prefix headers."""
- if not self.header:
+ if not self.header or not self.compile_headers:
return
writer.WriteLn(self._Gch('c') + ": GYP_PCH_CFLAGS := "
@@ -1919,8 +1938,13 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
if self.type == 'executable':
self.WriteLn(
'%s: LD_INPUTS := %s' % (self.output_binary, ' '.join(link_deps)))
- self.WriteDoCmd([self.output_binary], link_deps, 'link', part_of_all,
- postbuilds=postbuilds)
+ if self.toolset == 'host' and self.flavor == 'android':
+ self.WriteDoCmd([self.output_binary], link_deps, 'link_host',
+ part_of_all, postbuilds=postbuilds)
+ else:
+ self.WriteDoCmd([self.output_binary], link_deps, 'link', part_of_all,
+ postbuilds=postbuilds)
+
elif self.type == 'static_library':
for link_dep in link_deps:
assert ' ' not in link_dep, (
@@ -1936,9 +1960,13 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
for link_dep in link_deps:
assert ' ' not in link_dep, (
"Spaces in module input filenames not supported (%s)" % link_dep)
- self.WriteDoCmd(
- [self.output_binary], link_deps, 'solink_module', part_of_all,
- postbuilds=postbuilds)
+ if self.toolset == 'host' and self.flavor == 'android':
+ self.WriteDoCmd([self.output_binary], link_deps, 'solink_module_host',
+ part_of_all, postbuilds=postbuilds)
+ else:
+ self.WriteDoCmd(
+ [self.output_binary], link_deps, 'solink_module', part_of_all,
+ postbuilds=postbuilds)
elif self.type == 'none':
# Write a stamp line.
self.WriteDoCmd([self.output_binary], deps, 'touch', part_of_all,
@@ -2396,31 +2424,17 @@ def RunSystemTests(flavor):
'LINK_flags': link_flags }
-def CopyTool(flavor, out_path):
- """Finds (mac|sun)_tool.gyp in the gyp directory and copies it to |out_path|."""
- prefix = { 'solaris': 'sun', 'mac': 'mac' }.get(flavor, None)
- if not prefix:
- return
-
- tool_path = os.path.join(out_path, 'gyp-%s-tool' % prefix)
- if os.path.exists(tool_path):
- os.remove(tool_path)
-
- # Slurp input file.
+def CopyMacTool(out_path):
+ """Finds mac_tool.gyp in the gyp directory and copies it to |out_path|."""
source_path = os.path.join(
- os.path.dirname(os.path.abspath(__file__)), '..', '%s_tool.py' % prefix)
+ os.path.dirname(os.path.abspath(__file__)), '..', 'mac_tool.py')
source_file = open(source_path)
source = source_file.readlines()
source_file.close()
-
- # Add header and write it out.
- tool_file = open(tool_path, 'w')
- tool_file.write(
+ mactool_file = open(out_path, 'w')
+ mactool_file.write(
''.join([source[0], '# Generated by gyp. Do not edit.\n'] + source[1:]))
- tool_file.close()
-
- # Make file executable.
- os.chmod(tool_path, 0o755)
+ mactool_file.close()
def GenerateOutput(target_list, target_dicts, data, params):
@@ -2474,7 +2488,7 @@ def GenerateOutput(target_list, target_dicts, data, params):
'flock': 'flock',
'flock_index': 1,
'link_commands': LINK_COMMANDS_LINUX,
- 'extra_commands': '',
+ 'mac_commands': '',
'srcdir': srcdir,
}
if flavor == 'mac':
@@ -2482,15 +2496,12 @@ def GenerateOutput(target_list, target_dicts, data, params):
'flock': './gyp-mac-tool flock',
'flock_index': 2,
'link_commands': LINK_COMMANDS_MAC,
- 'extra_commands': SHARED_HEADER_MAC_COMMANDS,
+ 'mac_commands': SHARED_HEADER_MAC_COMMANDS,
})
- elif flavor == 'solaris':
+ if flavor == 'android':
header_params.update({
- 'flock': './gyp-sun-tool flock',
- 'flock_index': 2,
- 'extra_commands': SHARED_HEADER_SUN_COMMANDS,
+ 'link_commands': LINK_COMMANDS_ANDROID,
})
-
header_params.update(RunSystemTests(flavor))
build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0])
@@ -2528,8 +2539,13 @@ def GenerateOutput(target_list, target_dicts, data, params):
WriteRootHeaderSuffixRules(root_makefile)
# Put mac_tool next to the root Makefile.
- dest_path = os.path.dirname(makefile_path)
- CopyTool(flavor, dest_path)
+ if flavor == 'mac':
+ mactool_path = os.path.join(os.path.dirname(makefile_path), 'gyp-mac-tool')
+ if os.path.exists(mactool_path):
+ os.remove(mactool_path)
+ CopyMacTool(mactool_path)
+ # Make file executable.
+ os.chmod(mactool_path, 0755)
# Find the list of targets that derive from the gyp file(s) being built.
needed_targets = set()
diff --git a/tools/gyp/pylib/gyp/generator/msvs.py b/tools/gyp/pylib/gyp/generator/msvs.py
index dfecbda786..38ea3a271f 100644
--- a/tools/gyp/pylib/gyp/generator/msvs.py
+++ b/tools/gyp/pylib/gyp/generator/msvs.py
@@ -547,7 +547,7 @@ def _GenerateExternalRules(rules, output_dir, spec,
# Write out all: target, including mkdir for each output directory.
mk_file.write('all: %s\n' % ' '.join(first_outputs_cyg))
for od in all_output_dirs:
- mk_file.write('\tmkdir -p %s\n' % od)
+ mk_file.write('\tmkdir -p `cygpath -u "%s"`\n' % od)
mk_file.write('\n')
# Define how each output is generated.
for rule in rules:
@@ -882,7 +882,7 @@ def _GenerateMSVSProject(project, options, version):
p.AddFiles(sources)
_AddToolFilesToMSVS(p, spec)
- _HandlePreCompileHeaderStubs(p, spec)
+ _HandlePreCompiledHeaders(p, sources, spec)
_AddActions(actions_to_add, spec, relative_path_of_gyp_file)
_AddCopies(actions_to_add, spec)
_WriteMSVSUserFile(project.path, version, spec)
@@ -1383,8 +1383,12 @@ def _AddToolFilesToMSVS(p, spec):
p.AddToolFile(f)
-def _HandlePreCompileHeaderStubs(p, spec):
- # Handle pre-compiled headers source stubs specially.
+def _HandlePreCompiledHeaders(p, sources, spec):
+ # Pre-compiled header source stubs need a different compiler flag
+ # (generate precompiled header) and any source file not of the same
+ # kind (i.e. C vs. C++) as the precompiled header source stub needs
+ # to have use of precompiled headers disabled.
+ extensions_excluded_from_precompile = []
for config_name, config in spec['configurations'].iteritems():
source = config.get('msvs_precompiled_source')
if source:
@@ -1394,6 +1398,28 @@ def _HandlePreCompileHeaderStubs(p, spec):
{'UsePrecompiledHeader': '1'})
p.AddFileConfig(source, _ConfigFullName(config_name, config),
{}, tools=[tool])
+ basename, extension = os.path.splitext(source)
+ if extension == '.c':
+ extensions_excluded_from_precompile = ['.cc', '.cpp', '.cxx']
+ else:
+ extensions_excluded_from_precompile = ['.c']
+ def DisableForSourceTree(source_tree):
+ for source in source_tree:
+ if isinstance(source, MSVSProject.Filter):
+ DisableForSourceTree(source.contents)
+ else:
+ basename, extension = os.path.splitext(source)
+ if extension in extensions_excluded_from_precompile:
+ for config_name, config in spec['configurations'].iteritems():
+ tool = MSVSProject.Tool('VCCLCompilerTool',
+ {'UsePrecompiledHeader': '0',
+ 'ForcedIncludeFiles': '$(NOINHERIT)'})
+ p.AddFileConfig(_FixPath(source),
+ _ConfigFullName(config_name, config),
+ {}, tools=[tool])
+ # Do nothing if there was no precompiled source.
+ if extensions_excluded_from_precompile:
+ DisableForSourceTree(sources)
def _AddActions(actions_to_add, spec, relative_path_of_gyp_file):
diff --git a/tools/gyp/pylib/gyp/generator/ninja.py b/tools/gyp/pylib/gyp/generator/ninja.py
index b63e42cdb0..4e5a12f100 100644
--- a/tools/gyp/pylib/gyp/generator/ninja.py
+++ b/tools/gyp/pylib/gyp/generator/ninja.py
@@ -41,10 +41,10 @@ generator_default_variables = {
# Special variables that may be used by gyp 'rule' targets.
# We generate definitions for these variables on the fly when processing a
# rule.
- 'RULE_INPUT_ROOT': '$root',
- 'RULE_INPUT_PATH': '$source',
- 'RULE_INPUT_EXT': '$ext',
- 'RULE_INPUT_NAME': '$name',
+ 'RULE_INPUT_ROOT': '${root}',
+ 'RULE_INPUT_PATH': '${source}',
+ 'RULE_INPUT_EXT': '${ext}',
+ 'RULE_INPUT_NAME': '${name}',
}
# TODO: enable cross compiling once we figure out:
@@ -195,12 +195,17 @@ class NinjaWriter:
return os.path.normpath(os.path.join(obj, self.base_dir, path_dir,
path_basename))
- def StampPath(self, name):
- """Return a path for a stamp file with a particular name.
+ def WriteCollapsedDependencies(self, name, targets):
+ """Given a list of targets, return a dependency list for a single
+ file representing the result of building all the targets.
- Stamp files are used to collapse a dependency on a bunch of files
- into a single file."""
- return self.GypPathToUniqueOutput(name + '.stamp')
+ Uses a stamp file if necessary."""
+
+ if len(targets) > 1:
+ stamp = self.GypPathToUniqueOutput(name + '.stamp')
+ targets = self.ninja.build(stamp, 'stamp', targets)
+ self.ninja.newline()
+ return targets
def WriteSpec(self, spec, config):
"""The main entry point for NinjaWriter: write the build rules for a spec.
@@ -220,14 +225,10 @@ class NinjaWriter:
# running any of its internal steps.
prebuild = []
if 'dependencies' in spec:
- prebuild_deps = []
for dep in spec['dependencies']:
if dep in self.target_outputs:
- prebuild_deps.append(self.target_outputs[dep][0])
- if prebuild_deps:
- stamp = self.StampPath('predepends')
- prebuild = self.ninja.build(stamp, 'stamp', prebuild_deps)
- self.ninja.newline()
+ prebuild.append(self.target_outputs[dep][0])
+ prebuild = self.WriteCollapsedDependencies('predepends', prebuild)
# Write out actions, rules, and copies. These must happen before we
# compile any sources, so compute a list of predependencies for sources
@@ -270,11 +271,7 @@ class NinjaWriter:
if 'copies' in spec:
outputs += self.WriteCopies(spec['copies'], prebuild)
- # To simplify downstream build edges, ensure we generate a single
- # stamp file that represents the results of all of the above.
- if len(outputs) > 1:
- stamp = self.StampPath('actions_rules_copies')
- outputs = self.ninja.build(stamp, 'stamp', outputs)
+ outputs = self.WriteCollapsedDependencies('actions_rules_copies', outputs)
return outputs
@@ -322,9 +319,10 @@ class NinjaWriter:
# First write out a rule for the rule action.
name = rule['rule_name']
args = rule['action']
- description = self.GenerateDescription('RULE',
- rule.get('message', None),
- '%s $source' % name)
+ description = self.GenerateDescription(
+ 'RULE',
+ rule.get('message', None),
+ ('%s ' + generator_default_variables['RULE_INPUT_PATH']) % name)
rule_name = self.WriteNewNinjaRule(name, args, description)
# TODO: if the command references the outputs directly, we should
@@ -337,7 +335,7 @@ class NinjaWriter:
needed_variables = set(['source'])
for argument in args:
for var in special_locals:
- if '$' + var in argument:
+ if ('${%s}' % var) in argument:
needed_variables.add(var)
# For each source file, write an edge that generates all the outputs.
@@ -348,7 +346,8 @@ class NinjaWriter:
# Gather the list of outputs, expanding $vars if possible.
outputs = []
for output in rule['outputs']:
- outputs.append(output.replace('$root', root))
+ outputs.append(output.replace(
+ generator_default_variables['RULE_INPUT_ROOT'], root))
if int(rule.get('process_outputs_as_sources', False)):
extra_sources += outputs
diff --git a/tools/gyp/pylib/gyp/input.py b/tools/gyp/pylib/gyp/input.py
index d4eeebc0fc..4204f63276 100644
--- a/tools/gyp/pylib/gyp/input.py
+++ b/tools/gyp/pylib/gyp/input.py
@@ -1328,7 +1328,7 @@ class DependencyGraphNode(object):
setting.
When adding a target to the list of dependencies, this function will
- recurse into itself with |initial| set to False, to collect depenedencies
+ recurse into itself with |initial| set to False, to collect dependencies
that are linked into the linkable target for which the list is being built.
"""
if dependencies == None:
@@ -1369,11 +1369,7 @@ class DependencyGraphNode(object):
# The target is linkable, add it to the list of link dependencies.
if self.ref not in dependencies:
- if target_type != 'none':
- # Special case: "none" type targets don't produce any linkable products
- # and shouldn't be exposed as link dependencies, although dependencies
- # of "none" type targets may still be link dependencies.
- dependencies.append(self.ref)
+ dependencies.append(self.ref)
if initial or not is_linkable:
# If this is a subsequent target and it's linkable, don't look any
# further for linkable dependencies, as they'll already be linked into