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

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: comment fixes 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(root, default, path):
52 """Given a list of dictionary keys |path| and a tree of dicts |root|, find
53 value at path, or return |default| if any of the path doesn't exist."""
54 if not root:
55 return default
56 if not path:
57 return root
58 return _GenericRetrieve(root.get(path[0]), default, path[1:])
59
60
61 def _AddPrefix(element, prefix):
62 """Add |prefix| to |element| or each subelement if element is iterable."""
63 if element is None:
64 return element
65 # Note, not Iterable because we don't want to handle strings like that.
66 if isinstance(element, list) or isinstance(element, tuple):
Nico 2012/02/29 19:44:18 I think this would become simpler if you cribbed t
scottmg 2012/03/01 18:09:04 I tried that.. but it loses the listness-or-not of
67 return [prefix + e for e in element]
68 else:
69 return prefix + element
70
71
72 def _DoRemapping(element, map):
73 """If |element| then remap it through |map|. If |element| is iterable then
74 each item will be remapped. Any elements not found will be removed."""
75 if map is not None and element is not None:
76 if isinstance(element, list) or isinstance(element, tuple):
77 element = [map.get(elem) for elem in element]
78 element = [elem for elem in element if elem is not None]
Nico 2012/02/29 19:44:18 element = filter(none, [map.get(elem) for elem in
scottmg 2012/03/01 18:09:04 Done.
79 else:
80 element = map.get(element)
81 return element
82
83
84 def _AppendOrReturn(append, element):
Nico 2012/02/29 19:44:18 Docstring
scottmg 2012/03/01 18:09:04 Done.
85 if append is not None and element is not None:
86 if isinstance(element, list) or isinstance(element, tuple):
87 append.extend(element)
88 else:
89 append.append(element)
90 else:
91 return element
92
93
94 class MsvsSettings(object):
95 """A class that understands the gyp 'msvs_...' values (especially the
96 msvs_settings field). They largely correpond to the VS2008 IDE DOM. This
97 class helps map those settings to command line options."""
98
99 def __init__(self, spec):
100 self.spec = spec
101 self.configname = None
102
103 supported_fields = [
104 'msvs_configuration_attributes',
105 'msvs_settings',
106 'msvs_system_include_dirs',
107 'msvs_disabled_warnings',
108 ]
109 configs = spec['configurations']
110 for field in supported_fields:
111 setattr(self, field, {})
112 for configname, config in configs.iteritems():
113 getattr(self, field)[configname] = config.get(field, {})
114
115 def ConvertVSMacros(self, s):
Nico 2012/02/29 19:44:18 Private function?
scottmg 2012/03/01 18:09:04 Done.
116 """Convert from VS macro names to something equivalent."""
117 if '$' in s:
118 replacements = {
119 # TODO(scottmg): obviously
120 '$(VSInstallDir)':
121 r'C:\Program Files (x86)\Microsoft Visual Studio 9.0\\',
122 }
123 for old, new in replacements.iteritems():
124 s = s.replace(old, new)
125 return s
126
127 def GetAndMunge(self, field, path, default, prefix, append, map):
Nico 2012/02/29 19:44:18 Private function?
scottmg 2012/03/01 18:09:04 Done.
128 """Retrieve a value from |field| at |path| or return |default|. If
129 |append| is specified, and the item is found, it will be appended to that
130 object instead of returned. If |map| is specified, results will be
131 remapped through |map| before being returned or appended."""
132 result = _GenericRetrieve(field, default, path)
133 result = _DoRemapping(result, map)
134 result = _AddPrefix(result, prefix)
135 return _AppendOrReturn(append, result)
136
137 class GetWrapper(object):
Nico 2012/02/29 19:44:18 Private nested class?
scottmg 2012/03/01 18:09:04 Done.
138 def __init__(self, parent, field, base_path, append=None):
139 self.parent = parent
140 self.field = field
141 self.base_path = [base_path]
142 self.append = append
143 def __call__(self, name, map=None, prefix=''):
144 return self.parent.GetAndMunge(self.field, self.base_path + [name],
145 default=None, prefix=prefix, append=self.append, map=map)
146
147 def Setting(self, path, default=None, prefix='', append=None, map=None):
148 return self.GetAndMunge(
149 self.msvs_settings[self.configname], path, default, prefix, append, map)
150
151 def ConfigAttrib(self, path, default=None, prefix='', append=None, map=None):
152 """GetAndMunge for msvs_configuration_attributes."""
153 return self.GetAndMunge(
154 self.msvs_configuration_attributes[self.configname],
155 path, default, prefix, append, map)
156
157 def GetSystemIncludes(self, config):
158 """Returns the extra set of include paths that are used for the Windows
159 SDK and similar."""
160 return [self.ConvertVSMacros(p)
161 for p in self.msvs_system_include_dirs[config]]
162
163 def GetComputedDefines(self, config):
164 """Returns the set of defines that are injected to the defines list based
165 on other VS settings."""
166 self.configname = config
167 defines = []
168 if self.ConfigAttrib(['CharacterSet']) == '1':
169 defines.extend(('_UNICODE', 'UNICODE'))
170 if self.ConfigAttrib(['CharacterSet']) == '2':
171 defines.append('_MBCS')
172 defines.extend(self.Setting(('VCCLCompilerTool', 'PreprocessorDefinitions'),
173 default=[]))
174 self.configname = None
175 return defines
176
177 def GetCflags(self, config):
178 """Returns the flags that need to be added to .c and .cc compilations."""
179 cflags = []
180 cflags.extend(['$!/wd' + w for w in self.msvs_disabled_warnings[config]])
181 cl = self.GetWrapper(self, self.msvs_settings[config],
182 'VCCLCompilerTool', append=cflags)
183 cl('Optimization', map={'0':'d', '2':'s'}, prefix='$!/O')
184 cl('InlineFunctionExpansion', prefix='$!/Ob')
185 cl('OmitFramePointers', map={'false':'-', 'true':''}, prefix='$!/Oy')
186 cl('FavorSizeOrSpeed', map={'1':'s', '2':'t'}, prefix='$!/O')
187 cl('WholeProgramOptimization', map={'true':'$!/GL'})
188 cl('WarningLevel', prefix='$!/W')
189 cl('WarnAsError', map={'true':'$!/WX'})
190 cl('DebugInformationFormat', map={'1':'7', '3':'i', '4':'I'}, prefix='$!/Z')
191 cl('RuntimeTypeInfo', map={'true':'$!/GR', 'false':'$!/GR-'})
192 cl('EnableFunctionLevelLinking', map={'true':'$!/Gy', 'false':'$!/Gy-'})
193 cl('MinimalRebuild', map={'true':'$!/Gm'})
194 cl('BufferSecurityCheck', map={'true':'$!/GS', 'false':'$!/GS-'})
195 cl('BasicRuntimeChecks', map={'1':'s', '2':'u', '3':'1'}, prefix='$!/RTC')
196 cl('RuntimeLibrary',
197 map={'0':'T', '1':'Td', '2':'D', '3':'Dd'}, prefix='$!/M')
198 cl('ExceptionHandling', map={'1':'sc','2':'a'}, prefix='$!/EH')
199 cl('AdditionalOptions', prefix='$!')
200 return cflags
201
202 def GetCflagsC(self, config):
203 """Returns the flags that need to be added to .c compilations."""
204 return []
205
206 def GetCflagsCC(self, config):
207 """Returns the flags that need to be added to .cc compilations."""
208 return ['$!/TP']
209
210 def GetLdflags(self, config, product_dir, gyp_to_build_path):
211 """Returns the flags that need to be added to link and lib commands."""
212 ldflags = []
213 ld = self.GetWrapper(self, self.msvs_settings[config],
214 'VCLinkerTool', append=ldflags)
215 ld('GenerateDebugInformation', map={'true':'$!/DEBUG'})
216 ld('TargetMachine', map={'1':'X86', '17':'X64'}, prefix='$!/MACHINE:')
217 ld('AdditionalLibraryDirectories', prefix='$!/LIBPATH:')
218 ld('DelayLoadDLLs', prefix='$!/DELAYLOAD:')
219 ld('AdditionalOptions', prefix='$!')
220 ld('SubSystem', map={'1':'CONSOLE', '2':'WINDOWS'}, prefix='$!/SUBSYSTEM:')
221 ld('LinkIncremental', map={'1':':NO', '2':''}, prefix='$!/INCREMENTAL')
222 ld('FixedBaseAddress', map={'1':':NO', '2':''}, prefix='$!/FIXED')
223 ld('RandomizedBaseAddress',
224 map={'1':':NO', '2':''}, prefix='$!/DYNAMICBASE')
225 ld('DataExecutionPrevention',
226 map={'1':':NO', '2':''}, prefix='$!/NXCOMPAT')
227 ld('OptimizeReferences', map={'1':'NOREF', '2':'REF'}, prefix='$!/OPT:')
228 ld('EnableCOMDATFolding', map={'1':'NOICF', '2':'ICF'}, prefix='$!/OPT:')
229 ld('LinkTimeCodeGeneration', map={'1':'$!/LTCG'})
230 # TODO(scottmg): This should sort of be somewhere else (not really a flag).
231 ld('AdditionalDependencies', prefix='$!')
232 # TODO(scottmg): These too.
233 ldflags.extend(('kernel32.lib', 'user32.lib', 'gdi32.lib', 'winspool.lib',
234 'comdlg32.lib', 'advapi32.lib', 'shell32.lib', 'ole32.lib',
235 'oleaut32.lib', 'uuid.lib', 'odbc32.lib', 'odbccp32.lib',
236 'DelayImp.lib'))
237 return ldflags
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698