# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""
From a system-installed copy of the toolchain, packages all the required bits
into a .zip file.

It assumes default install locations for tools, on the C: drive.

1. Start from a fresh Windows VM image.
2. Download the VS installer. Run the installer with these parameters:
    --add Microsoft.VisualStudio.Workload.NativeDesktop
    --add Microsoft.VisualStudio.Component.VC.ATLMFC
    --add Microsoft.VisualStudio.Component.VC.Tools.ARM64
    --add Microsoft.VisualStudio.Component.VC.MFC.ARM64
    --includeRecommended --passive
These are equivalent to selecting the Desktop development with C++ workload,
within that the Visual C++ MFC for x86 and x64 component, and then  Individual
Components-> Compilers, build tools, and runtimes-> Visual C++ compilers and
libraries for ARM64, and Individual Components-> SDKs, libraries, and
frameworks-> Visual C++ MFC for ARM64 (which also brings in ATL for ARM64).
3. Use Add or Remove Programs to find the Windows SDK installed with VS
and modify it to include the debuggers.
4. Run this script, which will build a <sha1>.zip, something like this:
  python package_from_installed.py 2017|2019 -w 10.0.17763.0|<SDK version>

Express is not yet supported by this script, but patches welcome (it's not too
useful as the resulting zip can't be redistributed, and most will presumably
have a Pro license anyway).
"""

from __future__ import print_function

import collections
import glob
import json
import optparse
import os
import platform
import shutil
import subprocess
import sys
import tempfile
import zipfile

import get_toolchain_if_necessary


VS_VERSION = None
WIN_VERSION = None
VC_TOOLS = None
SUPPORTED_VS_VERSIONS = ['2017', '2019']


def GetVSPath():
  # Use vswhere to find the VS installation. This will find prerelease
  # versions because -prerelease is specified. This assumes that only one
  # version is installed.
  command = (r'C:\Program Files (x86)\Microsoft Visual Studio\Installer'
             r'\vswhere.exe -prerelease')
  marker = 'installationPath: '
  output = subprocess.check_output(command, universal_newlines=True)
  for line in output.splitlines():
    if line.startswith(marker):
      return line[len(marker):]
  raise Exception('VS %s path not found in vswhere output' % (VS_VERSION))


def ExpandWildcards(root, sub_dir):
  # normpath is needed to change '/' to '\\' characters.
  path = os.path.normpath(os.path.join(root, sub_dir))
  matches = glob.glob(path)
  if len(matches) != 1:
    raise Exception('%s had %d matches - should be one' % (path, len(matches)))
  return matches[0]


def BuildRepackageFileList(src_dir):
  # Strip off a trailing slash if present
  if src_dir.endswith('\\'):
    src_dir = src_dir[:-1]

  # Ensure .\win_sdk\Debuggers exists and fail to repackage if it doesn't.
  debuggers_path = os.path.join(src_dir, 'win_sdk', 'Debuggers')
  if not os.path.exists(debuggers_path):
    raise Exception('Repacking failed. Missing %s.' % (debuggers_path))

  result = []
  for root, _, files in os.walk(src_dir):
    for f in files:
      final_from = os.path.normpath(os.path.join(root, f))
      dest = final_from[len(src_dir) + 1:]
      result.append((final_from, dest))
  return result


def BuildFileList(override_dir, include_arm):
  result = []

  # Subset of VS corresponding roughly to VC.
  paths = [
      'DIA SDK/bin',
      'DIA SDK/idl',
      'DIA SDK/include',
      'DIA SDK/lib',
      VC_TOOLS + '/atlmfc',
      VC_TOOLS + '/crt',
      'VC/redist',
  ]

  if override_dir:
    paths += [
        (os.path.join(override_dir, 'bin'), VC_TOOLS + '/bin'),
        (os.path.join(override_dir, 'include'), VC_TOOLS + '/include'),
        (os.path.join(override_dir, 'lib'), VC_TOOLS + '/lib'),
    ]
  else:
    paths += [
        VC_TOOLS + '/bin',
        VC_TOOLS + '/include',
        VC_TOOLS + '/lib',
    ]

  paths += [
      ('VC/redist/MSVC/14.*.*/x86/Microsoft.VC*.CRT', 'sys32'),
      ('VC/redist/MSVC/14.*.*/x86/Microsoft.VC*.CRT', 'win_sdk/bin/x86'),
      ('VC/redist/MSVC/14.*.*/debug_nonredist/x86/Microsoft.VC*.DebugCRT',
       'sys32'),
      ('VC/redist/MSVC/14.*.*/x64/Microsoft.VC*.CRT', 'sys64'),
      ('VC/redist/MSVC/14.*.*/x64/Microsoft.VC*.CRT', 'VC/bin/amd64_x86'),
      ('VC/redist/MSVC/14.*.*/x64/Microsoft.VC*.CRT', 'VC/bin/amd64'),
      ('VC/redist/MSVC/14.*.*/x64/Microsoft.VC*.CRT', 'win_sdk/bin/x64'),
      ('VC/redist/MSVC/14.*.*/debug_nonredist/x64/Microsoft.VC*.DebugCRT',
       'sys64'),
  ]
  if include_arm:
    paths += [
        ('VC/redist/MSVC/14.*.*/arm64/Microsoft.VC*.CRT', 'sysarm64'),
        ('VC/redist/MSVC/14.*.*/arm64/Microsoft.VC*.CRT', 'VC/bin/amd64_arm64'),
        ('VC/redist/MSVC/14.*.*/arm64/Microsoft.VC*.CRT', 'VC/bin/arm64'),
        ('VC/redist/MSVC/14.*.*/arm64/Microsoft.VC*.CRT', 'win_sdk/bin/arm64'),
        ('VC/redist/MSVC/14.*.*/debug_nonredist/arm64/Microsoft.VC*.DebugCRT',
         'sysarm64'),
    ]

  vs_path = GetVSPath()

  for path in paths:
    src = path[0] if isinstance(path, tuple) else path
    # Note that vs_path is ignored if src is an absolute path.
    combined = ExpandWildcards(vs_path, src)
    if not os.path.exists(combined):
      raise Exception('%s missing.' % combined)
    if not os.path.isdir(combined):
      raise Exception('%s not a directory.' % combined)
    for root, _, files in os.walk(combined):
      for f in files:
        # vctip.exe doesn't shutdown, leaving locks on directories. It's
        # optional so let's avoid this problem by not packaging it.
        # https://crbug.com/735226
        if f.lower() =='vctip.exe':
          continue
        final_from = os.path.normpath(os.path.join(root, f))
        if isinstance(path, tuple):
          assert final_from.startswith(combined)
          dest = final_from[len(combined) + 1:]
          result.append(
              (final_from, os.path.normpath(os.path.join(path[1], dest))))
        else:
          assert final_from.startswith(vs_path)
          dest = final_from[len(vs_path) + 1:]
          result.append((final_from, dest))

  sdk_path = r'C:\Program Files (x86)\Windows Kits\10'
  debuggers_path = os.path.join(sdk_path, 'Debuggers')
  if not os.path.exists(debuggers_path):
    raise Exception('Packaging failed. Missing %s.' % (debuggers_path))

  for root, _, files in os.walk(sdk_path):
    for f in files:
      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. Exclude/filter/skip others just to save space.
      tail = combined[len(sdk_path) + 1:]
      skip_dir = False
      for dir in ['References\\', 'Windows Performance Toolkit\\', 'Testing\\',
                  'App Certification Kit\\', 'Extension SDKs\\',
                  'Assessment and Deployment Kit\\']:
        if tail.startswith(dir):
          skip_dir = True
      if skip_dir:
        continue
      # There may be many Include\Lib\Source\bin 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. Note that the SDK version number started being part of the bin
      # path with 10.0.15063.0.
      if (tail.startswith('Include\\') or tail.startswith('Lib\\') or
          tail.startswith('Source\\') or tail.startswith('bin\\')):
        if tail.count(WIN_VERSION) == 0:
          continue
      to = os.path.join('win_sdk', tail)
      result.append((combined, to))

  # Copy the x86 ucrt DLLs to all directories with x86 binaries that are
  # added to the path by SetEnv.cmd, and to sys32. Starting with the 17763
  # SDK the ucrt files are in WIN_VERSION\ucrt instead of just ucrt.
  ucrt_dir = os.path.join(sdk_path, 'redist', WIN_VERSION, r'ucrt\dlls\x86')
  if not os.path.exists(ucrt_dir):
    ucrt_dir = os.path.join(sdk_path, r'redist\ucrt\dlls\x86')
  ucrt_paths = glob.glob(ucrt_dir + r'\*')
  assert(len(ucrt_paths) > 0)
  for ucrt_path in ucrt_paths:
    ucrt_file = os.path.split(ucrt_path)[1]
    for dest_dir in [ r'win_sdk\bin\x86', 'sys32' ]:
      result.append((ucrt_path, os.path.join(dest_dir, ucrt_file)))

  # Copy the x64 ucrt DLLs to all directories with x64 binaries that are
  # added to the path by SetEnv.cmd, and to sys64.
  ucrt_dir = os.path.join(sdk_path, 'redist', WIN_VERSION, r'ucrt\dlls\x64')
  if not os.path.exists(ucrt_dir):
    ucrt_dir = os.path.join(sdk_path, r'redist\ucrt\dlls\x64')
  ucrt_paths = glob.glob(ucrt_dir + r'\*')
  assert(len(ucrt_paths) > 0)
  for ucrt_path in ucrt_paths:
    ucrt_file = os.path.split(ucrt_path)[1]
    for dest_dir in [ r'VC\bin\amd64_x86', r'VC\bin\amd64',
                      r'win_sdk\bin\x64', 'sys64']:
      result.append((ucrt_path, os.path.join(dest_dir, ucrt_file)))

  system_crt_files = [
      # Needed to let debug binaries run.
      'ucrtbased.dll',
  ]
  cpu_pairs = [
    ('x86', 'sys32'),
    ('x64', 'sys64'),
  ]
  if include_arm:
    cpu_pairs += [
      ('arm64', 'sysarm64'),
    ]
  for system_crt_file in system_crt_files:
    for cpu_pair in cpu_pairs:
      target_cpu, dest_dir = cpu_pair
      src_path = os.path.join(sdk_path, 'bin', WIN_VERSION, target_cpu, 'ucrt')
      result.append((os.path.join(src_path, system_crt_file),
                     os.path.join(dest_dir, system_crt_file)))

  # Generically drop all arm stuff that we don't need, and
  # drop .msi files because we don't need installers and drop
  # samples since those are not used by any tools.
  def is_skippable(f):
    return ('arm\\' in f.lower() or
            (not include_arm and 'arm64\\' in f.lower()) or
            'samples\\' in f.lower() or
            f.lower().endswith(('.msi',
                                '.msm')))
  return [(f, t) for f, t in result if not is_skippable(f)]

def GenerateSetEnvCmd(target_dir):
  """Generate a batch file that gyp expects to exist to set up the compiler
  environment.

  This is normally generated by a full install of the SDK, but we
  do it here manually since we do not do a full install."""
  vc_tools_parts = VC_TOOLS.split('/')

  # All these paths are relative to the grandparent of the directory containing
  # SetEnv.cmd.
  include_dirs = [
    ['win_sdk', 'Include', WIN_VERSION, 'um'],
    ['win_sdk', 'Include', WIN_VERSION, 'shared'],
    ['win_sdk', 'Include', WIN_VERSION, 'winrt'],
  ]
  include_dirs.append(['win_sdk', 'Include', WIN_VERSION, 'ucrt'])
  include_dirs.extend([
    vc_tools_parts + ['include'],
    vc_tools_parts + ['atlmfc', 'include'],
  ])
  libpath_dirs = [
    vc_tools_parts + ['lib', 'x86', 'store', 'references'],
    ['win_sdk', 'UnionMetadata', WIN_VERSION],
  ]
  # Common to x86, x64, and arm64
  env = collections.OrderedDict([
    # Yuck: These have a trailing \ character. No good way to represent this in
    # an OS-independent way.
    ('VSINSTALLDIR', [['.\\']]),
    ('VCINSTALLDIR', [['VC\\']]),
    ('INCLUDE', include_dirs),
    ('LIBPATH', libpath_dirs),
  ])
  # x86. Always use amd64_x86 cross, not x86 on x86.
  env['VCToolsInstallDir'] = [vc_tools_parts[:]]
  # Yuck: This one ends in a slash as well.
  env['VCToolsInstallDir'][0][-1] += '\\'
  env_x86 = collections.OrderedDict([
      (
          'PATH',
          [
              ['win_sdk', 'bin', WIN_VERSION, 'x64'],
              vc_tools_parts + ['bin', 'HostX64', 'x86'],
              vc_tools_parts + ['bin', 'HostX64', 'x64'
                                              ],  # Needed for mspdb1x0.dll.
          ]),
      ('LIB', [
          vc_tools_parts + ['lib', 'x86'],
          ['win_sdk', 'Lib', WIN_VERSION, 'um', 'x86'],
          ['win_sdk', 'Lib', WIN_VERSION, 'ucrt', 'x86'],
          vc_tools_parts + ['atlmfc', 'lib', 'x86'],
      ]),
  ])

  # x64.
  env_x64 = collections.OrderedDict([
      ('PATH', [
          ['win_sdk', 'bin', WIN_VERSION, 'x64'],
          vc_tools_parts + ['bin', 'HostX64', 'x64'],
      ]),
      ('LIB', [
          vc_tools_parts + ['lib', 'x64'],
          ['win_sdk', 'Lib', WIN_VERSION, 'um', 'x64'],
          ['win_sdk', 'Lib', WIN_VERSION, 'ucrt', 'x64'],
          vc_tools_parts + ['atlmfc', 'lib', 'x64'],
      ]),
  ])

  # arm64.
  env_arm64 = collections.OrderedDict([
      ('PATH', [
          ['win_sdk', 'bin', WIN_VERSION, 'x64'],
          vc_tools_parts + ['bin', 'HostX64', 'arm64'],
          vc_tools_parts + ['bin', 'HostX64', 'x64'],
      ]),
      ('LIB', [
          vc_tools_parts + ['lib', 'arm64'],
          ['win_sdk', 'Lib', WIN_VERSION, 'um', 'arm64'],
          ['win_sdk', 'Lib', WIN_VERSION, 'ucrt', 'arm64'],
          vc_tools_parts + ['atlmfc', 'lib', 'arm64'],
      ]),
  ])

  def BatDirs(dirs):
    return ';'.join(['%cd%\\' + os.path.join(*d) for d in dirs])
  set_env_prefix = os.path.join(target_dir, r'win_sdk\bin\SetEnv')
  with open(set_env_prefix + '.cmd', 'w') as f:
    # The prologue changes the current directory to the grandparent so that the
    # path entries can be set up without needing ..\..\ components.
    f.write('@echo off\n'
            ':: Generated by win_toolchain\\package_from_installed.py.\n'
            'pushd %~dp0..\..\n')
    for var, dirs in env.items():
      f.write('set %s=%s\n' % (var, BatDirs(dirs)))
    f.write('if "%1"=="/x64" goto x64\n')
    f.write('if "%1"=="/arm64" goto arm64\n')

    for var, dirs in env_x86.items():
      f.write('set %s=%s%s\n' % (
          var, BatDirs(dirs), ';%PATH%' if var == 'PATH' else ''))
    f.write('goto :END\n')

    f.write(':x64\n')
    for var, dirs in env_x64.items():
      f.write('set %s=%s%s\n' % (
          var, BatDirs(dirs), ';%PATH%' if var == 'PATH' else ''))
    f.write('goto :END\n')

    f.write(':arm64\n')
    for var, dirs in env_arm64.items():
      f.write('set %s=%s%s\n' % (
          var, BatDirs(dirs), ';%PATH%' if var == 'PATH' else ''))
    f.write('goto :END\n')
    f.write(':END\n')
    # Restore the original directory.
    f.write('popd\n')
  with open(set_env_prefix + '.x86.json', 'wt', newline='') as f:
    assert not set(env.keys()) & set(env_x86.keys()), 'dupe keys'
    json.dump({'env': collections.OrderedDict(list(env.items()) + list(env_x86.items()))},
              f)
  with open(set_env_prefix + '.x64.json', 'wt', newline='') as f:
    assert not set(env.keys()) & set(env_x64.keys()), 'dupe keys'
    json.dump({'env': collections.OrderedDict(list(env.items()) + list(env_x64.items()))},
              f)
  with open(set_env_prefix + '.arm64.json', 'wt', newline='') as f:
    assert not set(env.keys()) & set(env_arm64.keys()), 'dupe keys'
    json.dump({'env': collections.OrderedDict(list(env.items()) + list(env_arm64.items()))},
              f)


def AddEnvSetup(files, include_arm):
  """We need to generate this file in the same way that the "from pieces"
  script does, so pull that in here."""
  tempdir = tempfile.mkdtemp()
  os.makedirs(os.path.join(tempdir, 'win_sdk', 'bin'))
  GenerateSetEnvCmd(tempdir)
  files.append((os.path.join(tempdir, 'win_sdk', 'bin', 'SetEnv.cmd'),
                'win_sdk\\bin\\SetEnv.cmd'))
  files.append((os.path.join(tempdir, 'win_sdk', 'bin', 'SetEnv.x86.json'),
                'win_sdk\\bin\\SetEnv.x86.json'))
  files.append((os.path.join(tempdir, 'win_sdk', 'bin', 'SetEnv.x64.json'),
                'win_sdk\\bin\\SetEnv.x64.json'))
  if include_arm:
    files.append((os.path.join(tempdir, 'win_sdk', 'bin', 'SetEnv.arm64.json'),
                  'win_sdk\\bin\\SetEnv.arm64.json'))
  vs_version_file = os.path.join(tempdir, 'VS_VERSION')
  with open(vs_version_file, 'wt', newline='') as version:
    print(VS_VERSION, file=version)
  files.append((vs_version_file, 'VS_VERSION'))


def RenameToSha1(output):
  """Determine the hash in the same way that the unzipper does to rename the
  # .zip file."""
  print('Extracting to determine hash...')
  tempdir = tempfile.mkdtemp()
  old_dir = os.getcwd()
  os.chdir(tempdir)
  rel_dir = 'vs_files'
  with zipfile.ZipFile(
      os.path.join(old_dir, output), 'r', zipfile.ZIP_DEFLATED, True) as zf:
    zf.extractall(rel_dir)
  print('Hashing...')
  sha1 = get_toolchain_if_necessary.CalculateHash(rel_dir, None)
  # Shorten from forty characters to ten. This is still enough to avoid
  # collisions, while being less unwieldy and reducing the risk of MAX_PATH
  # failures.
  sha1 = sha1[:10]
  os.chdir(old_dir)
  shutil.rmtree(tempdir)
  final_name = sha1 + '.zip'
  os.rename(output, final_name)
  print('Renamed %s to %s.' % (output, final_name))


def main():
  if sys.version_info[0] < 3:
    print('This script requires Python 3')
    sys.exit(10)
  usage = 'usage: %prog [options] 2017|2019'
  parser = optparse.OptionParser(usage)
  parser.add_option('-w', '--winver', action='store', type='string',
                    dest='winver', default='10.0.18362.0',
                    help='Windows SDK version, such as 10.0.18362.0')
  parser.add_option('-d', '--dryrun', action='store_true', dest='dryrun',
                    default=False,
                    help='scan for file existence and prints statistics')
  parser.add_option('--noarm', action='store_false', dest='arm',
                    default=True,
                    help='Avoids arm parts of the SDK')
  parser.add_option('--override', action='store', type='string',
                    dest='override_dir', default=None,
                    help='Specify alternate bin/include/lib directory')
  parser.add_option('--repackage', action='store', type='string',
                    dest='repackage_dir', default=None,
                    help='Specify raw directory to be packaged, for hot fixes.')
  (options, args) = parser.parse_args()

  if options.repackage_dir:
    files = BuildRepackageFileList(options.repackage_dir)
  else:
    if len(args) != 1 or args[0] not in SUPPORTED_VS_VERSIONS:
      print('Must specify 2017 or 2019')
      parser.print_help();
      return 1

    if options.override_dir:
      if (not os.path.exists(os.path.join(options.override_dir, 'bin')) or
          not os.path.exists(os.path.join(options.override_dir, 'include')) or
          not os.path.exists(os.path.join(options.override_dir, 'lib'))):
        print('Invalid override directory - must contain bin/include/lib dirs')
        return 1

    global VS_VERSION
    VS_VERSION = args[0]
    global WIN_VERSION
    WIN_VERSION = options.winver
    global VC_TOOLS
    vs_path = GetVSPath()
    temp_tools_path = ExpandWildcards(vs_path, 'VC/Tools/MSVC/14.*.*')
    # Strip off the leading vs_path characters and switch back to / separators.
    VC_TOOLS = temp_tools_path[len(vs_path) + 1:].replace('\\', '/')

    print('Building file list for VS %s Windows %s...' % (VS_VERSION, WIN_VERSION))
    files = BuildFileList(options.override_dir, options.arm)

    AddEnvSetup(files, options.arm)

  if False:
    for f in files:
      print(f[0], '->', f[1])
    return 0

  output = 'out.zip'
  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
      if not options.repackage_dir and disk_name.count(WIN_VERSION) > 0:
        version_match_count += 1
      if os.path.exists(disk_name):
        total_size += os.path.getsize(disk_name)
        if not options.dryrun:
          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()
  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))
  if options.dryrun:
    return 0
  if missing_files:
    raise Exception('One or more files were missing - aborting')
  if not options.repackage_dir and version_match_count == 0:
    raise Exception('No files found that match the specified winversion')
  sys.stdout.write('\rWrote to %s.%s\n' % (output, ' '*50))
  sys.stdout.flush()

  RenameToSha1(output)

  return 0


if __name__ == '__main__':
  sys.exit(main())
