2016-03-12 02:00:02 +03:00
|
|
|
#!/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
|
|
|
|
|
2018-09-07 01:15:19 +03:00
|
|
|
SDK_RELEASE = "10.0.17134.0"
|
2017-11-02 18:10:39 +03:00
|
|
|
|
|
|
|
PATTERNS = [
|
|
|
|
{
|
|
|
|
"srcdir": "%(vs_path)s/DIA SDK",
|
|
|
|
"dstdir": "DIA SDK",
|
|
|
|
"files": [
|
|
|
|
{
|
|
|
|
"pattern": "bin/**",
|
|
|
|
"ignore": ("bin/arm/**",),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"pattern": "idl/**",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"pattern": "include/**",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"pattern": "lib/**",
|
|
|
|
"ignore": ("lib/arm/**",),
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
{
|
2019-01-28 22:29:56 +03:00
|
|
|
"srcdir": "%(vs_path)s/VC/Tools/MSVC/14.16.27023",
|
2017-11-02 18:10:39 +03:00
|
|
|
"dstdir": "VC",
|
|
|
|
"files": [
|
|
|
|
# ATL is needed by Breakpad.
|
|
|
|
{
|
|
|
|
"pattern": "atlmfc/include/**",
|
|
|
|
},
|
|
|
|
{
|
2019-01-28 22:29:56 +03:00
|
|
|
"pattern": "atlmfc/lib/arm64/atls.*",
|
2017-11-02 18:10:39 +03:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"pattern": "atlmfc/lib/x64/atls.*",
|
|
|
|
},
|
2019-01-28 22:29:56 +03:00
|
|
|
{
|
|
|
|
"pattern": "atlmfc/lib/x86/atls.*",
|
|
|
|
},
|
|
|
|
# ARM64 PGO-instrumented builds require ARM64 pgort140.dll.
|
|
|
|
{
|
|
|
|
"pattern": "bin/arm64/pgort140.dll",
|
|
|
|
},
|
2017-11-02 18:10:39 +03:00
|
|
|
{
|
|
|
|
"pattern": "bin/Hostx64/**",
|
|
|
|
},
|
|
|
|
# 32-bit PGO-instrumented builds require 32-bit pgort140.dll.
|
|
|
|
{
|
|
|
|
"pattern": "bin/Hostx86/x86/pgort140.dll",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"pattern": "include/**",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"pattern": "lib/**",
|
|
|
|
"ignore": (
|
2019-01-28 22:29:56 +03:00
|
|
|
"lib/arm64/store/**",
|
2017-11-02 18:10:39 +03:00
|
|
|
"lib/onecore/**",
|
|
|
|
"lib/x64/store/**",
|
|
|
|
"lib/x86/store/**",
|
|
|
|
),
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
{
|
2019-01-28 22:29:56 +03:00
|
|
|
"srcdir": "%(vs_path)s/VC/Redist/MSVC/14.16.27012",
|
2017-11-02 18:10:39 +03:00
|
|
|
"dstdir": "VC/redist",
|
|
|
|
"files": [
|
2019-01-28 22:29:56 +03:00
|
|
|
{
|
|
|
|
"pattern": "arm64/Microsoft.VC141.CRT/**",
|
|
|
|
},
|
2017-11-02 18:10:39 +03:00
|
|
|
{
|
|
|
|
"pattern": "x64/Microsoft.VC141.CRT/**",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"pattern": "x86/Microsoft.VC141.CRT/**",
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"srcdir": "%(sdk_path)s",
|
|
|
|
"dstdir": "SDK",
|
|
|
|
"files": [
|
|
|
|
{
|
|
|
|
"pattern": "bin/%s/x64/**" % SDK_RELEASE,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"pattern": "Include/%s/**" % SDK_RELEASE,
|
|
|
|
},
|
2019-01-28 22:29:56 +03:00
|
|
|
{
|
|
|
|
"pattern": "Lib/%s/ucrt/arm64/**" % SDK_RELEASE,
|
|
|
|
},
|
2017-11-02 18:10:39 +03:00
|
|
|
{
|
|
|
|
"pattern": "Lib/%s/ucrt/x64/**" % SDK_RELEASE,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"pattern": "Lib/%s/ucrt/x86/**" % SDK_RELEASE,
|
|
|
|
},
|
2019-01-28 22:29:56 +03:00
|
|
|
{
|
|
|
|
"pattern": "Lib/%s/um/arm64/**" % SDK_RELEASE,
|
|
|
|
},
|
2017-11-02 18:10:39 +03:00
|
|
|
{
|
|
|
|
"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/**",
|
|
|
|
},
|
|
|
|
],
|
2016-03-12 02:00:02 +03:00
|
|
|
},
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
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?"
|
|
|
|
)
|
|
|
|
|
2017-11-02 18:10:39 +03:00
|
|
|
vs_path = os.path.join(pf, "Microsoft Visual Studio", "2017", "Community")
|
2016-03-12 02:00:02 +03:00
|
|
|
if not os.path.exists(vs_path):
|
2017-11-02 18:10:39 +03:00
|
|
|
raise Exception(
|
|
|
|
"%s does not exist; Visual Studio 2017 not installed?" % vs_path
|
|
|
|
)
|
2016-03-12 02:00:02 +03:00
|
|
|
|
|
|
|
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)
|
|
|
|
|
2017-11-02 18:10:39 +03:00
|
|
|
sdk_fullver_path = os.path.join(sdk_path, "Include", SDK_RELEASE)
|
|
|
|
if not os.path.exists(sdk_fullver_path):
|
|
|
|
raise Exception(
|
|
|
|
"%s does not exist; Wrong SDK version installed?" % sdk_fullver_path
|
|
|
|
)
|
|
|
|
|
2016-03-12 02:00:02 +03:00
|
|
|
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()
|
|
|
|
|
2017-11-02 18:10:39 +03:00
|
|
|
for entry in PATTERNS:
|
|
|
|
fullpath = entry["srcdir"] % {
|
|
|
|
"vs_path": vs_path,
|
|
|
|
"sdk_path": sdk_path,
|
|
|
|
}
|
|
|
|
for pattern in entry["files"]:
|
|
|
|
finder = FileFinder(fullpath, ignore=pattern.get("ignore", []))
|
|
|
|
for p, f in finder.find(pattern["pattern"]):
|
|
|
|
dstpath = "%s/%s" % (entry["dstdir"], p)
|
|
|
|
yield dstpath.encode("utf-8"), f
|
2016-03-12 02:00:02 +03:00
|
|
|
|
2017-11-02 20:29:27 +03:00
|
|
|
|
2016-03-12 02:00:02 +03:00
|
|
|
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."""
|
2017-10-07 17:45:22 +03:00
|
|
|
if isinstance(prefix, unicode): # noqa Special case for Python 2
|
2016-03-12 02:00:02 +03:00
|
|
|
prefix = prefix.encode("utf-8")
|
|
|
|
|
2019-02-27 04:26:46 +03:00
|
|
|
with JarWriter(file=zip_path, compress_level=5) as zip:
|
2016-03-12 02:00:02 +03:00
|
|
|
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:
|
2016-04-22 21:37:14 +03:00
|
|
|
print("usage: %s create-zip <path-prefix>" % sys.argv[0])
|
2016-03-12 02:00:02 +03:00
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
assert sys.argv[1] == "create-zip"
|
2016-04-22 21:37:14 +03:00
|
|
|
prefix = os.path.basename(sys.argv[2])
|
|
|
|
destzip = "%s.zip" % sys.argv[2]
|
|
|
|
write_zip(destzip, prefix=prefix)
|
2016-03-12 02:00:02 +03:00
|
|
|
|
|
|
|
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())
|