Index: pylib/gyp/win_tool.py |
diff --git a/pylib/gyp/win_tool.py b/pylib/gyp/win_tool.py |
index 7f3b0a5413fb25eaebfc590489a5a4c2f4116efc..1634ff93ddc6a92b1cc6ef10955123e0ab412b18 100755 |
--- a/pylib/gyp/win_tool.py |
+++ b/pylib/gyp/win_tool.py |
@@ -13,6 +13,7 @@ import os |
import re |
import shutil |
import subprocess |
+import string |
import sys |
BASE_DIR = os.path.dirname(os.path.abspath(__file__)) |
@@ -116,6 +117,82 @@ class WinTool(object): |
print line |
return link.returncode |
+ def ExecLinkWithManifests(self, arch, embed_manifest, out, ldcmd, resname, |
+ mt, rc, intermediate_manifest, *manifests): |
+ """A wrapper for handling creating a manifest resource and then executing |
+ a link command.""" |
+ # The 'normal' way to do manifests is to have link generate a manifest |
+ # based on gathering dependencies from the object files, then merge that |
+ # manifest with other manifests supplied as sources, convert the merged |
+ # manifest to a resource, and then *relink*, including the compiled |
+ # version of the manifest resource. This breaks incremental linking, and |
+ # is generally overly complicated. Instead, we merge all the manifests |
+ # provided (along with one that includes what would normally be in the |
+ # linker-generated one, see msvs_emulation.py), and include that into the |
+ # first and only link. We still tell link to generate a manifest, but we |
+ # only use that to assert that our simpler process did not miss anything. |
+ variables = { |
+ 'python': sys.executable, |
+ 'arch': arch, |
+ 'out': out, |
+ 'ldcmd': ldcmd, |
+ 'resname': resname, |
+ 'mt': mt, |
+ 'rc': rc, |
+ 'intermediate_manifest': intermediate_manifest, |
+ 'manifests': ' '.join(manifests), |
+ } |
+ add_to_ld = '' |
+ if manifests: |
+ subprocess.check_call( |
+ '%(python)s gyp-win-tool manifest-wrapper %(arch)s %(mt)s -nologo ' |
+ '-manifest %(manifests)s -out:%(out)s.manifest' % variables) |
+ if embed_manifest == 'True': |
+ subprocess.check_call( |
+ '%(python)s gyp-win-tool manifest-to-rc %(arch)s %(out)s.manifest' |
+ ' %(out)s.manifest.rc %(resname)s' % variables) |
+ subprocess.check_call( |
+ '%(python)s gyp-win-tool rc-wrapper %(arch)s %(rc)s ' |
+ '%(out)s.manifest.rc' % variables) |
+ add_to_ld = ' %(out)s.manifest.res' % variables |
+ subprocess.check_call(ldcmd + add_to_ld) |
+ |
+ # Run mt.exe on the theoretically complete manifest we generated, merging |
+ # it with the one the linker generated to confirm that the linker |
+ # generated one does not add anything. This is strictly unnecessary for |
+ # correctness, it's only to verify that e.g. /MANIFESTDEPENDENCY was not |
+ # used in a #pragma comment. |
+ if manifests: |
+ # Merge the intermediate one with ours to .assert.manifest, then check |
+ # that .assert.manifest is identical to ours. |
+ subprocess.check_call( |
+ '%(python)s gyp-win-tool manifest-wrapper %(arch)s %(mt)s -nologo ' |
+ '-manifest %(out)s.manifest %(intermediate_manifest)s ' |
+ '-out:%(out)s.assert.manifest' % variables) |
+ assert_manifest = '%(out)s.assert.manifest' % variables |
+ our_manifest = '%(out)s.manifest' % variables |
+ # Load and normalize the manifests. mt.exe sometimes removes whitespace, |
+ # and sometimes doesn't unfortunately. |
+ with open(our_manifest, 'rb') as our_f: |
+ with open(assert_manifest, 'rb') as assert_f: |
+ our_data = our_f.read().translate(None, string.whitespace) |
+ assert_data = assert_f.read().translate(None, string.whitespace) |
+ if our_data != assert_data: |
+ os.unlink(out) |
+ def dump(filename): |
+ sys.stderr.write('%s\n-----\n' % filename) |
+ with open(filename, 'rb') as f: |
+ sys.stderr.write(f.read() + '\n-----\n') |
+ dump(intermediate_manifest) |
+ dump(our_manifest) |
+ dump(assert_manifest) |
+ sys.stderr.write( |
+ 'Linker generated manifest "%s" added to final manifest "%s" ' |
+ '(result in "%s"). ' |
+ 'Were /MANIFEST switches used in #pragma statements? ' % ( |
+ intermediate_manifest, our_manifest, assert_manifest)) |
+ return 1 |
+ |
def ExecManifestWrapper(self, arch, *args): |
"""Run manifest tool with environment set. Strip out undesirable warning |
(some XML blocks are recognized by the OS loader, but not the manifest |