Home | History | Annotate | Download | only in bot
      1 # Copyright 2014 The Chromium Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 import json
      6 import os
      7 import pipes
      8 import shutil
      9 import subprocess
     10 import sys
     11 
     12 
     13 script_dir = os.path.dirname(os.path.realpath(__file__))
     14 sys.path.insert(0, os.path.join(script_dir, 'gyp', 'pylib'))
     15 json_data_file = os.path.join(script_dir, 'win_toolchain.json')
     16 
     17 
     18 import gyp
     19 
     20 
     21 # Use MSVS2015 as the default toolchain.
     22 CURRENT_DEFAULT_TOOLCHAIN_VERSION = '2015'
     23 
     24 
     25 def SetEnvironmentAndGetRuntimeDllDirs():
     26   """Sets up os.environ to use the depot_tools VS toolchain with gyp, and
     27   returns the location of the VS runtime DLLs so they can be copied into
     28   the output directory after gyp generation.
     29   """
     30   vs_runtime_dll_dirs = None
     31   depot_tools_win_toolchain = \
     32       bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1')))
     33   if sys.platform in ('win32', 'cygwin') and depot_tools_win_toolchain:
     34     if not os.path.exists(json_data_file):
     35       Update()
     36     with open(json_data_file, 'r') as tempf:
     37       toolchain_data = json.load(tempf)
     38 
     39     toolchain = toolchain_data['path']
     40     version = toolchain_data['version']
     41     win_sdk = toolchain_data.get('win_sdk')
     42     if not win_sdk:
     43       win_sdk = toolchain_data['win8sdk']
     44     wdk = toolchain_data['wdk']
     45     # TODO(scottmg): The order unfortunately matters in these. They should be
     46     # split into separate keys for x86 and x64. (See CopyVsRuntimeDlls call
     47     # below). http://crbug.com/345992
     48     vs_runtime_dll_dirs = toolchain_data['runtime_dirs']
     49 
     50     os.environ['GYP_MSVS_OVERRIDE_PATH'] = toolchain
     51     os.environ['GYP_MSVS_VERSION'] = version
     52     # We need to make sure windows_sdk_path is set to the automated
     53     # toolchain values in GYP_DEFINES, but don't want to override any
     54     # otheroptions.express
     55     # values there.
     56     gyp_defines_dict = gyp.NameValueListToDict(gyp.ShlexEnv('GYP_DEFINES'))
     57     gyp_defines_dict['windows_sdk_path'] = win_sdk
     58     os.environ['GYP_DEFINES'] = ' '.join('%s=%s' % (k, pipes.quote(str(v)))
     59         for k, v in gyp_defines_dict.iteritems())
     60     os.environ['WINDOWSSDKDIR'] = win_sdk
     61     os.environ['WDK_DIR'] = wdk
     62     # Include the VS runtime in the PATH in case it's not machine-installed.
     63     runtime_path = ';'.join(vs_runtime_dll_dirs)
     64     os.environ['PATH'] = runtime_path + ';' + os.environ['PATH']
     65   return vs_runtime_dll_dirs
     66 
     67 
     68 def FindDepotTools():
     69   """Returns the path to depot_tools in $PATH."""
     70   for path in os.environ['PATH'].split(os.pathsep):
     71     if os.path.isfile(os.path.join(path, 'gclient.py')):
     72       return path
     73   raise Exception("depot_tools not found!")
     74 
     75 
     76 def GetVisualStudioVersion():
     77   """Return GYP_MSVS_VERSION of Visual Studio.
     78   """
     79   return os.environ.get('GYP_MSVS_VERSION', CURRENT_DEFAULT_TOOLCHAIN_VERSION)
     80 
     81 
     82 def _GetDesiredVsToolchainHashes():
     83   """Load a list of SHA1s corresponding to the toolchains that we want installed
     84   to build with."""
     85   env_version = GetVisualStudioVersion()
     86   if env_version == '2015':
     87     # Update 3 final with 10.0.15063.468 SDK and no vctip.exe.
     88     return ['f53e4598951162bad6330f7a167486c7ae5db1e5']
     89   if env_version == '2017':
     90     # VS 2017 Update 3.2 with 10.0.15063.468 SDK, patched setenv.cmd, and
     91     # 10.0.16299.15 debuggers.
     92     return ['1180cb75833ea365097e279efb2d5d7a42dee4b0']
     93   raise Exception('Unsupported VS version %s' % env_version)
     94 
     95 
     96 def Update():
     97   """Requests an update of the toolchain to the specific hashes we have at
     98   this revision. The update outputs a .json of the various configuration
     99   information required to pass to gyp which we use in |GetToolchainDir()|.
    100   """
    101   depot_tools_win_toolchain = \
    102       bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1')))
    103   if sys.platform in ('win32', 'cygwin') and depot_tools_win_toolchain:
    104     depot_tools_path = FindDepotTools()
    105     # Necessary so that get_toolchain_if_necessary.py will put the VS toolkit
    106     # in the correct directory.
    107     os.environ['GYP_MSVS_VERSION'] = GetVisualStudioVersion()
    108     get_toolchain_args = [
    109         sys.executable,
    110         os.path.join(depot_tools_path,
    111                     'win_toolchain',
    112                     'get_toolchain_if_necessary.py'),
    113         '--output-json', json_data_file,
    114       ] + _GetDesiredVsToolchainHashes()
    115     subprocess.check_call(get_toolchain_args)
    116 
    117   return 0
    118 
    119 
    120 def main():
    121   if not sys.platform.startswith(('win32', 'cygwin')):
    122     return 0
    123   commands = {
    124       'update': Update,
    125   }
    126   if len(sys.argv) < 2 or sys.argv[1] not in commands:
    127     print >>sys.stderr, 'Expected one of: %s' % ', '.join(commands)
    128     return 1
    129   return commands[sys.argv[1]](*sys.argv[2:])
    130 
    131 
    132 if __name__ == '__main__':
    133   sys.exit(main())
    134