OLD | NEW |
---|---|
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 os | 10 import os |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
136 | 136 |
137 # Try to find an installation location for the Windows DDK by checking | 137 # Try to find an installation location for the Windows DDK by checking |
138 # the WDK_DIR environment variable, may be None. | 138 # the WDK_DIR environment variable, may be None. |
139 self.wdk_dir = os.environ.get('WDK_DIR') | 139 self.wdk_dir = os.environ.get('WDK_DIR') |
140 | 140 |
141 supported_fields = [ | 141 supported_fields = [ |
142 ('msvs_configuration_attributes', dict), | 142 ('msvs_configuration_attributes', dict), |
143 ('msvs_settings', dict), | 143 ('msvs_settings', dict), |
144 ('msvs_system_include_dirs', list), | 144 ('msvs_system_include_dirs', list), |
145 ('msvs_disabled_warnings', list), | 145 ('msvs_disabled_warnings', list), |
146 ('msvs_precompiled_header', str), | |
147 ('msvs_precompiled_source', str), | |
146 ] | 148 ] |
147 configs = spec['configurations'] | 149 configs = spec['configurations'] |
148 for field, default in supported_fields: | 150 for field, default in supported_fields: |
149 setattr(self, field, {}) | 151 setattr(self, field, {}) |
150 for configname, config in configs.iteritems(): | 152 for configname, config in configs.iteritems(): |
151 getattr(self, field)[configname] = config.get(field, default()) | 153 getattr(self, field)[configname] = config.get(field, default()) |
152 | 154 |
153 self.msvs_cygwin_dirs = spec.get('msvs_cygwin_dirs', ['.']) | 155 self.msvs_cygwin_dirs = spec.get('msvs_cygwin_dirs', ['.']) |
154 | 156 |
155 def GetVSMacroEnv(self, base_to_build=None): | 157 def GetVSMacroEnv(self, base_to_build=None): |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
266 cl('BufferSecurityCheck', map={'true': '/GS', 'false': '/GS-'}) | 268 cl('BufferSecurityCheck', map={'true': '/GS', 'false': '/GS-'}) |
267 cl('BasicRuntimeChecks', map={'1': 's', '2': 'u', '3': '1'}, prefix='/RTC') | 269 cl('BasicRuntimeChecks', map={'1': 's', '2': 'u', '3': '1'}, prefix='/RTC') |
268 cl('RuntimeLibrary', | 270 cl('RuntimeLibrary', |
269 map={'0': 'T', '1': 'Td', '2': 'D', '3': 'Dd'}, prefix='/M') | 271 map={'0': 'T', '1': 'Td', '2': 'D', '3': 'Dd'}, prefix='/M') |
270 cl('ExceptionHandling', map={'1': 'sc','2': 'a'}, prefix='/EH') | 272 cl('ExceptionHandling', map={'1': 'sc','2': 'a'}, prefix='/EH') |
271 cl('AdditionalOptions', prefix='') | 273 cl('AdditionalOptions', prefix='') |
272 # ninja handles parallelism by itself, don't have the compiler do it too. | 274 # ninja handles parallelism by itself, don't have the compiler do it too. |
273 cflags = filter(lambda x: not x.startswith('/MP'), cflags) | 275 cflags = filter(lambda x: not x.startswith('/MP'), cflags) |
274 return cflags | 276 return cflags |
275 | 277 |
278 def GetPrecompiledHeader(self, config, gyp_to_build_path): | |
279 """Returns an object that handles the generation of precompiled header | |
280 build steps.""" | |
281 return _PchHelper(self, config, gyp_to_build_path) | |
282 | |
283 def _GetPchFlags(self, config, extension): | |
284 """Get the flags to be added to the cflags for precompiled header support. | |
285 """ | |
286 # The PCH is only built once by a particular source file. Usage of PCH must | |
287 # only be for the same language (i.e. C vs. C++), so only include the pch | |
288 # flags when the language matches. | |
289 if self.msvs_precompiled_header[config]: | |
290 source_ext = os.path.splitext(self.msvs_precompiled_source[config])[1] | |
291 if _LanguageMatchesForPch(source_ext, extension): | |
292 pch = os.path.split(self.msvs_precompiled_header[config])[1] | |
293 return ['/Yu' + pch, '/FI' + pch, '/Fp${pchprefix}.' + pch + '.pch'] | |
294 return [] | |
295 | |
276 def GetCflagsC(self, config): | 296 def GetCflagsC(self, config): |
277 """Returns the flags that need to be added to .c compilations.""" | 297 """Returns the flags that need to be added to .c compilations.""" |
278 return [] | 298 return self._GetPchFlags(config, '.c') |
279 | 299 |
280 def GetCflagsCC(self, config): | 300 def GetCflagsCC(self, config): |
281 """Returns the flags that need to be added to .cc compilations.""" | 301 """Returns the flags that need to be added to .cc compilations.""" |
282 return ['/TP'] | 302 return ['/TP'] + self._GetPchFlags(config, '.cc') |
283 | 303 |
284 def _GetAdditionalLibraryDirectories(self, root, config, gyp_to_build_path): | 304 def _GetAdditionalLibraryDirectories(self, root, config, gyp_to_build_path): |
285 """Get and normalize the list of paths in AdditionalLibraryDirectories | 305 """Get and normalize the list of paths in AdditionalLibraryDirectories |
286 setting.""" | 306 setting.""" |
287 libpaths = self._Setting((root, 'AdditionalLibraryDirectories'), | 307 libpaths = self._Setting((root, 'AdditionalLibraryDirectories'), |
288 config, default=[]) | 308 config, default=[]) |
289 libpaths = [os.path.normpath(gyp_to_build_path(self.ConvertVSMacros(p))) | 309 libpaths = [os.path.normpath(gyp_to_build_path(self.ConvertVSMacros(p))) |
290 for p in libpaths] | 310 for p in libpaths] |
291 return ['/LIBPATH:"' + p + '"' for p in libpaths] | 311 return ['/LIBPATH:"' + p + '"' for p in libpaths] |
292 | 312 |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
429 output = [header, dlldata, iid, proxy] | 449 output = [header, dlldata, iid, proxy] |
430 variables = [('tlb', tlb), | 450 variables = [('tlb', tlb), |
431 ('h', header), | 451 ('h', header), |
432 ('dlldata', dlldata), | 452 ('dlldata', dlldata), |
433 ('iid', iid), | 453 ('iid', iid), |
434 ('proxy', proxy)] | 454 ('proxy', proxy)] |
435 # TODO(scottmg): Are there configuration settings to set these flags? | 455 # TODO(scottmg): Are there configuration settings to set these flags? |
436 flags = ['/char', 'signed', '/env', 'win32', '/Oicf'] | 456 flags = ['/char', 'signed', '/env', 'win32', '/Oicf'] |
437 return outdir, output, variables, flags | 457 return outdir, output, variables, flags |
438 | 458 |
459 | |
460 def _LanguageMatchesForPch(source_ext, pch_source_ext): | |
461 c_exts = ('.c',) | |
462 cc_exts = ('.cc', '.cxx', '.cpp') | |
463 return ((source_ext in c_exts and pch_source_ext in c_exts) or | |
464 (source_ext in cc_exts and pch_source_ext in cc_exts)) | |
465 | |
466 class PrecompiledHeader(object): | |
467 """Helper to generate dependencies and build rules to handle generation of | |
468 precompiled headers. Interface matches the GCH handler in xcode_emulation.py. | |
469 """ | |
470 def __init__(self, settings, config, gyp_to_build_path): | |
471 self.settings = settings | |
472 self.config = config | |
473 self.gyp_to_build_path = gyp_to_build_path | |
474 | |
475 def _PchHeader(self): | |
476 """Get the header that will appear in an #include line for all source | |
477 files.""" | |
478 return os.path.split(self.settings.msvs_precompiled_header[self.config])[1] | |
479 | |
480 def _PchSource(self): | |
481 """Get the source file that is built once to compile the pch data.""" | |
482 return self.gyp_to_build_path( | |
483 self.settings.msvs_precompiled_source[self.config]) | |
484 | |
485 def _PchOutput(self): | |
486 """Get the name of the output of the compiled pch data.""" | |
487 return '${pchprefix}.' + self._PchHeader() + '.pch' | |
488 | |
489 def _PchObj(self): | |
490 """Get the name of the output of the compiled pch data.""" | |
491 return '${pchprefix}.' + self._PchHeader() + '.obj' | |
492 | |
493 def GetObjDependencies(self, sources, objs): | |
494 """Given a list of sources files and the corresponding object files, | |
495 returns a list of the pch files that should be depended upon. The | |
496 additional wrapping in the return value is for interface compatability | |
497 with make.py on Mac, and xcode_emulation.py.""" | |
498 if not self._PchHeader(): | |
499 return [] | |
500 source = self._PchSource() | |
501 assert source | |
502 pch_ext = os.path.splitext(self._PchSource())[1] | |
503 for source in sources: | |
504 if _LanguageMatchesForPch(os.path.splitext(source)[1], pch_ext): | |
505 return [(None, None, self._PchOutput())] | |
506 return [] | |
507 | |
508 def GetPchBuildCommands(self): | |
509 """Returns [(path_to_pch, language_flag, language, header, extra_vars)]. | |
510 |path_to_gch| and |header| are relative to the build directory.""" | |
511 header = self._PchHeader() | |
512 source = self._PchSource() | |
513 if not source or not header: | |
514 return [] | |
515 ext = os.path.splitext(source)[1] | |
516 lang = 'c' if ext == '.c' else 'cc' | |
517 extra_vars = [('outflag', '/Fp'), | |
518 ('pchobj', '/Fo' + self._PchObj())] | |
Nico
2012/05/25 22:35:39
nit: it'd be more consistent with the xcode code i
scottmg
2012/05/26 02:27:12
OK, guess it's more localized that way anyway.
| |
519 return [(self._PchOutput(), '/Yc' + header, lang, source, extra_vars)] | |
520 | |
521 | |
439 vs_version = None | 522 vs_version = None |
440 def GetVSVersion(generator_flags): | 523 def GetVSVersion(generator_flags): |
441 global vs_version | 524 global vs_version |
442 if not vs_version: | 525 if not vs_version: |
443 vs_version = gyp.MSVSVersion.SelectVisualStudioVersion( | 526 vs_version = gyp.MSVSVersion.SelectVisualStudioVersion( |
444 generator_flags.get('msvs_version', 'auto')) | 527 generator_flags.get('msvs_version', 'auto')) |
445 return vs_version | 528 return vs_version |
446 | 529 |
447 def _GetBinaryPath(generator_flags, tool): | 530 def _GetBinaryPath(generator_flags, tool): |
448 vs = GetVSVersion(generator_flags) | 531 vs = GetVSVersion(generator_flags) |
(...skipping 19 matching lines...) Expand all Loading... | |
468 return vs.SetupScript() | 551 return vs.SetupScript() |
469 | 552 |
470 def ExpandMacros(string, expansions): | 553 def ExpandMacros(string, expansions): |
471 """Expand $(Variable) per expansions dict. See MsvsSettings.GetVSMacroEnv | 554 """Expand $(Variable) per expansions dict. See MsvsSettings.GetVSMacroEnv |
472 for the canonical way to retrieve a suitable dict.""" | 555 for the canonical way to retrieve a suitable dict.""" |
473 if '$' in string: | 556 if '$' in string: |
474 for old, new in expansions.iteritems(): | 557 for old, new in expansions.iteritems(): |
475 assert '$(' not in new, new | 558 assert '$(' not in new, new |
476 string = string.replace(old, new) | 559 string = string.replace(old, new) |
477 return string | 560 return string |
OLD | NEW |