Chromium Code Reviews| Index: pylib/gyp/msvs_emulation.py |
| diff --git a/pylib/gyp/msvs_emulation.py b/pylib/gyp/msvs_emulation.py |
| index 7d10b94132af5c77cf2f4c370fbe8ef8ad81a39e..5f4f03a2a7cca75bf2ddfbf79d9a0a6cc87d223a 100644 |
| --- a/pylib/gyp/msvs_emulation.py |
| +++ b/pylib/gyp/msvs_emulation.py |
| @@ -8,6 +8,7 @@ build systems, primarily ninja. |
| """ |
| import re |
| +import sys |
| windows_quoter_regex = re.compile(r'(\\*)"') |
| @@ -41,6 +42,200 @@ def QuoteCmdExeArgument(arg): |
| # applies and whitespace isn't a word break. |
| return '"' + tmp + '"' |
| + |
| def EncodeCmdExeList(args): |
| """Process a list of arguments using QuoteCmdExeArgument.""" |
| return ' '.join(QuoteCmdExeArgument(arg) for arg in args) |
| + |
| + |
| +def GenericRetrieve(field, default, path): |
|
Nico
2012/02/27 16:23:30
Functions that are private to a class / module sho
scottmg
2012/02/28 00:01:13
Done.
|
| + """Walk down a tree of dicts starting from |field|, returning |default| if |
|
Nico
2012/02/27 16:23:30
s/field/root/?
I found the comment confusing unti
scottmg
2012/02/28 00:01:13
Done.
|
| + any part of the path is not found along the way.""" |
| + cur = field |
|
Nico
2012/02/27 16:23:30
I'd just assign to the parameter variable directly
scottmg
2012/02/28 00:01:13
Done.
|
| + for p in path: |
| + if not cur: |
| + return default |
| + cur = cur.get(p) |
| + if cur == None: |
|
Nico
2012/02/27 16:23:30
http://jaredgrubb.blogspot.com/2009/04/python-is-n
scottmg
2012/02/28 00:01:13
Done.
|
| + return default |
| + return cur |
|
Nico
2012/02/27 16:23:30
…could this maybe be more compact recursively?
i
scottmg
2012/02/28 00:01:13
Hmm, shrug? Sure. Done.
|
| + |
| + |
| +def AddPrefix(element, prefix): |
| + """Add prefix to element or each subelement if element is iterable.""" |
|
Nico
2012/02/27 16:23:30
s/prefix/|prefix|/
s/element/|element|/
scottmg
2012/02/28 00:01:13
Done.
|
| + if element == None: |
|
Nico
2012/02/27 16:23:30
is None
scottmg
2012/02/28 00:01:13
Done.
|
| + return element |
| + # Note, not Iterable because we don't want to handle strings like that. |
| + if isinstance(element, list) or isinstance(element, tuple): |
| + return [prefix + e for e in element] |
| + else: |
| + return prefix + element |
| + |
| + |
| +def DoRemapping(element, map): |
| + """If |element| then remap it through |map|. If |element| is iterable then |
| + each item will be remapped. Any elements not found will be removed.""" |
| + if map != None and element != None: |
|
Nico
2012/02/27 16:23:30
is not None
scottmg
2012/02/28 00:01:13
Done.
|
| + if isinstance(element, list) or isinstance(element, tuple): |
| + element = [map.get(elem) for elem in element] |
| + element = [elem for elem in element if elem != None] |
| + else: |
| + element = map.get(element) |
| + return element |
| + |
| + |
| +def AppendOrReturn(append, element): |
| + if append != None and element != None: |
| + if isinstance(element, list) or isinstance(element, tuple): |
| + append.extend(element) |
| + else: |
| + append.append(element) |
| + else: |
| + return element |
| + |
| + |
| +class MsvsSettings(object): |
| + """A class that understands the gyp 'msvs_...' values (especially the |
| + msvs_settings field). They largely correpond to the VS2008 IDE DOM. This |
| + class helps map those settings to command line options.""" |
| + |
| + def __init__(self, spec): |
| + self.spec = spec |
| + self.configname = None |
| + |
| + supported_fields = [ |
| + 'msvs_configuration_attributes', |
| + 'msvs_settings', |
| + 'msvs_system_include_dirs', |
| + 'msvs_disabled_warnings', |
| + ] |
| + configs = spec['configurations'] |
| + for field in supported_fields: |
| + setattr(self, field, {}) |
| + for configname, config in configs.iteritems(): |
| + getattr(self, field)[configname] = config.get(field, {}) |
| + |
| + def ConvertVSMacros(self, s): |
| + """Convert from VS macro names to something equivalent.""" |
| + if '$' in s: |
| + replacements = { |
| + # TODO(scottmg): obviously |
| + '$(VSInstallDir)': |
| + r'C:\Program Files (x86)\Microsoft Visual Studio 9.0\\', |
|
Nico
2012/02/27 16:23:30
Does this intentionally have two trailing \?
scottmg
2012/02/28 00:01:13
Vim syntax-highlighting made me do it (I think \'
|
| + } |
| + for old, new in replacements.iteritems(): |
| + s = s.replace(old, new) |
| + return s |
| + |
| + def GetAndMunge(self, field, path, default, prefix, append, map): |
| + """Retrieve a value from |field| at |path| or return |default|. |
| + Uses self.configname. If |append| is specified, and the item is found, |
|
Nico
2012/02/27 16:23:30
Looks like this doesn't use self.configname
scottmg
2012/02/28 00:01:13
Done.
|
| + it will be appended to that object instead of returned. If |map| is |
| + specified, results will be remapped through |map| before being returned |
| + or appended.""" |
| + result = GenericRetrieve(field, default, path) |
| + result = DoRemapping(result, map) |
| + result = AddPrefix(result, prefix) |
| + return AppendOrReturn(append, result) |
| + |
| + class GetWrapper(object): |
| + def __init__(self, parent, field, base_path, append=None): |
|
Nico
2012/02/27 16:23:30
It looks like base_path is always 1 element long.
scottmg
2012/02/28 00:01:13
The __call__ retrieve uses root + passed-in as a 2
|
| + self.parent = parent |
| + self.field = field |
| + self.base_path = list(base_path) |
| + self.append = append |
| + def __call__(self, name, map=None, prefix=''): |
| + return self.parent.GetAndMunge(self.field, self.base_path + [name], |
| + default=None, prefix=prefix, append=self.append, map=map) |
| + |
| + def Setting(self, path, default=None, prefix='', append=None, map=None): |
| + return self.GetAndMunge( |
| + self.msvs_settings[self.configname], path, default, prefix, append, map) |
| + |
| + def ConfigAttrib(self, path, default=None, prefix='', append=None, map=None): |
| + """GetAndMunge for msvs_configuration_attributes.""" |
| + return self.GetAndMunge( |
| + self.msvs_configuration_attributes[self.configname], |
| + path, default, prefix, append, map) |
| + |
| + def GetSystemIncludes(self, config): |
| + """Returns the extra set of include paths that are used for the Windows |
| + SDK and similar.""" |
| + return [self.ConvertVSMacros(p) |
| + for p in self.msvs_system_include_dirs[config]] |
| + |
| + def GetComputedDefines(self, config): |
| + """Returns the set of defines that are injected to the defines list based |
| + on other VS settings.""" |
| + self.configname = config |
| + defines = [] |
| + if self.ConfigAttrib(['CharacterSet']) == '1': |
| + defines.extend(('_UNICODE', 'UNICODE')) |
| + if self.ConfigAttrib(['CharacterSet']) == '2': |
| + defines.append('_MBCS') |
| + defines.extend(self.Setting(('VCCLCompilerTool', 'PreprocessorDefinitions'), |
| + default=[])) |
| + self.configname = None |
| + return defines |
| + |
| + def GetCflags(self, config): |
| + """Returns the flags that need to be added to .c and .cc compilations.""" |
| + cflags = [] |
| + cflags.extend(['$!/wd' + w for w in self.msvs_disabled_warnings[config]]) |
| + cl = self.GetWrapper(self, self.msvs_settings[config], |
| + ('VCCLCompilerTool',), cflags) |
|
Nico
2012/02/27 16:23:30
Naming the last parameter ("append=cflags") might
scottmg
2012/02/28 00:01:13
Done.
|
| + cl('Optimization', map={'0':'d', '2':'s'}, prefix='$!/O') |
| + cl('InlineFunctionExpansion', prefix='$!/Ob') |
| + cl('OmitFramePointers', map={'false':'-', 'true':''}, prefix='$!/Oy') |
| + cl('FavorSizeOrSpeed', map={'1':'s', '2':'t'}, prefix='$!/O') |
| + cl('WholeProgramOptimization', map={'true':'$!/GL'}) |
| + cl('WarningLevel', prefix='$!/W') |
| + cl('WarnAsError', map={'true':'$!/WX'}) |
| + cl('DebugInformationFormat', map={'1':'7', '3':'i', '4':'I'}, prefix='$!/Z') |
| + cl('RuntimeTypeInfo', map={'true':'$!/GR', 'false':'$!/GR-'}) |
| + cl('EnableFunctionLevelLinking', map={'true':'$!/Gy', 'false':'$!/Gy-'}) |
| + cl('MinimalRebuild', map={'true':'$!/Gm'}) |
| + cl('BufferSecurityCheck', map={'true':'$!/GS', 'false':'$!/GS-'}) |
| + cl('BasicRuntimeChecks', map={'1':'s', '2':'u', '3':'1'}, prefix='$!/RTC') |
| + cl('RuntimeLibrary', |
| + map={'0':'T', '1':'Td', '2':'D', '3':'Dd'}, prefix='$!/M') |
| + cl('ExceptionHandling', map={'1':'sc','2':'a'}, prefix='$!/EH') |
| + cl('AdditionalOptions', prefix='$!') |
| + return cflags |
| + |
| + def GetCflagsC(self, config): |
| + """Returns the flags that need to be added to .c compilations.""" |
| + return [] |
| + |
| + def GetCflagsCC(self, config): |
| + """Returns the flags that need to be added to .cc compilations.""" |
| + return ['$!/TP'] |
| + |
| + def GetLdflags(self, config, product_dir, gyp_to_build_path): |
| + """Returns the flags that need to be added to link and lib commands.""" |
| + ldflags = [] |
| + ld = self.GetWrapper(self, self.msvs_settings[config], |
| + ('VCLinkerTool',), ldflags) |
| + ld('GenerateDebugInformation', map={'true':'$!/DEBUG'}) |
| + ld('TargetMachine', map={'1':'X86', '17':'X64'}, prefix='$!/MACHINE:') |
| + ld('AdditionalLibraryDirectories', prefix='$!/LIBPATH:') |
| + ld('DelayLoadDLLs', prefix='$!/DELAYLOAD:') |
| + ld('AdditionalOptions', prefix='$!') |
| + ld('SubSystem', map={'1':'CONSOLE', '2':'WINDOWS'}, prefix='$!/SUBSYSTEM:') |
| + ld('LinkIncremental', map={'1':':NO', '2':''}, prefix='$!/INCREMENTAL') |
| + ld('FixedBaseAddress', map={'1':':NO', '2':''}, prefix='$!/FIXED') |
| + ld('RandomizedBaseAddress', |
| + map={'1':':NO', '2':''}, prefix='$!/DYNAMICBASE') |
| + ld('DataExecutionPrevention', |
| + map={'1':':NO', '2':''}, prefix='$!/NXCOMPAT') |
| + ld('OptimizeReferences', map={'1':'NOREF', '2':'REF'}, prefix='$!/OPT:') |
| + ld('EnableCOMDATFolding', map={'1':'NOICF', '2':'ICF'}, prefix='$!/OPT:') |
| + ld('LinkTimeCodeGeneration', map={'1':'$!/LTCG'}) |
| + # TODO(scottmg): This should sort of be somewhere else (not really a flag). |
| + ld('AdditionalDependencies', prefix='$!') |
| + # TODO(scottmg): These too. |
| + ldflags.extend(('kernel32.lib', 'user32.lib', 'gdi32.lib', 'winspool.lib', |
| + 'comdlg32.lib', 'advapi32.lib', 'shell32.lib', 'ole32.lib', |
| + 'oleaut32.lib', 'uuid.lib', 'odbc32.lib', 'odbccp32.lib', |
| + 'DelayImp.lib')) |
| + return ldflags |