|
@ -2,6 +2,7 @@ |
|
|
# Use of this source code is governed by a BSD-style license that can be |
|
|
# Use of this source code is governed by a BSD-style license that can be |
|
|
# found in the LICENSE file. |
|
|
# found in the LICENSE file. |
|
|
|
|
|
|
|
|
|
|
|
import collections |
|
|
import copy |
|
|
import copy |
|
|
import ntpath |
|
|
import ntpath |
|
|
import os |
|
|
import os |
|
@ -86,6 +87,46 @@ cached_username = None |
|
|
cached_domain = None |
|
|
cached_domain = None |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Based on http://code.activestate.com/recipes/576694/. |
|
|
|
|
|
class OrderedSet(collections.MutableSet): |
|
|
|
|
|
def __init__(self, iterable=None): |
|
|
|
|
|
self.end = end = [] |
|
|
|
|
|
end += [None, end, end] # sentinel node for doubly linked list |
|
|
|
|
|
self.map = {} # key --> [key, prev, next] |
|
|
|
|
|
if iterable is not None: |
|
|
|
|
|
self |= iterable |
|
|
|
|
|
|
|
|
|
|
|
def __len__(self): |
|
|
|
|
|
return len(self.map) |
|
|
|
|
|
|
|
|
|
|
|
def discard(self, key): |
|
|
|
|
|
if key in self.map: |
|
|
|
|
|
key, prev, next = self.map.pop(key) |
|
|
|
|
|
prev[2] = next |
|
|
|
|
|
next[1] = prev |
|
|
|
|
|
|
|
|
|
|
|
def __contains__(self, key): |
|
|
|
|
|
return key in self.map |
|
|
|
|
|
|
|
|
|
|
|
def add(self, key): |
|
|
|
|
|
if key not in self.map: |
|
|
|
|
|
end = self.end |
|
|
|
|
|
curr = end[1] |
|
|
|
|
|
curr[2] = end[1] = self.map[key] = [key, curr, end] |
|
|
|
|
|
|
|
|
|
|
|
def update(self, iterable): |
|
|
|
|
|
for i in iterable: |
|
|
|
|
|
if i not in self: |
|
|
|
|
|
self.add(i) |
|
|
|
|
|
|
|
|
|
|
|
def __iter__(self): |
|
|
|
|
|
end = self.end |
|
|
|
|
|
curr = end[2] |
|
|
|
|
|
while curr is not end: |
|
|
|
|
|
yield curr[0] |
|
|
|
|
|
curr = curr[2] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# TODO(gspencer): Switch the os.environ calls to be |
|
|
# TODO(gspencer): Switch the os.environ calls to be |
|
|
# win32api.GetDomainName() and win32api.GetUserName() once the |
|
|
# win32api.GetDomainName() and win32api.GetUserName() once the |
|
|
# python version in depot_tools has been updated to work on Vista |
|
|
# python version in depot_tools has been updated to work on Vista |
|
@ -179,7 +220,7 @@ def _ConvertSourcesToFilterHierarchy(sources, prefix=None, excluded=None, |
|
|
if not prefix: prefix = [] |
|
|
if not prefix: prefix = [] |
|
|
result = [] |
|
|
result = [] |
|
|
excluded_result = [] |
|
|
excluded_result = [] |
|
|
folders = dict() |
|
|
folders = collections.OrderedDict() |
|
|
# Gather files into the final result, excluded, or folders. |
|
|
# Gather files into the final result, excluded, or folders. |
|
|
for s in sources: |
|
|
for s in sources: |
|
|
if len(s) == 1: |
|
|
if len(s) == 1: |
|
@ -415,13 +456,13 @@ def _AddAccumulatedActionsToMSVS(p, spec, actions_dict): |
|
|
dicts describing the actions attached to that input file. |
|
|
dicts describing the actions attached to that input file. |
|
|
""" |
|
|
""" |
|
|
for primary_input in actions_dict: |
|
|
for primary_input in actions_dict: |
|
|
inputs = set() |
|
|
inputs = OrderedSet() |
|
|
outputs = set() |
|
|
outputs = OrderedSet() |
|
|
descriptions = [] |
|
|
descriptions = [] |
|
|
commands = [] |
|
|
commands = [] |
|
|
for action in actions_dict[primary_input]: |
|
|
for action in actions_dict[primary_input]: |
|
|
inputs.update(set(action['inputs'])) |
|
|
inputs.update(OrderedSet(action['inputs'])) |
|
|
outputs.update(set(action['outputs'])) |
|
|
outputs.update(OrderedSet(action['outputs'])) |
|
|
descriptions.append(action['description']) |
|
|
descriptions.append(action['description']) |
|
|
commands.append(action['command']) |
|
|
commands.append(action['command']) |
|
|
# Add the custom build step for one input file. |
|
|
# Add the custom build step for one input file. |
|
@ -477,8 +518,8 @@ def _RuleInputsAndOutputs(rule, trigger_file): |
|
|
""" |
|
|
""" |
|
|
raw_inputs = _FixPaths(rule.get('inputs', [])) |
|
|
raw_inputs = _FixPaths(rule.get('inputs', [])) |
|
|
raw_outputs = _FixPaths(rule.get('outputs', [])) |
|
|
raw_outputs = _FixPaths(rule.get('outputs', [])) |
|
|
inputs = set() |
|
|
inputs = OrderedSet() |
|
|
outputs = set() |
|
|
outputs = OrderedSet() |
|
|
inputs.add(trigger_file) |
|
|
inputs.add(trigger_file) |
|
|
for i in raw_inputs: |
|
|
for i in raw_inputs: |
|
|
inputs.add(_RuleExpandPath(i, trigger_file)) |
|
|
inputs.add(_RuleExpandPath(i, trigger_file)) |
|
@ -549,16 +590,16 @@ def _GenerateExternalRules(rules, output_dir, spec, |
|
|
mk_file.write('OutDirCygwin:=$(shell cygpath -u "$(OutDir)")\n') |
|
|
mk_file.write('OutDirCygwin:=$(shell cygpath -u "$(OutDir)")\n') |
|
|
mk_file.write('IntDirCygwin:=$(shell cygpath -u "$(IntDir)")\n') |
|
|
mk_file.write('IntDirCygwin:=$(shell cygpath -u "$(IntDir)")\n') |
|
|
# Gather stuff needed to emit all: target. |
|
|
# Gather stuff needed to emit all: target. |
|
|
all_inputs = set() |
|
|
all_inputs = OrderedSet() |
|
|
all_outputs = set() |
|
|
all_outputs = OrderedSet() |
|
|
all_output_dirs = set() |
|
|
all_output_dirs = OrderedSet() |
|
|
first_outputs = [] |
|
|
first_outputs = [] |
|
|
for rule in rules: |
|
|
for rule in rules: |
|
|
trigger_files = _FindRuleTriggerFiles(rule, sources) |
|
|
trigger_files = _FindRuleTriggerFiles(rule, sources) |
|
|
for tf in trigger_files: |
|
|
for tf in trigger_files: |
|
|
inputs, outputs = _RuleInputsAndOutputs(rule, tf) |
|
|
inputs, outputs = _RuleInputsAndOutputs(rule, tf) |
|
|
all_inputs.update(set(inputs)) |
|
|
all_inputs.update(OrderedSet(inputs)) |
|
|
all_outputs.update(set(outputs)) |
|
|
all_outputs.update(OrderedSet(outputs)) |
|
|
# Only use one target from each rule as the dependency for |
|
|
# Only use one target from each rule as the dependency for |
|
|
# 'all' so we don't try to build each rule multiple times. |
|
|
# 'all' so we don't try to build each rule multiple times. |
|
|
first_outputs.append(list(outputs)[0]) |
|
|
first_outputs.append(list(outputs)[0]) |
|
@ -799,8 +840,8 @@ def _AdjustSourcesForRules(spec, rules, sources, excluded_sources): |
|
|
trigger_files = _FindRuleTriggerFiles(rule, sources) |
|
|
trigger_files = _FindRuleTriggerFiles(rule, sources) |
|
|
for trigger_file in trigger_files: |
|
|
for trigger_file in trigger_files: |
|
|
inputs, outputs = _RuleInputsAndOutputs(rule, trigger_file) |
|
|
inputs, outputs = _RuleInputsAndOutputs(rule, trigger_file) |
|
|
inputs = set(_FixPaths(inputs)) |
|
|
inputs = OrderedSet(_FixPaths(inputs)) |
|
|
outputs = set(_FixPaths(outputs)) |
|
|
outputs = OrderedSet(_FixPaths(outputs)) |
|
|
inputs.remove(_FixPath(trigger_file)) |
|
|
inputs.remove(_FixPath(trigger_file)) |
|
|
sources.update(inputs) |
|
|
sources.update(inputs) |
|
|
if not spec.get('msvs_external_builder'): |
|
|
if not spec.get('msvs_external_builder'): |
|
@ -817,7 +858,7 @@ def _FilterActionsFromExcluded(excluded_sources, actions_to_add): |
|
|
Returns: |
|
|
Returns: |
|
|
excluded_sources with files that have actions attached removed. |
|
|
excluded_sources with files that have actions attached removed. |
|
|
""" |
|
|
""" |
|
|
must_keep = set(_FixPaths(actions_to_add.keys())) |
|
|
must_keep = OrderedSet(_FixPaths(actions_to_add.keys())) |
|
|
return [s for s in excluded_sources if s not in must_keep] |
|
|
return [s for s in excluded_sources if s not in must_keep] |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -965,7 +1006,7 @@ def _GetUniquePlatforms(spec): |
|
|
The MSVSUserFile object created. |
|
|
The MSVSUserFile object created. |
|
|
""" |
|
|
""" |
|
|
# Gather list of unique platforms. |
|
|
# Gather list of unique platforms. |
|
|
platforms = set() |
|
|
platforms = OrderedSet() |
|
|
for configuration in spec['configurations']: |
|
|
for configuration in spec['configurations']: |
|
|
platforms.add(_ConfigPlatform(spec['configurations'][configuration])) |
|
|
platforms.add(_ConfigPlatform(spec['configurations'][configuration])) |
|
|
platforms = list(platforms) |
|
|
platforms = list(platforms) |
|
@ -1152,7 +1193,7 @@ def _GetLibraries(spec): |
|
|
# in libraries that are assumed to be in the default library path). |
|
|
# in libraries that are assumed to be in the default library path). |
|
|
# Also remove duplicate entries, leaving only the last duplicate, while |
|
|
# Also remove duplicate entries, leaving only the last duplicate, while |
|
|
# preserving order. |
|
|
# preserving order. |
|
|
found = set() |
|
|
found = OrderedSet() |
|
|
unique_libraries_list = [] |
|
|
unique_libraries_list = [] |
|
|
for entry in reversed(libraries): |
|
|
for entry in reversed(libraries): |
|
|
library = re.sub('^\-l', '', entry) |
|
|
library = re.sub('^\-l', '', entry) |
|
@ -1331,8 +1372,7 @@ def _GetMSVSAttributes(spec, config, config_type): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _AddNormalizedSources(sources_set, sources_array): |
|
|
def _AddNormalizedSources(sources_set, sources_array): |
|
|
sources = [_NormalizedSource(s) for s in sources_array] |
|
|
sources_set.update(_NormalizedSource(s) for s in sources_array) |
|
|
sources_set.update(set(sources)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _PrepareListOfSources(spec, generator_flags, gyp_file): |
|
|
def _PrepareListOfSources(spec, generator_flags, gyp_file): |
|
@ -1350,9 +1390,9 @@ def _PrepareListOfSources(spec, generator_flags, gyp_file): |
|
|
A pair of (list of sources, list of excluded sources). |
|
|
A pair of (list of sources, list of excluded sources). |
|
|
The sources will be relative to the gyp file. |
|
|
The sources will be relative to the gyp file. |
|
|
""" |
|
|
""" |
|
|
sources = set() |
|
|
sources = OrderedSet() |
|
|
_AddNormalizedSources(sources, spec.get('sources', [])) |
|
|
_AddNormalizedSources(sources, spec.get('sources', [])) |
|
|
excluded_sources = set() |
|
|
excluded_sources = OrderedSet() |
|
|
# Add in the gyp file. |
|
|
# Add in the gyp file. |
|
|
if not generator_flags.get('standalone'): |
|
|
if not generator_flags.get('standalone'): |
|
|
sources.add(gyp_file) |
|
|
sources.add(gyp_file) |
|
@ -1362,7 +1402,7 @@ def _PrepareListOfSources(spec, generator_flags, gyp_file): |
|
|
inputs = a['inputs'] |
|
|
inputs = a['inputs'] |
|
|
inputs = [_NormalizedSource(i) for i in inputs] |
|
|
inputs = [_NormalizedSource(i) for i in inputs] |
|
|
# Add all inputs to sources and excluded sources. |
|
|
# Add all inputs to sources and excluded sources. |
|
|
inputs = set(inputs) |
|
|
inputs = OrderedSet(inputs) |
|
|
sources.update(inputs) |
|
|
sources.update(inputs) |
|
|
if not spec.get('msvs_external_builder'): |
|
|
if not spec.get('msvs_external_builder'): |
|
|
excluded_sources.update(inputs) |
|
|
excluded_sources.update(inputs) |
|
@ -1391,7 +1431,7 @@ def _AdjustSourcesAndConvertToFilterHierarchy( |
|
|
path of excluded IDL file) |
|
|
path of excluded IDL file) |
|
|
""" |
|
|
""" |
|
|
# Exclude excluded sources coming into the generator. |
|
|
# Exclude excluded sources coming into the generator. |
|
|
excluded_sources.update(set(spec.get('sources_excluded', []))) |
|
|
excluded_sources.update(OrderedSet(spec.get('sources_excluded', []))) |
|
|
# Add excluded sources into sources for good measure. |
|
|
# Add excluded sources into sources for good measure. |
|
|
sources.update(excluded_sources) |
|
|
sources.update(excluded_sources) |
|
|
# Convert to proper windows form. |
|
|
# Convert to proper windows form. |
|
@ -1412,6 +1452,11 @@ def _AdjustSourcesAndConvertToFilterHierarchy( |
|
|
sources = _ConvertSourcesToFilterHierarchy(sources, excluded=fully_excluded, |
|
|
sources = _ConvertSourcesToFilterHierarchy(sources, excluded=fully_excluded, |
|
|
list_excluded=list_excluded) |
|
|
list_excluded=list_excluded) |
|
|
|
|
|
|
|
|
|
|
|
# Prune filters with a single child to flatten ugly directory structures |
|
|
|
|
|
# such as ../../src/modules/module1 etc. |
|
|
|
|
|
while len(sources) == 1 and isinstance(sources[0], MSVSProject.Filter): |
|
|
|
|
|
sources = sources[0].contents |
|
|
|
|
|
|
|
|
return sources, excluded_sources, excluded_idl |
|
|
return sources, excluded_sources, excluded_idl |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1479,7 +1524,7 @@ def _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl): |
|
|
|
|
|
|
|
|
def _AddToolFilesToMSVS(p, spec): |
|
|
def _AddToolFilesToMSVS(p, spec): |
|
|
# Add in tool files (rules). |
|
|
# Add in tool files (rules). |
|
|
tool_files = set() |
|
|
tool_files = OrderedSet() |
|
|
for _, config in spec['configurations'].iteritems(): |
|
|
for _, config in spec['configurations'].iteritems(): |
|
|
for f in config.get('msvs_tool_files', []): |
|
|
for f in config.get('msvs_tool_files', []): |
|
|
tool_files.add(f) |
|
|
tool_files.add(f) |
|
@ -3202,16 +3247,16 @@ def _GenerateActionsForMSBuild(spec, actions_to_add): |
|
|
Returns: |
|
|
Returns: |
|
|
A pair of (action specification, the sources handled by this action). |
|
|
A pair of (action specification, the sources handled by this action). |
|
|
""" |
|
|
""" |
|
|
sources_handled_by_action = set() |
|
|
sources_handled_by_action = OrderedSet() |
|
|
actions_spec = [] |
|
|
actions_spec = [] |
|
|
for primary_input, actions in actions_to_add.iteritems(): |
|
|
for primary_input, actions in actions_to_add.iteritems(): |
|
|
inputs = set() |
|
|
inputs = OrderedSet() |
|
|
outputs = set() |
|
|
outputs = OrderedSet() |
|
|
descriptions = [] |
|
|
descriptions = [] |
|
|
commands = [] |
|
|
commands = [] |
|
|
for action in actions: |
|
|
for action in actions: |
|
|
inputs.update(set(action['inputs'])) |
|
|
inputs.update(OrderedSet(action['inputs'])) |
|
|
outputs.update(set(action['outputs'])) |
|
|
outputs.update(OrderedSet(action['outputs'])) |
|
|
descriptions.append(action['description']) |
|
|
descriptions.append(action['description']) |
|
|
cmd = action['command'] |
|
|
cmd = action['command'] |
|
|
# For most actions, add 'call' so that actions that invoke batch files |
|
|
# For most actions, add 'call' so that actions that invoke batch files |
|
|