123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- #!/usr/bin/env python2.7
- # This Source Code Form is subject to the terms of the Mozilla Public
- # License, v. 2.0. If a copy of the MPL was not distributed with this
- # file, You can obtain one at http://mozilla.org/MPL/2.0/.
- # This script is used to create and manipulate archives containing
- # files necessary to build Firefox on Windows (referred to as the
- # "Windows toolchain").
- #
- # When updating behavior of this script, remember to update the docs
- # in ``build/docs/toolchains.rst``.
- from __future__ import absolute_import, unicode_literals
- import hashlib
- import os
- import sys
- from mozpack.files import (
- FileFinder,
- )
- from mozpack.mozjar import (
- JarWriter,
- )
- import mozpack.path as mozpath
- # mozpack.match patterns for files under "Microsoft Visual Studio 14.0".
- VS_PATTERNS = [
- {
- 'pattern': 'DIA SDK/bin/**',
- 'ignore': (
- 'DIA SDK/bin/arm/**',
- ),
- },
- {
- 'pattern': 'DIA SDK/idl/**',
- },
- {
- 'pattern': 'DIA SDK/include/**',
- },
- {
- 'pattern': 'DIA SDK/lib/**',
- 'ignore': (
- 'DIA SDK/lib/arm/**',
- ),
- },
- # ATL is needed by Breakpad.
- {
- 'pattern': 'VC/atlmfc/include/**',
- },
- {
- 'pattern': 'VC/atlmfc/lib/atls.*',
- },
- {
- 'pattern': 'VC/atlmfc/lib/amd64/atls.*',
- },
- {
- 'pattern': 'VC/bin/**',
- # We only care about compiling on amd64 for amd64 or x86 targets.
- 'ignore': (
- 'VC/bin/amd64_arm/**',
- 'VC/bin/arm/**',
- 'VC/bin/x86_arm/**',
- 'VC/bin/x86_amd64/**',
- ),
- },
- {
- 'pattern': 'VC/include/**',
- },
- {
- 'pattern': 'VC/lib/**',
- 'ignore': (
- 'VC/lib/arm/**',
- 'VC/lib/onecore/**',
- 'VC/lib/store/**',
- ),
- },
- {
- 'pattern': 'VC/redist/x64/Microsoft.VC140.CRT/**',
- },
- {
- 'pattern': 'VC/redist/x86/Microsoft.VC140.CRT/**',
- },
- ]
- SDK_RELEASE = '10.0.14393.0'
- # Files from the Windows 10 SDK to install.
- SDK_PATTERNS = [
- {
- 'pattern': 'bin/x64/**',
- },
- {
- 'pattern': 'Include/%s/**' % SDK_RELEASE,
- },
- {
- 'pattern': 'Lib/%s/ucrt/x64/**' % SDK_RELEASE,
- },
- {
- 'pattern': 'Lib/%s/ucrt/x86/**' % SDK_RELEASE,
- },
- {
- 'pattern': 'Lib/%s/um/x64/**' % SDK_RELEASE,
- },
- {
- 'pattern': 'Lib/%s/um/x86/**' % SDK_RELEASE,
- },
- {
- 'pattern': 'Redist/D3D/**',
- },
- {
- 'pattern': 'Redist/ucrt/DLLs/x64/**',
- },
- {
- 'pattern': 'Redist/ucrt/DLLs/x86/**',
- },
- ]
- def find_vs_paths():
- """Resolve source locations of files.
- Returns a 2-tuple of (Visual Studio Path, SDK Path).
- """
- pf = os.environ.get('ProgramFiles(x86)')
- if not pf:
- raise Exception('No "ProgramFiles(x86)" environment variable. '
- 'Not running on 64-bit Windows?')
- vs_path = os.path.join(pf, 'Microsoft Visual Studio 14.0')
- if not os.path.exists(vs_path):
- raise Exception('%s does not exist; Visual Studio 2015 not installed?' %
- vs_path)
- sdk_path = os.path.join(pf, 'Windows Kits', '10')
- if not os.path.exists(sdk_path):
- raise Exception('%s does not exist; Windows 10 SDK not installed?' %
- sdk_path)
- return vs_path, sdk_path
- def resolve_files():
- """Resolve the files that constitute a standalone toolchain.
- This is a generator of (dest path, file) where the destination
- path is relative and the file instance is a BaseFile from mozpack.
- """
- vs_path, sdk_path = find_vs_paths()
- for entry in VS_PATTERNS:
- finder = FileFinder(vs_path, find_executables=False,
- ignore=entry.get('ignore', []))
- for p, f in finder.find(entry['pattern']):
- assert p.startswith(('VC/', 'DIA SDK/'))
- yield p.encode('utf-8'), f
- for entry in SDK_PATTERNS:
- finder = FileFinder(sdk_path, find_executables=False,
- ignore=entry.get('ignore', []))
- for p, f in finder.find(entry['pattern']):
- relpath = 'SDK/%s' % p
- yield relpath.encode('utf-8'), f
- def resolve_files_and_hash(manifest):
- """Resolve files and hash their data.
- This is a generator of 3-tuples of (relpath, data, mode).
- As data is read, the manifest is populated with metadata.
- Keys are set to the relative file path. Values are 2-tuples
- of (data length, sha-256).
- """
- assert manifest == {}
- for p, f in resolve_files():
- data = f.read()
- sha256 = hashlib.sha256()
- sha256.update(data)
- manifest[p] = (len(data), sha256.hexdigest())
- yield p, data, f.mode
- def format_manifest(manifest):
- """Return formatted SHA-256 manifests as a byte strings."""
- sha256_lines = []
- for path, (length, sha256) in sorted(manifest.items()):
- sha256_lines.append(b'%s\t%d\t%s' % (sha256, length, path))
- # Trailing newline.
- sha256_lines.append(b'')
- return b'\n'.join(sha256_lines)
- def write_zip(zip_path, prefix=None):
- """Write toolchain data to a zip file."""
- if isinstance(prefix, unicode):
- prefix = prefix.encode('utf-8')
- with JarWriter(file=zip_path, optimize=False, compress=5) as zip:
- manifest = {}
- for p, data, mode in resolve_files_and_hash(manifest):
- print(p)
- if prefix:
- p = mozpath.join(prefix, p)
- zip.add(p, data, mode=mode)
- sha256_manifest = format_manifest(manifest)
- sdk_path = b'SDK_VERSION'
- sha256_path = b'MANIFEST.SHA256'
- if prefix:
- sdk_path = mozpath.join(prefix, sdk_path)
- sha256_path = mozpath.join(prefix, sha256_path)
- zip.add(sdk_path, SDK_RELEASE.encode('utf-8'))
- zip.add(sha256_path, sha256_manifest)
- if __name__ == '__main__':
- if len(sys.argv) != 3:
- print('usage: %s create-zip <path-prefix>' % sys.argv[0])
- sys.exit(1)
- assert sys.argv[1] == 'create-zip'
- prefix = os.path.basename(sys.argv[2])
- destzip = '%s.zip' % sys.argv[2]
- write_zip(destzip, prefix=prefix)
- sha1 = hashlib.sha1()
- sha256 = hashlib.sha256()
- sha512 = hashlib.sha512()
- with open(destzip, 'rb') as fh:
- data = fh.read()
- sha1.update(data)
- sha256.update(data)
- sha512.update(data)
- print('Hashes of %s (size=%d)' % (destzip, len(data)))
- print('SHA-1: %s' % sha1.hexdigest())
- print('SHA-256: %s' % sha256.hexdigest())
- print('SHA-512: %s' % sha512.hexdigest())
|