Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(60)

Side by Side Diff: pylib/gyp/msvs_emulation.py

Issue 9443044: Beginnings of some msvs_... emulation (windows ninja) (Closed) Base URL: https://gyp.googlecode.com/svn/trunk
Patch Set: no pdb option for LIB Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 # Copyright (c) 2012 Google Inc. All rights reserved. 1 # Copyright (c) 2012 Google Inc. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """ 5 """
6 This module helps emulate Visual Studio 2008 behavior on top of other 6 This module helps emulate Visual Studio 2008 behavior on top of other
7 build systems, primarily ninja. 7 build systems, primarily ninja.
8 """ 8 """
9 9
10 import re 10 import re
11 import sys
11 12
12 windows_quoter_regex = re.compile(r'(\\*)"') 13 windows_quoter_regex = re.compile(r'(\\*)"')
13 14
14 def QuoteCmdExeArgument(arg): 15 def QuoteCmdExeArgument(arg):
15 """Quote a command line argument so that it appears as one argument when 16 """Quote a command line argument so that it appears as one argument when
16 processed via cmd.exe and parsed by CommandLineToArgvW (as is typical for 17 processed via cmd.exe and parsed by CommandLineToArgvW (as is typical for
17 Windows programs).""" 18 Windows programs)."""
18 # See http://goo.gl/cuFbX and http://goo.gl/dhPnp including the comment 19 # See http://goo.gl/cuFbX and http://goo.gl/dhPnp including the comment
19 # threads. This is actually the quoting rules for CommandLineToArgvW, not 20 # threads. This is actually the quoting rules for CommandLineToArgvW, not
20 # for the shell, because the shell doesn't do anything in Windows. This 21 # for the shell, because the shell doesn't do anything in Windows. This
(...skipping 13 matching lines...) Expand all
34 # positional arguments. Also make sure to escape the % so that they're 35 # positional arguments. Also make sure to escape the % so that they're
35 # passed literally through escaping so they can be singled to just the 36 # passed literally through escaping so they can be singled to just the
36 # original %. Otherwise, trying to pass the literal representation that 37 # original %. Otherwise, trying to pass the literal representation that
37 # looks like an environment variable to the shell (e.g. %PATH%) would fail. 38 # looks like an environment variable to the shell (e.g. %PATH%) would fail.
38 tmp = tmp.replace('%', '^%^%') 39 tmp = tmp.replace('%', '^%^%')
39 40
40 # Finally, wrap the whole thing in quotes so that the above quote rule 41 # Finally, wrap the whole thing in quotes so that the above quote rule
41 # applies and whitespace isn't a word break. 42 # applies and whitespace isn't a word break.
42 return '"' + tmp + '"' 43 return '"' + tmp + '"'
43 44
45
44 def EncodeCmdExeList(args): 46 def EncodeCmdExeList(args):
45 """Process a list of arguments using QuoteCmdExeArgument.""" 47 """Process a list of arguments using QuoteCmdExeArgument."""
46 return ' '.join(QuoteCmdExeArgument(arg) for arg in args) 48 return ' '.join(QuoteCmdExeArgument(arg) for arg in args)
49
50
51 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.
52 """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.
53 any part of the path is not found along the way."""
54 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.
55 for p in path:
56 if not cur:
57 return default
58 cur = cur.get(p)
59 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.
60 return default
61 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.
62
63
64 def AddPrefix(element, prefix):
65 """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.
66 if element == None:
Nico 2012/02/27 16:23:30 is None
scottmg 2012/02/28 00:01:13 Done.
67 return element
68 # Note, not Iterable because we don't want to handle strings like that.
69 if isinstance(element, list) or isinstance(element, tuple):
70 return [prefix + e for e in element]
71 else:
72 return prefix + element
73
74
75 def DoRemapping(element, map):
76 """If |element| then remap it through |map|. If |element| is iterable then
77 each item will be remapped. Any elements not found will be removed."""
78 if map != None and element != None:
Nico 2012/02/27 16:23:30 is not None
scottmg 2012/02/28 00:01:13 Done.
79 if isinstance(element, list) or isinstance(element, tuple):
80 element = [map.get(elem) for elem in element]
81 element = [elem for elem in element if elem != None]
82 else:
83 element = map.get(element)
84 return element
85
86
87 def AppendOrReturn(append, element):
88 if append != None and element != None:
89 if isinstance(element, list) or isinstance(element, tuple):
90 append.extend(element)
91 else:
92 append.append(element)
93 else:
94 return element
95
96
97 class MsvsSettings(object):
98 """A class that understands the gyp 'msvs_...' values (especially the
99 msvs_settings field). They largely correpond to the VS2008 IDE DOM. This
100 class helps map those settings to command line options."""
101
102 def __init__(self, spec):
103 self.spec = spec
104 self.configname = None
105
106 supported_fields = [
107 'msvs_configuration_attributes',
108 'msvs_settings',
109 'msvs_system_include_dirs',
110 'msvs_disabled_warnings',
111 ]
112 configs = spec['configurations']
113 for field in supported_fields:
114 setattr(self, field, {})
115 for configname, config in configs.iteritems():
116 getattr(self, field)[configname] = config.get(field, {})
117
118 def ConvertVSMacros(self, s):
119 """Convert from VS macro names to something equivalent."""
120 if '$' in s:
121 replacements = {
122 # TODO(scottmg): obviously
123 '$(VSInstallDir)':
124 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 \'
125 }
126 for old, new in replacements.iteritems():
127 s = s.replace(old, new)
128 return s
129
130 def GetAndMunge(self, field, path, default, prefix, append, map):
131 """Retrieve a value from |field| at |path| or return |default|.
132 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.
133 it will be appended to that object instead of returned. If |map| is
134 specified, results will be remapped through |map| before being returned
135 or appended."""
136 result = GenericRetrieve(field, default, path)
137 result = DoRemapping(result, map)
138 result = AddPrefix(result, prefix)
139 return AppendOrReturn(append, result)
140
141 class GetWrapper(object):
142 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
143 self.parent = parent
144 self.field = field
145 self.base_path = list(base_path)
146 self.append = append
147 def __call__(self, name, map=None, prefix=''):
148 return self.parent.GetAndMunge(self.field, self.base_path + [name],
149 default=None, prefix=prefix, append=self.append, map=map)
150
151 def Setting(self, path, default=None, prefix='', append=None, map=None):
152 return self.GetAndMunge(
153 self.msvs_settings[self.configname], path, default, prefix, append, map)
154
155 def ConfigAttrib(self, path, default=None, prefix='', append=None, map=None):
156 """GetAndMunge for msvs_configuration_attributes."""
157 return self.GetAndMunge(
158 self.msvs_configuration_attributes[self.configname],
159 path, default, prefix, append, map)
160
161 def GetSystemIncludes(self, config):
162 """Returns the extra set of include paths that are used for the Windows
163 SDK and similar."""
164 return [self.ConvertVSMacros(p)
165 for p in self.msvs_system_include_dirs[config]]
166
167 def GetComputedDefines(self, config):
168 """Returns the set of defines that are injected to the defines list based
169 on other VS settings."""
170 self.configname = config
171 defines = []
172 if self.ConfigAttrib(['CharacterSet']) == '1':
173 defines.extend(('_UNICODE', 'UNICODE'))
174 if self.ConfigAttrib(['CharacterSet']) == '2':
175 defines.append('_MBCS')
176 defines.extend(self.Setting(('VCCLCompilerTool', 'PreprocessorDefinitions'),
177 default=[]))
178 self.configname = None
179 return defines
180
181 def GetCflags(self, config):
182 """Returns the flags that need to be added to .c and .cc compilations."""
183 cflags = []
184 cflags.extend(['$!/wd' + w for w in self.msvs_disabled_warnings[config]])
185 cl = self.GetWrapper(self, self.msvs_settings[config],
186 ('VCCLCompilerTool',), cflags)
Nico 2012/02/27 16:23:30 Naming the last parameter ("append=cflags") might
scottmg 2012/02/28 00:01:13 Done.
187 cl('Optimization', map={'0':'d', '2':'s'}, prefix='$!/O')
188 cl('InlineFunctionExpansion', prefix='$!/Ob')
189 cl('OmitFramePointers', map={'false':'-', 'true':''}, prefix='$!/Oy')
190 cl('FavorSizeOrSpeed', map={'1':'s', '2':'t'}, prefix='$!/O')
191 cl('WholeProgramOptimization', map={'true':'$!/GL'})
192 cl('WarningLevel', prefix='$!/W')
193 cl('WarnAsError', map={'true':'$!/WX'})
194 cl('DebugInformationFormat', map={'1':'7', '3':'i', '4':'I'}, prefix='$!/Z')
195 cl('RuntimeTypeInfo', map={'true':'$!/GR', 'false':'$!/GR-'})
196 cl('EnableFunctionLevelLinking', map={'true':'$!/Gy', 'false':'$!/Gy-'})
197 cl('MinimalRebuild', map={'true':'$!/Gm'})
198 cl('BufferSecurityCheck', map={'true':'$!/GS', 'false':'$!/GS-'})
199 cl('BasicRuntimeChecks', map={'1':'s', '2':'u', '3':'1'}, prefix='$!/RTC')
200 cl('RuntimeLibrary',
201 map={'0':'T', '1':'Td', '2':'D', '3':'Dd'}, prefix='$!/M')
202 cl('ExceptionHandling', map={'1':'sc','2':'a'}, prefix='$!/EH')
203 cl('AdditionalOptions', prefix='$!')
204 return cflags
205
206 def GetCflagsC(self, config):
207 """Returns the flags that need to be added to .c compilations."""
208 return []
209
210 def GetCflagsCC(self, config):
211 """Returns the flags that need to be added to .cc compilations."""
212 return ['$!/TP']
213
214 def GetLdflags(self, config, product_dir, gyp_to_build_path):
215 """Returns the flags that need to be added to link and lib commands."""
216 ldflags = []
217 ld = self.GetWrapper(self, self.msvs_settings[config],
218 ('VCLinkerTool',), ldflags)
219 ld('GenerateDebugInformation', map={'true':'$!/DEBUG'})
220 ld('TargetMachine', map={'1':'X86', '17':'X64'}, prefix='$!/MACHINE:')
221 ld('AdditionalLibraryDirectories', prefix='$!/LIBPATH:')
222 ld('DelayLoadDLLs', prefix='$!/DELAYLOAD:')
223 ld('AdditionalOptions', prefix='$!')
224 ld('SubSystem', map={'1':'CONSOLE', '2':'WINDOWS'}, prefix='$!/SUBSYSTEM:')
225 ld('LinkIncremental', map={'1':':NO', '2':''}, prefix='$!/INCREMENTAL')
226 ld('FixedBaseAddress', map={'1':':NO', '2':''}, prefix='$!/FIXED')
227 ld('RandomizedBaseAddress',
228 map={'1':':NO', '2':''}, prefix='$!/DYNAMICBASE')
229 ld('DataExecutionPrevention',
230 map={'1':':NO', '2':''}, prefix='$!/NXCOMPAT')
231 ld('OptimizeReferences', map={'1':'NOREF', '2':'REF'}, prefix='$!/OPT:')
232 ld('EnableCOMDATFolding', map={'1':'NOICF', '2':'ICF'}, prefix='$!/OPT:')
233 ld('LinkTimeCodeGeneration', map={'1':'$!/LTCG'})
234 # TODO(scottmg): This should sort of be somewhere else (not really a flag).
235 ld('AdditionalDependencies', prefix='$!')
236 # TODO(scottmg): These too.
237 ldflags.extend(('kernel32.lib', 'user32.lib', 'gdi32.lib', 'winspool.lib',
238 'comdlg32.lib', 'advapi32.lib', 'shell32.lib', 'ole32.lib',
239 'oleaut32.lib', 'uuid.lib', 'odbc32.lib', 'odbccp32.lib',
240 'DelayImp.lib'))
241 return ldflags
OLDNEW
« pylib/gyp/generator/ninja.py ('K') | « pylib/gyp/input.py ('k') | pylib/gyp/win_tool.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698