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."""
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', '')
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:
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.
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
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
164
211
self.msvs_cygwin_dirs = spec.get('msvs_cygwin_dirs', ['.'])
213
unsupported_fields = [
218
for field in unsupported_fields:
219
for config in configs.values():
221
unsupported += ["%s not supported (target %s)." %
222
(field, spec['target_name'])]
224
raise Exception('\n'.join(unsupported))
226
def GetExtension(self):
227
"""Returns the extension for the target, with no leading dot.
229
Uses 'product_extension' if specified, otherwise uses MSVS defaults based on
232
ext = self.spec.get('product_extension', None)
235
return gyp.MSVSUtil.TARGET_TYPE_EXT.get(self.spec['type'], '')
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
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
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),
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(),
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
198
264
def ConvertVSMacros(self, s, base_to_build=None, config=None):
271
338
('VCCLCompilerTool', 'AdditionalIncludeDirectories'), config, default=[]))
272
339
return [self.ConvertVSMacros(p, config=config) for p in includes]
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]
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
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)
325
output_file = expand_special(self.ConvertVSMacros(
326
output_file, config=config))
400
generate_debug_info = self._Setting(
401
('VCLinkerTool', 'GenerateDebugInformation'), config)
402
if generate_debug_info == 'true':
404
return expand_special(self.ConvertVSMacros(output_file, config=config))
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'
417
def GetAsmflags(self, config):
418
"""Returns the flags that need to be added to ml invocations."""
419
config = self._TargetConfig(config)
421
safeseh = self._Setting(('MASM', 'UseSafeExceptionHandlers'), config)
422
if safeseh == 'true':
423
asmflags.append('/safeseh')
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:',
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'},
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)
371
def GetPrecompiledHeader(self, config, gyp_to_build_path):
372
"""Returns an object that handles the generation of precompiled header
374
config = self._TargetConfig(config)
375
return _PchHelper(self, config, gyp_to_build_path)
377
478
def _GetPchFlags(self, config, extension):
378
479
"""Get the flags to be added to the cflags for precompiled header support.
440
543
ldflags.append('/DEF:"%s"' % def_file)
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)
552
output_file = expand_special(self.ConvertVSMacros(
553
output_file, config=config))
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'},
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)
458
575
ldflags.append('/OUT:' + out)
459
pdb = self.GetPDBName(config, expand_special)
576
pdb = self.GetPDBName(config, expand_special, output_name + '.pdb')
461
578
ldflags.append('/PDB:' + pdb)
579
pgd = self.GetPGDName(config, expand_special)
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
465
585
ld('MapExports', map={'true': '/MAPINFO:EXPORTS'})
466
586
ld('AdditionalOptions', prefix='')
467
ld('SubSystem', map={'1': 'CONSOLE', '2': 'WINDOWS'}, prefix='/SUBSYSTEM:')
588
minimum_required_version = self._Setting(
589
('VCLinkerTool', 'MinimumRequiredVersion'), config, default='')
590
if minimum_required_version:
591
minimum_required_version = ',' + minimum_required_version
593
map={'1': 'CONSOLE%s' % minimum_required_version,
594
'2': 'WINDOWS%s' % minimum_required_version},
595
prefix='/SUBSYSTEM:')
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))
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',
478
621
ld('IgnoreDefaultLibraryNames', prefix='/NODEFAULTLIB:')
479
622
ld('ResourceOnlyDLL', map={'true': '/NOENTRY'})
480
623
ld('EntryPointSymbol', prefix='/ENTRY:')
499
650
ldflags.append('/NXCOMPAT')
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)
508
return ldflags, manifest_files
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
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
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'),
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'], [], []
514
677
output_name = name + '.intermediate.manifest'
517
680
'/ManifestFile:' + output_name,
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.
691
# Always NO, because we generate a manifest file that has what we want.
692
flags.append('/MANIFESTUAC:NO')
520
694
config = self._TargetConfig(config)
521
695
enable_uac = self._Setting(('VCLinkerTool', 'EnableUAC'), config,
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" \
523
702
if enable_uac == 'true':
524
703
execution_level = self._Setting(('VCLinkerTool', 'UACExecutionLevel'),
525
704
config, default='0')
532
711
ui_access = self._Setting(('VCLinkerTool', 'UACUIAccess'), config,
534
flags.append('''/MANIFESTUAC:"level='%s' uiAccess='%s'"''' %
535
(execution_level_map[execution_level], ui_access))
715
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
717
<requestedPrivileges>
718
<requestedExecutionLevel level='%s' uiAccess='%s' />
719
</requestedPrivileges>
721
</trustInfo>''' % (execution_level_map[execution_level], ui_access)
537
flags.append('/MANIFESTUAC:NO')
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
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)
737
manifest_files = [generated_name]
539
739
if allow_isolation:
540
740
flags.append('/ALLOWISOLATION')
541
return flags, output_name
742
manifest_files += self._GetAdditionalManifestFiles(config,
744
return flags, output_name, manifest_files
543
746
def _GetAdditionalManifestFiles(self, config, gyp_to_build_path):
544
747
"""Gets additional manifest files that are added to the default one
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', [])])
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))
625
835
def HasExplicitAsmRules(self, spec):
626
836
"""Determine if there's an explicit rule for asm files. When there isn't we
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))
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', {})
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()
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
1087
default_variables['MSVS_OS_BITS'] = 32