diff --git a/site_scons/site_tools/VSProject.py b/site_scons/site_tools/VSProject.py
index 65cdcbb27..fe1c555e1 100644
--- a/site_scons/site_tools/VSProject.py
+++ b/site_scons/site_tools/VSProject.py
@@ -94,13 +94,23 @@ def is_subdir(child, parent):
'''Determine if child is a subdirectory of parent'''
return os.path.commonprefix([parent, child]) == parent
+def xsorted(*args, **kwargs):
+ '''Performs sorted in a deterministic manner.'''
+ if not 'key' in kwargs:
+ def _lower(item):
+ if isinstance(item, str):
+ return (item.lower(), item)
+ return (item, item)
+ kwargs['key'] = _lower
+ return sorted(*args, **kwargs)
+
def itemList(items, sep):
if type(items) == str: # Won't work in Python 3.
return items
def gen():
- for item in sorted(items):
+ for item in xsorted(items):
if type(item) == dict:
- for k, v in sorted(item.items()):
+ for k, v in xsorted(item.items()):
yield k + '=' + v
else:
yield item
@@ -126,8 +136,7 @@ class SwitchConverter(object):
self.retable = []
def getXml(self, switches, prefix = ''):
- if not isinstance(switches, list):
- switches = list(switches)
+ switches = list(set(switches)) # Filter dupes because on windows platforms, /nologo is added automatically to the environment.
xml = []
for regex, tag in self.retable:
matches = []
@@ -289,12 +298,7 @@ class LinkSwitchConverter(SwitchConverter):
booltable = {
'/DEBUG' : ['GenerateDebugInformation'],
'/DYNAMICBASE' : ['RandomizedBaseAddress'],
- '/DYNAMICBASE' : ['RandomizedBaseAddress'],
- '/DYNAMICBASE' : ['RandomizedBaseAddress'],
- '/DYNAMICBASE' : ['RandomizedBaseAddress'],
- '/DYNAMICBASE' : ['RandomizedBaseAddress'],
'/NOLOGO' : ['SuppressStartupBanner'],
- '/nologo' : ['SuppressStartupBanner'],
}
table = {
'/ERRORREPORT:NONE' : ['ErrorReporting', 'NoErrorReport'],
@@ -565,7 +569,7 @@ class _ProjectGenerator(object):
def __init__(self, project_node, filters_node, env):
try:
- self.configs = sorted(env['VSPROJECT_CONFIGS'], key=lambda x: x.name)
+ self.configs = xsorted(env['VSPROJECT_CONFIGS'], key=lambda x: x.name)
except KeyError:
raise ValueError ('Missing VSPROJECT_CONFIGS')
self.root_dir = os.getcwd()
@@ -603,7 +607,7 @@ class _ProjectGenerator(object):
targets = config.target
for target in targets:
_walk(target, items)
- self.items = sorted(items.itervalues(), key=lambda x: x.path())
+ self.items = xsorted(items.itervalues(), key=lambda x: x.path())
def makeListTag(self, items, prefix, tag, attrs, inherit=True):
'''Builds an XML tag string from a list of items. If items is
@@ -657,7 +661,7 @@ class _ProjectGenerator(object):
variant_dir = os.path.relpath(os.path.dirname(
config.target[0].get_abspath()), self.project_dir)
out_dir = winpath(variant_dir) + ntpath.sep
- int_dir = winpath(os.path.join(variant_dir, 'src')) + ntpath.sep
+ int_dir = winpath(ntpath.join(variant_dir, 'src')) + ntpath.sep
f.write(V12DSPPropertyGroup % locals())
f.write(' \r\n')
@@ -678,20 +682,20 @@ class _ProjectGenerator(object):
' %s%%(PreprocessorDefinitions)\r\n' % (
itemList(config.env['CPPDEFINES'], ';')))
props = ''
- props += self.makeListTag(self.relPaths(sorted(config.env['CPPPATH'])),
+ props += self.makeListTag(self.relPaths(xsorted(config.env['CPPPATH'])),
' ', 'AdditionalIncludeDirectories', '', True)
f.write(props)
- f.write(CLSWITCHES.getXml(sorted(config.env['CCFLAGS']), ' '))
+ f.write(CLSWITCHES.getXml(xsorted(config.env['CCFLAGS']), ' '))
f.write(' \r\n')
f.write(' \r\n')
props = ''
- props += self.makeListTag(sorted(config.env['LIBS']),
+ props += self.makeListTag(xsorted(config.env['LIBS']),
' ', 'AdditionalDependencies', '', True)
- props += self.makeListTag(self.relPaths(sorted(config.env['LIBPATH'])),
+ props += self.makeListTag(self.relPaths(xsorted(config.env['LIBPATH'])),
' ', 'AdditionalLibraryDirectories', '', True)
f.write(props)
- f.write(LINKSWITCHES.getXml(sorted(config.env['LINKFLAGS']), ' '))
+ f.write(LINKSWITCHES.getXml(xsorted(config.env['LINKFLAGS']), ' '))
f.write(' \r\n')
f.write(' \r\n')
@@ -709,21 +713,23 @@ class _ProjectGenerator(object):
props = ' True\r\n'
elif item.builder() == 'Object':
props = ''
- for config, output in sorted(item.node.iteritems()):
+ for config, output in xsorted(item.node.iteritems()):
name = config.name
env = output.get_build_env()
variant = config.variant
platform = config.platform
- props += self.makeListTag(self.extraRelPaths(sorted(env['CPPPATH']), config.env['CPPPATH']),
+ props += self.makeListTag(self.extraRelPaths(xsorted(env['CPPPATH']), config.env['CPPPATH']),
' ', 'AdditionalIncludeDirectories',
''' Condition="'$(Configuration)|$(Platform)'=='%(variant)s|%(platform)s'"''' % locals(),
True)
elif item.builder() == 'Protoc':
- for config, output in sorted(item.node.iteritems()):
+ for config, output in xsorted(item.node.iteritems()):
name = config.name
out_dir = os.path.relpath(os.path.dirname(str(output)), self.project_dir)
cpp_out = winpath(out_dir)
- base_out = os.path.join(out_dir, os.path.splitext(os.path.basename(item.path()))[0])
+ out_parts = out_dir.split(os.sep)
+ out_parts.append(os.path.splitext(os.path.basename(item.path()))[0])
+ base_out = ntpath.join(*out_parts)
props += V12CustomBuildProtoc % locals()
f.write(' <%(tag)s Include="%(path)s">\r\n' % locals())
@@ -757,7 +763,7 @@ class _ProjectGenerator(object):
while group != '':
groups.add(group)
group = ntpath.split(group)[0]
- for group in sorted(groups):
+ for group in xsorted(groups):
guid = _guid(self.guid, group)
f.write(
' \r\n'