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