~hjd/ubuntu/wily/gyp/debian-merged

« back to all changes in this revision

Viewing changes to pylib/gyp/msvs_emulation.py

  • Committer: Hans Joachim Desserud
  • Date: 2015-10-31 12:46:59 UTC
  • mfrom: (6.2.6 sid)
  • Revision ID: hans_joachim_desserud-20151031124659-lzxekr6woskh4k0b
Merge latest Debian version

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
import subprocess
13
13
import sys
14
14
 
 
15
from gyp.common import OrderedSet
 
16
import gyp.MSVSUtil
15
17
import gyp.MSVSVersion
16
18
 
 
19
 
17
20
windows_quoter_regex = re.compile(r'(\\*)"')
18
21
 
 
22
 
19
23
def QuoteForRspFile(arg):
20
24
  """Quote a command line argument so that it appears as one argument when
21
25
  processed via cmd.exe and parsed by CommandLineToArgvW (as is typical for
131
135
  return dxsdk_dir
132
136
 
133
137
 
 
138
def GetGlobalVSMacroEnv(vs_version):
 
139
  """Get a dict of variables mapping internal VS macro names to their gyp
 
140
  equivalents. Returns all variables that are independent of the target."""
 
141
  env = {}
 
142
  # '$(VSInstallDir)' and '$(VCInstallDir)' are available when and only when
 
143
  # Visual Studio is actually installed.
 
144
  if vs_version.Path():
 
145
    env['$(VSInstallDir)'] = vs_version.Path()
 
146
    env['$(VCInstallDir)'] = os.path.join(vs_version.Path(), 'VC') + '\\'
 
147
  # Chromium uses DXSDK_DIR in include/lib paths, but it may or may not be
 
148
  # set. This happens when the SDK is sync'd via src-internal, rather than
 
149
  # by typical end-user installation of the SDK. If it's not set, we don't
 
150
  # want to leave the unexpanded variable in the path, so simply strip it.
 
151
  dxsdk_dir = _FindDirectXInstallation()
 
152
  env['$(DXSDK_DIR)'] = dxsdk_dir if dxsdk_dir else ''
 
153
  # Try to find an installation location for the Windows DDK by checking
 
154
  # the WDK_DIR environment variable, may be None.
 
155
  env['$(WDK_DIR)'] = os.environ.get('WDK_DIR', '')
 
156
  return env
 
157
 
 
158
def ExtractSharedMSVSSystemIncludes(configs, generator_flags):
 
159
  """Finds msvs_system_include_dirs that are common to all targets, removes
 
160
  them from all targets, and returns an OrderedSet containing them."""
 
161
  all_system_includes = OrderedSet(
 
162
      configs[0].get('msvs_system_include_dirs', []))
 
163
  for config in configs[1:]:
 
164
    system_includes = config.get('msvs_system_include_dirs', [])
 
165
    all_system_includes = all_system_includes & OrderedSet(system_includes)
 
166
  if not all_system_includes:
 
167
    return None
 
168
  # Expand macros in all_system_includes.
 
169
  env = GetGlobalVSMacroEnv(GetVSVersion(generator_flags))
 
170
  expanded_system_includes = OrderedSet([ExpandMacros(include, env)
 
171
                                         for include in all_system_includes])
 
172
  if any(['$' in include for include in expanded_system_includes]):
 
173
    # Some path relies on target-specific variables, bail.
 
174
    return None
 
175
 
 
176
  # Remove system includes shared by all targets from the targets.
 
177
  for config in configs:
 
178
    includes = config.get('msvs_system_include_dirs', [])
 
179
    if includes:  # Don't insert a msvs_system_include_dirs key if not needed.
 
180
      # This must check the unexpanded includes list:
 
181
      new_includes = [i for i in includes if i not in all_system_includes]
 
182
      config['msvs_system_include_dirs'] = new_includes
 
183
  return expanded_system_includes
 
184
 
 
185
 
134
186
class MsvsSettings(object):
135
187
  """A class that understands the gyp 'msvs_...' values (especially the
136
188
  msvs_settings field). They largely correpond to the VS2008 IDE DOM. This
139
191
  def __init__(self, spec, generator_flags):
140
192
    self.spec = spec
141
193
    self.vs_version = GetVSVersion(generator_flags)
142
 
    self.dxsdk_dir = _FindDirectXInstallation()
143
 
 
144
 
    # Try to find an installation location for the Windows DDK by checking
145
 
    # the WDK_DIR environment variable, may be None.
146
 
    self.wdk_dir = os.environ.get('WDK_DIR')
147
194
 
148
195
    supported_fields = [
149
196
        ('msvs_configuration_attributes', dict),
163
210
 
164
211
    self.msvs_cygwin_dirs = spec.get('msvs_cygwin_dirs', ['.'])
165
212
 
 
213
    unsupported_fields = [
 
214
        'msvs_prebuild',
 
215
        'msvs_postbuild',
 
216
    ]
 
217
    unsupported = []
 
218
    for field in unsupported_fields:
 
219
      for config in configs.values():
 
220
        if field in config:
 
221
          unsupported += ["%s not supported (target %s)." %
 
222
                          (field, spec['target_name'])]
 
223
    if unsupported:
 
224
      raise Exception('\n'.join(unsupported))
 
225
 
 
226
  def GetExtension(self):
 
227
    """Returns the extension for the target, with no leading dot.
 
228
 
 
229
    Uses 'product_extension' if specified, otherwise uses MSVS defaults based on
 
230
    the target type.
 
231
    """
 
232
    ext = self.spec.get('product_extension', None)
 
233
    if ext:
 
234
      return ext
 
235
    return gyp.MSVSUtil.TARGET_TYPE_EXT.get(self.spec['type'], '')
 
236
 
166
237
  def GetVSMacroEnv(self, base_to_build=None, config=None):
167
238
    """Get a dict of variables mapping internal VS macro names to their gyp
168
239
    equivalents."""
170
241
    target_name = self.spec.get('product_prefix', '') + \
171
242
        self.spec.get('product_name', self.spec['target_name'])
172
243
    target_dir = base_to_build + '\\' if base_to_build else ''
 
244
    target_ext = '.' + self.GetExtension()
 
245
    target_file_name = target_name + target_ext
 
246
 
173
247
    replacements = {
 
248
        '$(InputName)': '${root}',
 
249
        '$(InputPath)': '${source}',
 
250
        '$(IntDir)': '$!INTERMEDIATE_DIR',
174
251
        '$(OutDir)\\': target_dir,
 
252
        '$(PlatformName)': target_platform,
 
253
        '$(ProjectDir)\\': '',
 
254
        '$(ProjectName)': self.spec['target_name'],
175
255
        '$(TargetDir)\\': target_dir,
176
 
        '$(IntDir)': '$!INTERMEDIATE_DIR',
177
 
        '$(InputPath)': '${source}',
178
 
        '$(InputName)': '${root}',
179
 
        '$(ProjectName)': self.spec['target_name'],
 
256
        '$(TargetExt)': target_ext,
 
257
        '$(TargetFileName)': target_file_name,
180
258
        '$(TargetName)': target_name,
181
 
        '$(PlatformName)': target_platform,
182
 
        '$(ProjectDir)\\': '',
 
259
        '$(TargetPath)': os.path.join(target_dir, target_file_name),
183
260
    }
184
 
    # '$(VSInstallDir)' and '$(VCInstallDir)' are available when and only when
185
 
    # Visual Studio is actually installed.
186
 
    if self.vs_version.Path():
187
 
      replacements['$(VSInstallDir)'] = self.vs_version.Path()
188
 
      replacements['$(VCInstallDir)'] = os.path.join(self.vs_version.Path(),
189
 
                                                     'VC') + '\\'
190
 
    # Chromium uses DXSDK_DIR in include/lib paths, but it may or may not be
191
 
    # set. This happens when the SDK is sync'd via src-internal, rather than
192
 
    # by typical end-user installation of the SDK. If it's not set, we don't
193
 
    # want to leave the unexpanded variable in the path, so simply strip it.
194
 
    replacements['$(DXSDK_DIR)'] = self.dxsdk_dir if self.dxsdk_dir else ''
195
 
    replacements['$(WDK_DIR)'] = self.wdk_dir if self.wdk_dir else ''
 
261
    replacements.update(GetGlobalVSMacroEnv(self.vs_version))
196
262
    return replacements
197
263
 
198
264
  def ConvertVSMacros(self, s, base_to_build=None, config=None):
202
268
 
203
269
  def AdjustLibraries(self, libraries):
204
270
    """Strip -l from library if it's specified with that."""
205
 
    return [lib[2:] if lib.startswith('-l') else lib for lib in libraries]
 
271
    libs = [lib[2:] if lib.startswith('-l') else lib for lib in libraries]
 
272
    return [lib + '.lib' if not lib.endswith('.lib') else lib for lib in libs]
206
273
 
207
274
  def _GetAndMunge(self, field, path, default, prefix, append, map):
208
275
    """Retrieve a value from |field| at |path| or return |default|. If
271
338
      ('VCCLCompilerTool', 'AdditionalIncludeDirectories'), config, default=[]))
272
339
    return [self.ConvertVSMacros(p, config=config) for p in includes]
273
340
 
 
341
  def AdjustMidlIncludeDirs(self, midl_include_dirs, config):
 
342
    """Updates midl_include_dirs to expand VS specific paths, and adds the
 
343
    system include dirs used for platform SDK and similar."""
 
344
    config = self._TargetConfig(config)
 
345
    includes = midl_include_dirs + self.msvs_system_include_dirs[config]
 
346
    includes.extend(self._Setting(
 
347
      ('VCMIDLTool', 'AdditionalIncludeDirectories'), config, default=[]))
 
348
    return [self.ConvertVSMacros(p, config=config) for p in includes]
 
349
 
274
350
  def GetComputedDefines(self, config):
275
351
    """Returns the set of defines that are injected to the defines list based
276
352
    on other VS settings."""
316
392
          output_file, config=config))
317
393
    return output_file
318
394
 
319
 
  def GetPDBName(self, config, expand_special):
320
 
    """Gets the explicitly overridden pdb name for a target or returns None
321
 
    if it's not overridden."""
 
395
  def GetPDBName(self, config, expand_special, default):
 
396
    """Gets the explicitly overridden pdb name for a target or returns
 
397
    default if it's not overridden, or if no pdb will be generated."""
322
398
    config = self._TargetConfig(config)
323
399
    output_file = self._Setting(('VCLinkerTool', 'ProgramDatabaseFile'), config)
324
 
    if output_file:
325
 
      output_file = expand_special(self.ConvertVSMacros(
326
 
          output_file, config=config))
327
 
    return output_file
 
400
    generate_debug_info = self._Setting(
 
401
        ('VCLinkerTool', 'GenerateDebugInformation'), config)
 
402
    if generate_debug_info == 'true':
 
403
      if output_file:
 
404
        return expand_special(self.ConvertVSMacros(output_file, config=config))
 
405
      else:
 
406
        return default
 
407
    else:
 
408
      return None
 
409
 
 
410
  def GetNoImportLibrary(self, config):
 
411
    """If NoImportLibrary: true, ninja will not expect the output to include
 
412
    an import library."""
 
413
    config = self._TargetConfig(config)
 
414
    noimplib = self._Setting(('NoImportLibrary',), config)
 
415
    return noimplib == 'true'
 
416
 
 
417
  def GetAsmflags(self, config):
 
418
    """Returns the flags that need to be added to ml invocations."""
 
419
    config = self._TargetConfig(config)
 
420
    asmflags = []
 
421
    safeseh = self._Setting(('MASM', 'UseSafeExceptionHandlers'), config)
 
422
    if safeseh == 'true':
 
423
      asmflags.append('/safeseh')
 
424
    return asmflags
328
425
 
329
426
  def GetCflags(self, config):
330
427
    """Returns the flags that need to be added to .c and .cc compilations."""
336
433
    cl('Optimization',
337
434
       map={'0': 'd', '1': '1', '2': '2', '3': 'x'}, prefix='/O', default='2')
338
435
    cl('InlineFunctionExpansion', prefix='/Ob')
 
436
    cl('DisableSpecificWarnings', prefix='/wd')
339
437
    cl('StringPooling', map={'true': '/GF'})
340
438
    cl('EnableFiberSafeOptimizations', map={'true': '/GT'})
341
439
    cl('OmitFramePointers', map={'false': '-', 'true': ''}, prefix='/Oy')
342
440
    cl('EnableIntrinsicFunctions', map={'false': '-', 'true': ''}, prefix='/Oi')
343
441
    cl('FavorSizeOrSpeed', map={'1': 't', '2': 's'}, prefix='/O')
 
442
    cl('FloatingPointModel',
 
443
        map={'0': 'precise', '1': 'strict', '2': 'fast'}, prefix='/fp:',
 
444
        default='0')
 
445
    cl('CompileAsManaged', map={'false': '', 'true': '/clr'})
344
446
    cl('WholeProgramOptimization', map={'true': '/GL'})
345
447
    cl('WarningLevel', prefix='/W')
346
448
    cl('WarnAsError', map={'true': '/WX'})
 
449
    cl('CallingConvention',
 
450
        map={'0': 'd', '1': 'r', '2': 'z', '3': 'v'}, prefix='/G')
347
451
    cl('DebugInformationFormat',
348
452
        map={'1': '7', '3': 'i', '4': 'I'}, prefix='/Z')
349
453
    cl('RuntimeTypeInfo', map={'true': '/GR', 'false': '/GR-'})
359
463
        map={'false': '-', 'true': ''}, prefix='/Zc:wchar_t')
360
464
    cl('EnablePREfast', map={'true': '/analyze'})
361
465
    cl('AdditionalOptions', prefix='')
 
466
    cl('EnableEnhancedInstructionSet',
 
467
        map={'1': 'SSE', '2': 'SSE2', '3': 'AVX', '4': 'IA32', '5': 'AVX2'},
 
468
        prefix='/arch:')
362
469
    cflags.extend(['/FI' + f for f in self._Setting(
363
470
        ('VCCLCompilerTool', 'ForcedIncludeFiles'), config, default=[])])
364
 
    if self.vs_version.short_name == '2013' or self.vs_version == '2013e':
 
471
    if self.vs_version.short_name in ('2013', '2013e', '2015'):
365
472
      # New flag required in 2013 to maintain previous PDB behavior.
366
473
      cflags.append('/FS')
367
474
    # ninja handles parallelism by itself, don't have the compiler do it too.
368
475
    cflags = filter(lambda x: not x.startswith('/MP'), cflags)
369
476
    return cflags
370
477
 
371
 
  def GetPrecompiledHeader(self, config, gyp_to_build_path):
372
 
    """Returns an object that handles the generation of precompiled header
373
 
    build steps."""
374
 
    config = self._TargetConfig(config)
375
 
    return _PchHelper(self, config, gyp_to_build_path)
376
 
 
377
478
  def _GetPchFlags(self, config, extension):
378
479
    """Get the flags to be added to the cflags for precompiled header support.
379
480
    """
418
519
    libflags.extend(self._GetAdditionalLibraryDirectories(
419
520
        'VCLibrarianTool', config, gyp_to_build_path))
420
521
    lib('LinkTimeCodeGeneration', map={'true': '/LTCG'})
 
522
    lib('TargetMachine', map={'1': 'X86', '17': 'X64', '3': 'ARM'},
 
523
        prefix='/MACHINE:')
421
524
    lib('AdditionalOptions')
422
525
    return libflags
423
526
 
439
542
    if def_file:
440
543
      ldflags.append('/DEF:"%s"' % def_file)
441
544
 
 
545
  def GetPGDName(self, config, expand_special):
 
546
    """Gets the explicitly overridden pgd name for a target or returns None
 
547
    if it's not overridden."""
 
548
    config = self._TargetConfig(config)
 
549
    output_file = self._Setting(
 
550
        ('VCLinkerTool', 'ProfileGuidedDatabase'), config)
 
551
    if output_file:
 
552
      output_file = expand_special(self.ConvertVSMacros(
 
553
          output_file, config=config))
 
554
    return output_file
 
555
 
442
556
  def GetLdflags(self, config, gyp_to_build_path, expand_special,
443
 
                 manifest_base_name, is_executable):
 
557
                 manifest_base_name, output_name, is_executable, build_dir):
444
558
    """Returns the flags that need to be added to link commands, and the
445
559
    manifest files."""
446
560
    config = self._TargetConfig(config)
449
563
                          'VCLinkerTool', append=ldflags)
450
564
    self._GetDefFileAsLdflags(ldflags, gyp_to_build_path)
451
565
    ld('GenerateDebugInformation', map={'true': '/DEBUG'})
452
 
    ld('TargetMachine', map={'1': 'X86', '17': 'X64'}, prefix='/MACHINE:')
 
566
    ld('TargetMachine', map={'1': 'X86', '17': 'X64', '3': 'ARM'},
 
567
       prefix='/MACHINE:')
453
568
    ldflags.extend(self._GetAdditionalLibraryDirectories(
454
569
        'VCLinkerTool', config, gyp_to_build_path))
455
570
    ld('DelayLoadDLLs', prefix='/DELAYLOAD:')
 
571
    ld('TreatLinkerWarningAsErrors', prefix='/WX',
 
572
       map={'true': '', 'false': ':NO'})
456
573
    out = self.GetOutputName(config, expand_special)
457
574
    if out:
458
575
      ldflags.append('/OUT:' + out)
459
 
    pdb = self.GetPDBName(config, expand_special)
 
576
    pdb = self.GetPDBName(config, expand_special, output_name + '.pdb')
460
577
    if pdb:
461
578
      ldflags.append('/PDB:' + pdb)
 
579
    pgd = self.GetPGDName(config, expand_special)
 
580
    if pgd:
 
581
      ldflags.append('/PGD:' + pgd)
462
582
    map_file = self.GetMapFileName(config, expand_special)
463
583
    ld('GenerateMapFile', map={'true': '/MAP:' + map_file if map_file
464
584
        else '/MAP'})
465
585
    ld('MapExports', map={'true': '/MAPINFO:EXPORTS'})
466
586
    ld('AdditionalOptions', prefix='')
467
 
    ld('SubSystem', map={'1': 'CONSOLE', '2': 'WINDOWS'}, prefix='/SUBSYSTEM:')
 
587
 
 
588
    minimum_required_version = self._Setting(
 
589
        ('VCLinkerTool', 'MinimumRequiredVersion'), config, default='')
 
590
    if minimum_required_version:
 
591
      minimum_required_version = ',' + minimum_required_version
 
592
    ld('SubSystem',
 
593
       map={'1': 'CONSOLE%s' % minimum_required_version,
 
594
            '2': 'WINDOWS%s' % minimum_required_version},
 
595
       prefix='/SUBSYSTEM:')
 
596
 
 
597
    stack_reserve_size = self._Setting(
 
598
        ('VCLinkerTool', 'StackReserveSize'), config, default='')
 
599
    if stack_reserve_size:
 
600
      stack_commit_size = self._Setting(
 
601
          ('VCLinkerTool', 'StackCommitSize'), config, default='')
 
602
      if stack_commit_size:
 
603
        stack_commit_size = ',' + stack_commit_size
 
604
      ldflags.append('/STACK:%s%s' % (stack_reserve_size, stack_commit_size))
 
605
 
468
606
    ld('TerminalServerAware', map={'1': ':NO', '2': ''}, prefix='/TSAWARE')
469
607
    ld('LinkIncremental', map={'1': ':NO', '2': ''}, prefix='/INCREMENTAL')
 
608
    ld('BaseAddress', prefix='/BASE:')
470
609
    ld('FixedBaseAddress', map={'1': ':NO', '2': ''}, prefix='/FIXED')
471
610
    ld('RandomizedBaseAddress',
472
611
        map={'1': ':NO', '2': ''}, prefix='/DYNAMICBASE')
473
612
    ld('DataExecutionPrevention',
474
613
        map={'1': ':NO', '2': ''}, prefix='/NXCOMPAT')
475
614
    ld('OptimizeReferences', map={'1': 'NOREF', '2': 'REF'}, prefix='/OPT:')
 
615
    ld('ForceSymbolReferences', prefix='/INCLUDE:')
476
616
    ld('EnableCOMDATFolding', map={'1': 'NOICF', '2': 'ICF'}, prefix='/OPT:')
477
 
    ld('LinkTimeCodeGeneration', map={'1': '/LTCG'})
 
617
    ld('LinkTimeCodeGeneration',
 
618
        map={'1': '', '2': ':PGINSTRUMENT', '3': ':PGOPTIMIZE',
 
619
             '4': ':PGUPDATE'},
 
620
        prefix='/LTCG')
478
621
    ld('IgnoreDefaultLibraryNames', prefix='/NODEFAULTLIB:')
479
622
    ld('ResourceOnlyDLL', map={'true': '/NOENTRY'})
480
623
    ld('EntryPointSymbol', prefix='/ENTRY:')
484
627
    # TODO(scottmg): This should sort of be somewhere else (not really a flag).
485
628
    ld('AdditionalDependencies', prefix='')
486
629
 
 
630
    if self.GetArch(config) == 'x86':
 
631
      safeseh_default = 'true'
 
632
    else:
 
633
      safeseh_default = None
 
634
    ld('ImageHasSafeExceptionHandlers',
 
635
        map={'false': ':NO', 'true': ''}, prefix='/SAFESEH',
 
636
        default=safeseh_default)
 
637
 
487
638
    # If the base address is not specifically controlled, DYNAMICBASE should
488
639
    # be on by default.
489
640
    base_flags = filter(lambda x: 'DYNAMICBASE' in x or x == '/FIXED',
499
650
      ldflags.append('/NXCOMPAT')
500
651
 
501
652
    have_def_file = filter(lambda x: x.startswith('/DEF:'), ldflags)
502
 
    manifest_flags, intermediate_manifest_file = self._GetLdManifestFlags(
503
 
        config, manifest_base_name, is_executable and not have_def_file)
 
653
    manifest_flags, intermediate_manifest, manifest_files = \
 
654
        self._GetLdManifestFlags(config, manifest_base_name, gyp_to_build_path,
 
655
                                 is_executable and not have_def_file, build_dir)
504
656
    ldflags.extend(manifest_flags)
505
 
    manifest_files = self._GetAdditionalManifestFiles(config, gyp_to_build_path)
506
 
    manifest_files.append(intermediate_manifest_file)
507
 
 
508
 
    return ldflags, manifest_files
509
 
 
510
 
  def _GetLdManifestFlags(self, config, name, allow_isolation):
511
 
    """Returns the set of flags that need to be added to the link to generate
512
 
    a default manifest, as well as the name of the generated file."""
513
 
    # The manifest is generated by default.
 
657
    return ldflags, intermediate_manifest, manifest_files
 
658
 
 
659
  def _GetLdManifestFlags(self, config, name, gyp_to_build_path,
 
660
                          allow_isolation, build_dir):
 
661
    """Returns a 3-tuple:
 
662
    - the set of flags that need to be added to the link to generate
 
663
      a default manifest
 
664
    - the intermediate manifest that the linker will generate that should be
 
665
      used to assert it doesn't add anything to the merged one.
 
666
    - the list of all the manifest files to be merged by the manifest tool and
 
667
      included into the link."""
 
668
    generate_manifest = self._Setting(('VCLinkerTool', 'GenerateManifest'),
 
669
                                      config,
 
670
                                      default='true')
 
671
    if generate_manifest != 'true':
 
672
      # This means not only that the linker should not generate the intermediate
 
673
      # manifest but also that the manifest tool should do nothing even when
 
674
      # additional manifests are specified.
 
675
      return ['/MANIFEST:NO'], [], []
 
676
 
514
677
    output_name = name + '.intermediate.manifest'
515
678
    flags = [
516
679
      '/MANIFEST',
517
680
      '/ManifestFile:' + output_name,
518
681
    ]
519
682
 
 
683
    # Instead of using the MANIFESTUAC flags, we generate a .manifest to
 
684
    # include into the list of manifests. This allows us to avoid the need to
 
685
    # do two passes during linking. The /MANIFEST flag and /ManifestFile are
 
686
    # still used, and the intermediate manifest is used to assert that the
 
687
    # final manifest we get from merging all the additional manifest files
 
688
    # (plus the one we generate here) isn't modified by merging the
 
689
    # intermediate into it.
 
690
 
 
691
    # Always NO, because we generate a manifest file that has what we want.
 
692
    flags.append('/MANIFESTUAC:NO')
 
693
 
520
694
    config = self._TargetConfig(config)
521
695
    enable_uac = self._Setting(('VCLinkerTool', 'EnableUAC'), config,
522
696
                               default='true')
 
697
    manifest_files = []
 
698
    generated_manifest_outer = \
 
699
"<?xml version='1.0' encoding='UTF-8' standalone='yes'?>" \
 
700
"<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>%s" \
 
701
"</assembly>"
523
702
    if enable_uac == 'true':
524
703
      execution_level = self._Setting(('VCLinkerTool', 'UACExecutionLevel'),
525
704
                                      config, default='0')
531
710
 
532
711
      ui_access = self._Setting(('VCLinkerTool', 'UACUIAccess'), config,
533
712
                                default='false')
534
 
      flags.append('''/MANIFESTUAC:"level='%s' uiAccess='%s'"''' %
535
 
          (execution_level_map[execution_level], ui_access))
 
713
 
 
714
      inner = '''
 
715
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
 
716
  <security>
 
717
    <requestedPrivileges>
 
718
      <requestedExecutionLevel level='%s' uiAccess='%s' />
 
719
    </requestedPrivileges>
 
720
  </security>
 
721
</trustInfo>''' % (execution_level_map[execution_level], ui_access)
536
722
    else:
537
 
      flags.append('/MANIFESTUAC:NO')
 
723
      inner = ''
 
724
 
 
725
    generated_manifest_contents = generated_manifest_outer % inner
 
726
    generated_name = name + '.generated.manifest'
 
727
    # Need to join with the build_dir here as we're writing it during
 
728
    # generation time, but we return the un-joined version because the build
 
729
    # will occur in that directory. We only write the file if the contents
 
730
    # have changed so that simply regenerating the project files doesn't
 
731
    # cause a relink.
 
732
    build_dir_generated_name = os.path.join(build_dir, generated_name)
 
733
    gyp.common.EnsureDirExists(build_dir_generated_name)
 
734
    f = gyp.common.WriteOnDiff(build_dir_generated_name)
 
735
    f.write(generated_manifest_contents)
 
736
    f.close()
 
737
    manifest_files = [generated_name]
538
738
 
539
739
    if allow_isolation:
540
740
      flags.append('/ALLOWISOLATION')
541
 
    return flags, output_name
 
741
 
 
742
    manifest_files += self._GetAdditionalManifestFiles(config,
 
743
                                                       gyp_to_build_path)
 
744
    return flags, output_name, manifest_files
542
745
 
543
746
  def _GetAdditionalManifestFiles(self, config, gyp_to_build_path):
544
747
    """Gets additional manifest files that are added to the default one
561
764
  def IsEmbedManifest(self, config):
562
765
    """Returns whether manifest should be linked into binary."""
563
766
    config = self._TargetConfig(config)
564
 
    embed = self._Setting(('VCManifestTool', 'EmbedManifest'), config)
 
767
    embed = self._Setting(('VCManifestTool', 'EmbedManifest'), config,
 
768
                          default='true')
565
769
    return embed == 'true'
566
770
 
567
771
  def IsLinkIncremental(self, config):
617
821
        return True
618
822
    return False
619
823
 
620
 
  def HasExplicitIdlRules(self, spec):
621
 
    """Determine if there's an explicit rule for idl files. When there isn't we
622
 
    need to generate implicit rules to build MIDL .idl files."""
623
 
    return self._HasExplicitRuleForExtension(spec, 'idl')
 
824
  def _HasExplicitIdlActions(self, spec):
 
825
    """Determine if an action should not run midl for .idl files."""
 
826
    return any([action.get('explicit_idl_action', 0)
 
827
                for action in spec.get('actions', [])])
 
828
 
 
829
  def HasExplicitIdlRulesOrActions(self, spec):
 
830
    """Determine if there's an explicit rule or action for idl files. When
 
831
    there isn't we need to generate implicit rules to build MIDL .idl files."""
 
832
    return (self._HasExplicitRuleForExtension(spec, 'idl') or
 
833
            self._HasExplicitIdlActions(spec))
624
834
 
625
835
  def HasExplicitAsmRules(self, spec):
626
836
    """Determine if there's an explicit rule for asm files. When there isn't we
683
893
  def GetObjDependencies(self, sources, objs, arch):
684
894
    """Given a list of sources files and the corresponding object files,
685
895
    returns a list of the pch files that should be depended upon. The
686
 
    additional wrapping in the return value is for interface compatability
 
896
    additional wrapping in the return value is for interface compatibility
687
897
    with make.py on Mac, and xcode_emulation.py."""
688
898
    assert arch is None
689
899
    if not self._PchHeader():
719
929
  global vs_version
720
930
  if not vs_version:
721
931
    vs_version = gyp.MSVSVersion.SelectVisualStudioVersion(
722
 
        generator_flags.get('msvs_version', 'auto'))
 
932
        generator_flags.get('msvs_version', 'auto'),
 
933
        allow_fallback=False)
723
934
  return vs_version
724
935
 
725
936
def _GetVsvarsSetupArgs(generator_flags, arch):
787
998
    if line.startswith('LOC:'):
788
999
      return line[len('LOC:'):].strip()
789
1000
 
790
 
def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags, open_out):
 
1001
def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags,
 
1002
                             system_includes, open_out):
791
1003
  """It's not sufficient to have the absolute path to the compiler, linker,
792
1004
  etc. on Windows, as those tools rely on .dlls being in the PATH. We also
793
1005
  need to support both x86 and x64 compilers within the same build (to support
818
1030
        args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
819
1031
    variables, _ = popen.communicate()
820
1032
    env = _ExtractImportantEnvironment(variables)
 
1033
 
 
1034
    # Inject system includes from gyp files into INCLUDE.
 
1035
    if system_includes:
 
1036
      system_includes = system_includes | OrderedSet(
 
1037
                                              env.get('INCLUDE', '').split(';'))
 
1038
      env['INCLUDE'] = ';'.join(system_includes)
 
1039
 
821
1040
    env_block = _FormatAsEnvironmentBlock(env)
822
1041
    f = open_out(os.path.join(toplevel_build_dir, 'environment.' + arch), 'wb')
823
1042
    f.write(env_block)
847
1066
      # path for a slightly less crazy looking output.
848
1067
      cleaned_up = [os.path.normpath(x) for x in missing]
849
1068
      raise Exception('Missing input files:\n%s' % '\n'.join(cleaned_up))
 
1069
 
 
1070
# Sets some values in default_variables, which are required for many
 
1071
# generators, run on Windows.
 
1072
def CalculateCommonVariables(default_variables, params):
 
1073
  generator_flags = params.get('generator_flags', {})
 
1074
 
 
1075
  # Set a variable so conditions can be based on msvs_version.
 
1076
  msvs_version = gyp.msvs_emulation.GetVSVersion(generator_flags)
 
1077
  default_variables['MSVS_VERSION'] = msvs_version.ShortName()
 
1078
 
 
1079
  # To determine processor word size on Windows, in addition to checking
 
1080
  # PROCESSOR_ARCHITECTURE (which reflects the word size of the current
 
1081
  # process), it is also necessary to check PROCESSOR_ARCHITEW6432 (which
 
1082
  # contains the actual word size of the system when running thru WOW64).
 
1083
  if ('64' in os.environ.get('PROCESSOR_ARCHITECTURE', '') or
 
1084
      '64' in os.environ.get('PROCESSOR_ARCHITEW6432', '')):
 
1085
    default_variables['MSVS_OS_BITS'] = 64
 
1086
  else:
 
1087
    default_variables['MSVS_OS_BITS'] = 32