Chromium Code Reviews| 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 |