Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: pylib/gyp/msvs_emulation.py

Issue 111373002: win ninja: Refactor manifest generate and embed to be 1-pass (Closed) Base URL: http://gyp.googlecode.com/svn/trunk
Patch Set: add some extra print in failure case, and rebase Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pylib/gyp/generator/ninja.py ('k') | pylib/gyp/win_tool.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 # normalized correctly. 55 # normalized correctly.
56 if not args: return '' 56 if not args: return ''
57 if args[0].startswith('call '): 57 if args[0].startswith('call '):
58 call, program = args[0].split(' ', 1) 58 call, program = args[0].split(' ', 1)
59 program = call + ' ' + os.path.normpath(program) 59 program = call + ' ' + os.path.normpath(program)
60 else: 60 else:
61 program = os.path.normpath(args[0]) 61 program = os.path.normpath(args[0])
62 return program + ' ' + ' '.join(QuoteForRspFile(arg) for arg in args[1:]) 62 return program + ' ' + ' '.join(QuoteForRspFile(arg) for arg in args[1:])
63 63
64 64
65 def _WriteIfChanged(open_output, filename, contents):
66 """Writes the specified contents to the specified filename if the contents
67 are different than the current contents."""
68 try:
69 with open(filename, 'rb') as f:
70 old_contents = f.read()
71 except EnvironmentError:
72 pass
73 else:
74 if contents == old_contents:
75 return
76 with open_output(filename, 'wb') as f:
77 f.write(contents)
Nico 2013/12/12 17:45:54 (There's gyp.common.WriteOnDiff fwiw. It's a bit o
scottmg 2013/12/12 18:14:05 Thanks, done with a little rejiggering. That func
78
79
65 def _GenericRetrieve(root, default, path): 80 def _GenericRetrieve(root, default, path):
66 """Given a list of dictionary keys |path| and a tree of dicts |root|, find 81 """Given a list of dictionary keys |path| and a tree of dicts |root|, find
67 value at path, or return |default| if any of the path doesn't exist.""" 82 value at path, or return |default| if any of the path doesn't exist."""
68 if not root: 83 if not root:
69 return default 84 return default
70 if not path: 85 if not path:
71 return root 86 return root
72 return _GenericRetrieve(root.get(path[0]), default, path[1:]) 87 return _GenericRetrieve(root.get(path[0]), default, path[1:])
73 88
74 89
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 if it's not overridden.""" 462 if it's not overridden."""
448 config = self._TargetConfig(config) 463 config = self._TargetConfig(config)
449 output_file = self._Setting( 464 output_file = self._Setting(
450 ('VCLinkerTool', 'ProfileGuidedDatabase'), config) 465 ('VCLinkerTool', 'ProfileGuidedDatabase'), config)
451 if output_file: 466 if output_file:
452 output_file = expand_special(self.ConvertVSMacros( 467 output_file = expand_special(self.ConvertVSMacros(
453 output_file, config=config)) 468 output_file, config=config))
454 return output_file 469 return output_file
455 470
456 def GetLdflags(self, config, gyp_to_build_path, expand_special, 471 def GetLdflags(self, config, gyp_to_build_path, expand_special,
457 manifest_base_name, is_executable): 472 manifest_base_name, is_executable, build_dir, open_output):
458 """Returns the flags that need to be added to link commands, and the 473 """Returns the flags that need to be added to link commands, and the
459 manifest files.""" 474 manifest files."""
460 config = self._TargetConfig(config) 475 config = self._TargetConfig(config)
461 ldflags = [] 476 ldflags = []
462 ld = self._GetWrapper(self, self.msvs_settings[config], 477 ld = self._GetWrapper(self, self.msvs_settings[config],
463 'VCLinkerTool', append=ldflags) 478 'VCLinkerTool', append=ldflags)
464 self._GetDefFileAsLdflags(ldflags, gyp_to_build_path) 479 self._GetDefFileAsLdflags(ldflags, gyp_to_build_path)
465 ld('GenerateDebugInformation', map={'true': '/DEBUG'}) 480 ld('GenerateDebugInformation', map={'true': '/DEBUG'})
466 ld('TargetMachine', map={'1': 'X86', '17': 'X64'}, prefix='/MACHINE:') 481 ld('TargetMachine', map={'1': 'X86', '17': 'X64'}, prefix='/MACHINE:')
467 ldflags.extend(self._GetAdditionalLibraryDirectories( 482 ldflags.extend(self._GetAdditionalLibraryDirectories(
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 ldflags.append('/DYNAMICBASE') 539 ldflags.append('/DYNAMICBASE')
525 540
526 # If the NXCOMPAT flag has not been specified, default to on. Despite the 541 # If the NXCOMPAT flag has not been specified, default to on. Despite the
527 # documentation that says this only defaults to on when the subsystem is 542 # documentation that says this only defaults to on when the subsystem is
528 # Vista or greater (which applies to the linker), the IDE defaults it on 543 # Vista or greater (which applies to the linker), the IDE defaults it on
529 # unless it's explicitly off. 544 # unless it's explicitly off.
530 if not filter(lambda x: 'NXCOMPAT' in x, ldflags): 545 if not filter(lambda x: 'NXCOMPAT' in x, ldflags):
531 ldflags.append('/NXCOMPAT') 546 ldflags.append('/NXCOMPAT')
532 547
533 have_def_file = filter(lambda x: x.startswith('/DEF:'), ldflags) 548 have_def_file = filter(lambda x: x.startswith('/DEF:'), ldflags)
534 manifest_flags, manifest_files = self._GetLdManifestFlags( 549 manifest_flags, intermediate_manifest, manifest_files = \
535 config, manifest_base_name, gyp_to_build_path, 550 self._GetLdManifestFlags(config, manifest_base_name, gyp_to_build_path,
536 is_executable and not have_def_file) 551 is_executable and not have_def_file, build_dir,
552 open_output)
537 ldflags.extend(manifest_flags) 553 ldflags.extend(manifest_flags)
538 return ldflags, manifest_files 554 return ldflags, intermediate_manifest, manifest_files
539 555
540 def _GetLdManifestFlags(self, config, name, gyp_to_build_path, 556 def _GetLdManifestFlags(self, config, name, gyp_to_build_path,
541 allow_isolation): 557 allow_isolation, build_dir, open_output):
542 """Returns the set of flags that need to be added to the link to generate 558 """Returns a 3-tuple:
543 a default manifest, as well as the list of all the manifest files to be 559 - the set of flags that need to be added to the link to generate
544 merged by the manifest tool.""" 560 a default manifest
561 - the intermediate manifest that the linker will generate that should be
562 used to assert it doesn't add anything to the merged one.
563 - the list of all the manifest files to be merged by the manifest tool and
564 included into the link."""
545 generate_manifest = self._Setting(('VCLinkerTool', 'GenerateManifest'), 565 generate_manifest = self._Setting(('VCLinkerTool', 'GenerateManifest'),
546 config, 566 config,
547 default='true') 567 default='true')
548 if generate_manifest != 'true': 568 if generate_manifest != 'true':
549 # This means not only that the linker should not generate the intermediate 569 # This means not only that the linker should not generate the intermediate
550 # manifest but also that the manifest tool should do nothing even when 570 # manifest but also that the manifest tool should do nothing even when
551 # additional manifests are specified. 571 # additional manifests are specified.
552 return ['/MANIFEST:NO'], [] 572 return ['/MANIFEST:NO'], [], []
553 573
554 output_name = name + '.intermediate.manifest' 574 output_name = name + '.intermediate.manifest'
555 flags = [ 575 flags = [
556 '/MANIFEST', 576 '/MANIFEST',
557 '/ManifestFile:' + output_name, 577 '/ManifestFile:' + output_name,
558 ] 578 ]
559 579
580 # Instead of using the MANIFESTUAC flags, we generate a .manifest to
581 # include into the list of manifests. This allows us to avoid the need to
582 # do two passes during linking. The /MANIFEST flag and /ManifestFile are
583 # still used, and the intermediate manifest is used to assert that the
584 # final manifest we get from merging all the additional manifest files
585 # (plus the one we generate here) isn't modified by merging the
586 # intermediate into it.
587
588 # Always NO, because we generate a manifest file that has what we want.
589 flags.append('/MANIFESTUAC:NO')
590
560 config = self._TargetConfig(config) 591 config = self._TargetConfig(config)
561 enable_uac = self._Setting(('VCLinkerTool', 'EnableUAC'), config, 592 enable_uac = self._Setting(('VCLinkerTool', 'EnableUAC'), config,
562 default='true') 593 default='true')
594 manifest_files = []
595 generated_manifest_outer = \
596 "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>" \
597 "<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>%s" \
598 "</assembly>"
563 if enable_uac == 'true': 599 if enable_uac == 'true':
564 execution_level = self._Setting(('VCLinkerTool', 'UACExecutionLevel'), 600 execution_level = self._Setting(('VCLinkerTool', 'UACExecutionLevel'),
565 config, default='0') 601 config, default='0')
566 execution_level_map = { 602 execution_level_map = {
567 '0': 'asInvoker', 603 '0': 'asInvoker',
568 '1': 'highestAvailable', 604 '1': 'highestAvailable',
569 '2': 'requireAdministrator' 605 '2': 'requireAdministrator'
570 } 606 }
571 607
572 ui_access = self._Setting(('VCLinkerTool', 'UACUIAccess'), config, 608 ui_access = self._Setting(('VCLinkerTool', 'UACUIAccess'), config,
573 default='false') 609 default='false')
574 flags.append('''/MANIFESTUAC:"level='%s' uiAccess='%s'"''' % 610
575 (execution_level_map[execution_level], ui_access)) 611 inner = '''
612 <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
613 <security>
614 <requestedPrivileges>
615 <requestedExecutionLevel level='%s' uiAccess='%s' />
616 </requestedPrivileges>
617 </security>
618 </trustInfo>''' % (execution_level_map[execution_level], ui_access)
576 else: 619 else:
577 flags.append('/MANIFESTUAC:NO') 620 inner = ''
621
622 generated_manifest_contents = generated_manifest_outer % inner
623 generated_name = name + '.generated.manifest'
624 # Need to join with the build_dir here as we're writing it during
625 # generation time, but we return the un-joined version because the build
626 # will occur in that directory. We only write the file if the contents
627 # have changed so that simply regenerating the project files doesn't
628 # cause a relink.
629 _WriteIfChanged(open_output,
630 os.path.join(build_dir, generated_name),
631 generated_manifest_contents)
632 manifest_files = [generated_name]
578 633
579 if allow_isolation: 634 if allow_isolation:
580 flags.append('/ALLOWISOLATION') 635 flags.append('/ALLOWISOLATION')
581 636
582 manifest_files = [output_name]
583 manifest_files += self._GetAdditionalManifestFiles(config, 637 manifest_files += self._GetAdditionalManifestFiles(config,
584 gyp_to_build_path) 638 gyp_to_build_path)
585 return flags, manifest_files 639 return flags, output_name, manifest_files
586 640
587 def _GetAdditionalManifestFiles(self, config, gyp_to_build_path): 641 def _GetAdditionalManifestFiles(self, config, gyp_to_build_path):
588 """Gets additional manifest files that are added to the default one 642 """Gets additional manifest files that are added to the default one
589 generated by the linker.""" 643 generated by the linker."""
590 files = self._Setting(('VCManifestTool', 'AdditionalManifestFiles'), config, 644 files = self._Setting(('VCManifestTool', 'AdditionalManifestFiles'), config,
591 default=[]) 645 default=[])
592 if isinstance(files, str): 646 if isinstance(files, str):
593 files = files.split(';') 647 files = files.split(';')
594 return [os.path.normpath( 648 return [os.path.normpath(
595 gyp_to_build_path(self.ConvertVSMacros(f, config=config))) 649 gyp_to_build_path(self.ConvertVSMacros(f, config=config)))
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
903 957
904 # To determine processor word size on Windows, in addition to checking 958 # To determine processor word size on Windows, in addition to checking
905 # PROCESSOR_ARCHITECTURE (which reflects the word size of the current 959 # PROCESSOR_ARCHITECTURE (which reflects the word size of the current
906 # process), it is also necessary to check PROCESSOR_ARCHITEW6432 (which 960 # process), it is also necessary to check PROCESSOR_ARCHITEW6432 (which
907 # contains the actual word size of the system when running thru WOW64). 961 # contains the actual word size of the system when running thru WOW64).
908 if ('64' in os.environ.get('PROCESSOR_ARCHITECTURE', '') or 962 if ('64' in os.environ.get('PROCESSOR_ARCHITECTURE', '') or
909 '64' in os.environ.get('PROCESSOR_ARCHITEW6432', '')): 963 '64' in os.environ.get('PROCESSOR_ARCHITEW6432', '')):
910 default_variables['MSVS_OS_BITS'] = 64 964 default_variables['MSVS_OS_BITS'] = 64
911 else: 965 else:
912 default_variables['MSVS_OS_BITS'] = 32 966 default_variables['MSVS_OS_BITS'] = 32
OLDNEW
« no previous file with comments | « pylib/gyp/generator/ninja.py ('k') | pylib/gyp/win_tool.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698