| Index: win_toolchain/package_from_installed.py
|
| diff --git a/win_toolchain/package_from_installed.py b/win_toolchain/package_from_installed.py
|
| index 2762201284115e82e17d5d8457fcb508df7e2b90..19d3e706c1b4925c349464c7b138de2f5008a271 100644
|
| --- a/win_toolchain/package_from_installed.py
|
| +++ b/win_toolchain/package_from_installed.py
|
| @@ -21,7 +21,9 @@ useful as the resulting zip can't be redistributed, and most will presumably
|
| have a Pro license anyway).
|
| """
|
|
|
| +import optparse
|
| import os
|
| +import platform
|
| import shutil
|
| import sys
|
| import tempfile
|
| @@ -31,6 +33,7 @@ import get_toolchain_if_necessary
|
|
|
|
|
| VS_VERSION = None
|
| +WIN_VERSION = None
|
|
|
|
|
| def BuildFileList():
|
| @@ -112,24 +115,24 @@ def BuildFileList():
|
| combined = os.path.normpath(os.path.join(root, f))
|
| # Some of the files in this directory are exceedingly long (and exceed
|
| #_MAX_PATH for any moderately long root), so exclude them. We don't need
|
| - # them anyway.
|
| + # them anyway. Exclude the Windows Performance Toolkit just to save space.
|
| tail = combined[len(sdk_path) + 1:]
|
| - if tail.startswith('References\\'):
|
| + if (tail.startswith('References\\') or
|
| + tail.startswith('Windows Performance Toolkit\\')):
|
| continue
|
| + if VS_VERSION == '2015':
|
| + # There may be many Include\Lib\Source directories for many different
|
| + # versions of Windows and packaging them all wastes ~450 MB
|
| + # (uncompressed) per version and wastes time. Only copy the specified
|
| + # version.
|
| + if (tail.startswith('Include\\') or tail.startswith('Lib\\') or
|
| + tail.startswith('Source\\')):
|
| + if tail.count(WIN_VERSION) == 0:
|
| + continue
|
| to = os.path.join('win_sdk', tail)
|
| result.append((combined, to))
|
|
|
| if VS_VERSION == '2015':
|
| - for ucrt_path in (
|
| - (r'C:\Program Files (x86)\Windows Kits\10\Include', 'Include'),
|
| - (r'C:\Program Files (x86)\Windows Kits\10\Lib', 'Lib'),
|
| - (r'C:\Program Files (x86)\Windows Kits\10\Source', 'Source')):
|
| - src, target = ucrt_path
|
| - for root, _, files in os.walk(src):
|
| - for f in files:
|
| - combined = os.path.normpath(os.path.join(root, f))
|
| - to = os.path.join('ucrt', target, combined[len(src) + 1:])
|
| - result.append((combined, to))
|
|
|
| system_crt_files = [
|
| 'api-ms-win-core-file-l1-2-0.dll',
|
| @@ -158,15 +161,21 @@ def BuildFileList():
|
| 'ucrtbase.dll',
|
| 'ucrtbased.dll',
|
| ]
|
| + bitness = platform.architecture()[0]
|
| + # When running 64-bit python the x64 DLLs will be in System32
|
| + x64_path = 'System32' if bitness == '64bit' else 'Sysnative'
|
| + x64_path = os.path.join(r'C:\Windows', x64_path)
|
| for system_crt_file in system_crt_files:
|
| result.append((os.path.join(r'C:\Windows\SysWOW64', system_crt_file),
|
| os.path.join('sys32', system_crt_file)))
|
| - result.append((os.path.join(r'C:\Windows\Sysnative', system_crt_file),
|
| + result.append((os.path.join(x64_path, system_crt_file),
|
| os.path.join('sys64', system_crt_file)))
|
|
|
| - # Generically drop all arm stuff that we don't need.
|
| + # Generically drop all arm stuff that we don't need, and
|
| + # drop .msi files because we don't need installers.
|
| return [(f, t) for f, t in result if 'arm\\' not in f.lower() and
|
| - 'arm64\\' not in f.lower()]
|
| + 'arm64\\' not in f.lower() and
|
| + not f.lower().endswith('.msi')]
|
|
|
|
|
| def GenerateSetEnvCmd(target_dir):
|
| @@ -181,12 +190,13 @@ def GenerateSetEnvCmd(target_dir):
|
| ':: Generated by win_toolchain\\package_from_installed.py.\n'
|
| # Common to x86 and x64
|
| 'set PATH=%~dp0..\\..\\Common7\\IDE;%PATH%\n'
|
| - 'set INCLUDE=%~dp0..\\..\\win_sdk\\Include\\10.0.10240.0\\um;'
|
| - '%~dp0..\\..\\win_sdk\\Include\\10.0.10240.0\\shared;'
|
| - '%~dp0..\\..\\win_sdk\\Include\\10.0.10240.0\\winrt;'
|
| + 'set INCLUDE=%~dp0..\\..\\win_sdk\\Include\\WINVERSION\\um;'
|
| + '%~dp0..\\..\\win_sdk\\Include\\WINVERSION\\shared;'
|
| + '%~dp0..\\..\\win_sdk\\Include\\WINVERSION\\winrt;'
|
| + '%~dp0..\\..\\win_sdk\\Include\\WINVERSION\\ucrt;' # VS 2015
|
| '%~dp0..\\..\\VC\\include;'
|
| '%~dp0..\\..\\VC\\atlmfc\\include\n'
|
| - 'if "%1"=="/x64" goto x64\n')
|
| + 'if "%1"=="/x64" goto x64\n'.replace('WINVERSION', WIN_VERSION))
|
|
|
| # x86. Always use amd64_x86 cross, not x86 on x86.
|
| f.write('set PATH=%~dp0..\\..\\win_sdk\\bin\\x86;'
|
| @@ -194,9 +204,10 @@ def GenerateSetEnvCmd(target_dir):
|
| '%~dp0..\\..\\VC\\bin\\amd64;' # Needed for mspdb1x0.dll.
|
| '%PATH%\n')
|
| f.write('set LIB=%~dp0..\\..\\VC\\lib;'
|
| - '%~dp0..\\..\\win_sdk\\Lib\\10.0.10240.0\\um\\x86;'
|
| + '%~dp0..\\..\\win_sdk\\Lib\\WINVERSION\\um\\x86;'
|
| + '%~dp0..\\..\\win_sdk\\Lib\\WINVERSION\\ucrt\\x86;' # VS 2015
|
| '%~dp0..\\..\\VC\\atlmfc\\lib\n'
|
| - 'goto :EOF\n')
|
| + 'goto :EOF\n'.replace('WINVERSION', WIN_VERSION))
|
|
|
| # x64.
|
| f.write(':x64\n'
|
| @@ -204,8 +215,10 @@ def GenerateSetEnvCmd(target_dir):
|
| '%~dp0..\\..\\VC\\bin\\amd64;'
|
| '%PATH%\n')
|
| f.write('set LIB=%~dp0..\\..\\VC\\lib\\amd64;'
|
| - '%~dp0..\\..\\win_sdk\\Lib\\10.0.10240.0\\um\\x64;'
|
| - '%~dp0..\\..\\VC\\atlmfc\\lib\\amd64\n')
|
| + '%~dp0..\\..\\win_sdk\\Lib\\WINVERSION\\um\\x64;'
|
| + '%~dp0..\\..\\win_sdk\\Lib\\WINVERSION\\ucrt\\x64;' # VS 2015
|
| + '%~dp0..\\..\\VC\\atlmfc\\lib\\amd64\n'
|
| + .replace('WINVERSION', WIN_VERSION))
|
|
|
|
|
| def AddEnvSetup(files):
|
| @@ -246,14 +259,27 @@ def RenameToSha1(output):
|
|
|
|
|
| def main():
|
| - if len(sys.argv) != 2 or sys.argv[1] not in ('2013', '2015'):
|
| - print 'Usage: package_from_installed.py 2013|2015'
|
| + usage = 'usage: %prog [options] 2013|2015'
|
| + parser = optparse.OptionParser(usage)
|
| + parser.add_option('-w', '--winver', action='store', type='string',
|
| + dest='winver', default='10.0.10586.0',
|
| + help='Windows SDK version, such as 10.0.10586.0')
|
| + parser.add_option('-d', '--dryrun', action='store_true', dest='dryrun',
|
| + default=False,
|
| + help='scan for file existence and prints statistics')
|
| + (options, args) = parser.parse_args()
|
| +
|
| + if len(args) != 1 or args[0] not in ('2013', '2015'):
|
| + print 'Must specify 2013 or 2015'
|
| + parser.print_help();
|
| return 1
|
|
|
| global VS_VERSION
|
| - VS_VERSION = sys.argv[1]
|
| + VS_VERSION = args[0]
|
| + global WIN_VERSION
|
| + WIN_VERSION = options.winver
|
|
|
| - print 'Building file list...'
|
| + print 'Building file list for VS %s Windows %s...' % (VS_VERSION, WIN_VERSION)
|
| files = BuildFileList()
|
|
|
| AddEnvSetup(files)
|
| @@ -267,12 +293,33 @@ def main():
|
| if os.path.exists(output):
|
| os.unlink(output)
|
| count = 0
|
| + version_match_count = 0
|
| + total_size = 0
|
| + missing_files = False
|
| with zipfile.ZipFile(output, 'w', zipfile.ZIP_DEFLATED, True) as zf:
|
| for disk_name, archive_name in files:
|
| sys.stdout.write('\r%d/%d ...%s' % (count, len(files), disk_name[-40:]))
|
| sys.stdout.flush()
|
| count += 1
|
| - zf.write(disk_name, archive_name)
|
| + if disk_name.count(WIN_VERSION) > 0:
|
| + version_match_count += 1
|
| + if os.path.exists(disk_name):
|
| + if options.dryrun:
|
| + total_size += os.path.getsize(disk_name)
|
| + else:
|
| + zf.write(disk_name, archive_name)
|
| + else:
|
| + missing_files = True
|
| + sys.stdout.write('\r%s does not exist.\n\n' % disk_name)
|
| + sys.stdout.flush()
|
| + if options.dryrun:
|
| + sys.stdout.write('\r%1.3f GB of data in %d files, %d files for %s.%s\n' %
|
| + (total_size / 1e9, count, version_match_count, WIN_VERSION, ' '*50))
|
| + return 0
|
| + if missing_files:
|
| + raise 'One or more files were missing - aborting'
|
| + if version_match_count == 0:
|
| + raise 'No files found that match the specified winversion'
|
| sys.stdout.write('\rWrote to %s.%s\n' % (output, ' '*50))
|
| sys.stdout.flush()
|
|
|
|
|