1448a52dfe9691d2b24f152b950b773c59e8b0ee6scottmg@chromium.org#!/usr/bin/env python
2448a52dfe9691d2b24f152b950b773c59e8b0ee6scottmg@chromium.org
3448a52dfe9691d2b24f152b950b773c59e8b0ee6scottmg@chromium.org# Copyright (c) 2012 Google Inc. All rights reserved.
4448a52dfe9691d2b24f152b950b773c59e8b0ee6scottmg@chromium.org# Use of this source code is governed by a BSD-style license that can be
5448a52dfe9691d2b24f152b950b773c59e8b0ee6scottmg@chromium.org# found in the LICENSE file.
6448a52dfe9691d2b24f152b950b773c59e8b0ee6scottmg@chromium.org
7448a52dfe9691d2b24f152b950b773c59e8b0ee6scottmg@chromium.org"""
8448a52dfe9691d2b24f152b950b773c59e8b0ee6scottmg@chromium.orgMake sure we generate a manifest file when linking binaries, including
9448a52dfe9691d2b24f152b950b773c59e8b0ee6scottmg@chromium.orghandling AdditionalManifestFiles.
10448a52dfe9691d2b24f152b950b773c59e8b0ee6scottmg@chromium.org"""
11448a52dfe9691d2b24f152b950b773c59e8b0ee6scottmg@chromium.org
12448a52dfe9691d2b24f152b950b773c59e8b0ee6scottmg@chromium.orgimport TestGyp
13448a52dfe9691d2b24f152b950b773c59e8b0ee6scottmg@chromium.org
14448a52dfe9691d2b24f152b950b773c59e8b0ee6scottmg@chromium.orgimport sys
15448a52dfe9691d2b24f152b950b773c59e8b0ee6scottmg@chromium.org
16448a52dfe9691d2b24f152b950b773c59e8b0ee6scottmg@chromium.orgif sys.platform == 'win32':
177509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org  import pywintypes
187509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org  import win32api
197509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org  import winerror
207509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org
217509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org  RT_MANIFEST = 24
227509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org
237509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org  class LoadLibrary(object):
247509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org    """Context manager for loading and releasing binaries in Windows.
257509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org    Yields the handle of the binary loaded."""
267509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org    def __init__(self, path):
277509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org      self._path = path
287509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org      self._handle = None
297509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org
307509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org    def __enter__(self):
317509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org      self._handle = win32api.LoadLibrary(self._path)
327509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org      return self._handle
337509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org
347509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org    def __exit__(self, type, value, traceback):
357509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org      win32api.FreeLibrary(self._handle)
367509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org
377509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org  def extract_manifest(path, resource_name):
387509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org    """Reads manifest from |path| and returns it as a string.
397509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org    Returns None is there is no such manifest."""
407509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org    with LoadLibrary(path) as handle:
417509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org      try:
427509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org        return win32api.LoadResource(handle, RT_MANIFEST, resource_name)
437509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org      except pywintypes.error as error:
447509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org        if error.args[0] == winerror.ERROR_RESOURCE_DATA_NOT_FOUND:
457509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org          return None
467509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org        else:
477509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org          raise
487509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org
49448a52dfe9691d2b24f152b950b773c59e8b0ee6scottmg@chromium.org  test = TestGyp.TestGyp(formats=['msvs', 'ninja'])
50448a52dfe9691d2b24f152b950b773c59e8b0ee6scottmg@chromium.org
51448a52dfe9691d2b24f152b950b773c59e8b0ee6scottmg@chromium.org  CHDIR = 'linker-flags'
52448a52dfe9691d2b24f152b950b773c59e8b0ee6scottmg@chromium.org  test.run_gyp('generate-manifest.gyp', chdir=CHDIR)
53448a52dfe9691d2b24f152b950b773c59e8b0ee6scottmg@chromium.org  test.build('generate-manifest.gyp', test.ALL, chdir=CHDIR)
54448a52dfe9691d2b24f152b950b773c59e8b0ee6scottmg@chromium.org
5578d5366f3040ddfd2fcdcde6e2e4dde87c102850scottmg@chromium.org  # Make sure that generation of .generated.manifest does not cause a relink.
5678d5366f3040ddfd2fcdcde6e2e4dde87c102850scottmg@chromium.org  test.run_gyp('generate-manifest.gyp', chdir=CHDIR)
5778d5366f3040ddfd2fcdcde6e2e4dde87c102850scottmg@chromium.org  test.up_to_date('generate-manifest.gyp', test.ALL, chdir=CHDIR)
5878d5366f3040ddfd2fcdcde6e2e4dde87c102850scottmg@chromium.org
597509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org  def test_manifest(filename, generate_manifest, embedded_manifest,
607509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                    extra_manifest):
617509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org    exe_file = test.built_file_path(filename, chdir=CHDIR)
627509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org    if not generate_manifest:
637509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org      test.must_not_exist(exe_file + '.manifest')
647509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org      manifest = extract_manifest(exe_file, 1)
657509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org      test.fail_test(manifest)
667509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org      return
677509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org    if embedded_manifest:
687509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org      manifest = extract_manifest(exe_file, 1)
697509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org      test.fail_test(not manifest)
707509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org    else:
717509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org      test.must_exist(exe_file + '.manifest')
727509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org      manifest = test.read(exe_file + '.manifest')
737509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org      test.fail_test(not manifest)
747509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org      test.fail_test(extract_manifest(exe_file, 1))
757509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org    if generate_manifest:
767509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org      test.must_contain_any_line(manifest, 'requestedExecutionLevel')
777509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org    if extra_manifest:
787509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org      test.must_contain_any_line(manifest,
797509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                                 '35138b9a-5d96-4fbd-8e2d-a2440225f93a')
807509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org      test.must_contain_any_line(manifest,
817509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                                 'e2011457-1546-43c5-a5fe-008deee3d3f0')
827509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org
837509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org  test_manifest('test_generate_manifest_true.exe',
847509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                generate_manifest=True,
857509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                embedded_manifest=False,
867509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                extra_manifest=False)
877509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org  test_manifest('test_generate_manifest_false.exe',
887509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                generate_manifest=False,
897509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                embedded_manifest=False,
907509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                extra_manifest=False)
917509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org  test_manifest('test_generate_manifest_default.exe',
927509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                generate_manifest=True,
937509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                embedded_manifest=False,
947509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                extra_manifest=False)
957509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org  test_manifest('test_generate_manifest_true_as_embedded.exe',
967509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                generate_manifest=True,
977509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                embedded_manifest=True,
987509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                extra_manifest=False)
997509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org  test_manifest('test_generate_manifest_false_as_embedded.exe',
1007509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                generate_manifest=False,
1017509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                embedded_manifest=True,
1027509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                extra_manifest=False)
1037509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org  test_manifest('test_generate_manifest_default_as_embedded.exe',
1047509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                generate_manifest=True,
1057509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                embedded_manifest=True,
1067509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                extra_manifest=False)
1077509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org  test_manifest('test_generate_manifest_true_with_extra_manifest.exe',
1087509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                generate_manifest=True,
1097509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                embedded_manifest=False,
1107509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                extra_manifest=True)
1117509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org  test_manifest('test_generate_manifest_false_with_extra_manifest.exe',
1127509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                generate_manifest=False,
1137509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                embedded_manifest=False,
1147509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                extra_manifest=True)
1157509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org  test_manifest('test_generate_manifest_true_with_extra_manifest_list.exe',
1167509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                generate_manifest=True,
1177509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                embedded_manifest=False,
1187509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                extra_manifest=True)
1197509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org  test_manifest('test_generate_manifest_false_with_extra_manifest_list.exe',
1207509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                generate_manifest=False,
1217509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                embedded_manifest=False,
1227509f5f9cd770e1ae1a4d1b720dda59ca60c5524yukawa@chromium.org                extra_manifest=True)
12367e1e1f46d9b534543c4da6c27988aca0ef5c475scottmg@chromium.org  test_manifest('test_generate_manifest_default_embed_default.exe',
12467e1e1f46d9b534543c4da6c27988aca0ef5c475scottmg@chromium.org                generate_manifest=True,
12567e1e1f46d9b534543c4da6c27988aca0ef5c475scottmg@chromium.org                embedded_manifest=True,
12667e1e1f46d9b534543c4da6c27988aca0ef5c475scottmg@chromium.org                extra_manifest=False)
127448a52dfe9691d2b24f152b950b773c59e8b0ee6scottmg@chromium.org  test.pass_test()
128