| OLD | NEW |
| (Empty) |
| 1 # Copyright 2014 The Native Client 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 nacl_dir = os.path.dirname(script_dir) | |
| 15 root_dir = os.path.dirname(nacl_dir) | |
| 16 sys.path.insert(1, os.path.join(root_dir, 'tools')) | |
| 17 sys.path.insert(0, os.path.join(root_dir, 'tools', 'gyp', 'pylib')) | |
| 18 json_data_file = os.path.join(script_dir, 'win_toolchain.json') | |
| 19 | |
| 20 | |
| 21 import gyp | |
| 22 | |
| 23 | |
| 24 def SetEnvironmentAndGetRuntimeDllDirs(): | |
| 25 """Sets up os.environ to use the depot_tools VS toolchain with gyp, and | |
| 26 returns the location of the VS runtime DLLs so they can be copied into | |
| 27 the output directory after gyp generation. | |
| 28 """ | |
| 29 vs2013_runtime_dll_dirs = None | |
| 30 depot_tools_win_toolchain = \ | |
| 31 bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1'))) | |
| 32 if sys.platform in ('win32', 'cygwin') and depot_tools_win_toolchain: | |
| 33 with open(json_data_file, 'r') as tempf: | |
| 34 toolchain_data = json.load(tempf) | |
| 35 | |
| 36 toolchain = toolchain_data['path'] | |
| 37 version = toolchain_data['version'] | |
| 38 version_is_pro = version[-1] != 'e' | |
| 39 win8sdk = toolchain_data['win8sdk'] | |
| 40 wdk = toolchain_data['wdk'] | |
| 41 # TODO(scottmg): The order unfortunately matters in these. They should be | |
| 42 # split into separate keys for x86 and x64. (See CopyVsRuntimeDlls call | |
| 43 # below). http://crbug.com/345992 | |
| 44 vs2013_runtime_dll_dirs = toolchain_data['runtime_dirs'] | |
| 45 | |
| 46 os.environ['GYP_MSVS_OVERRIDE_PATH'] = toolchain | |
| 47 os.environ['GYP_MSVS_VERSION'] = version | |
| 48 # We need to make sure windows_sdk_path is set to the automated | |
| 49 # toolchain values in GYP_DEFINES, but don't want to override any | |
| 50 # otheroptions.express | |
| 51 # values there. | |
| 52 gyp_defines_dict = gyp.NameValueListToDict(gyp.ShlexEnv('GYP_DEFINES')) | |
| 53 gyp_defines_dict['windows_sdk_path'] = win8sdk | |
| 54 os.environ['GYP_DEFINES'] = ' '.join('%s=%s' % (k, pipes.quote(str(v))) | |
| 55 for k, v in gyp_defines_dict.iteritems()) | |
| 56 os.environ['WINDOWSSDKDIR'] = win8sdk | |
| 57 os.environ['WDK_DIR'] = wdk | |
| 58 # Include the VS runtime in the PATH in case it's not machine-installed. | |
| 59 runtime_path = ';'.join(vs2013_runtime_dll_dirs) | |
| 60 os.environ['PATH'] = runtime_path + ';' + os.environ['PATH'] | |
| 61 return vs2013_runtime_dll_dirs | |
| 62 | |
| 63 | |
| 64 def CopyVsRuntimeDlls(output_dir, runtime_dirs): | |
| 65 """Copies the VS runtime DLLs from the given |runtime_dirs| to the output | |
| 66 directory so that even if not system-installed, built binaries are likely to | |
| 67 be able to run. | |
| 68 | |
| 69 This needs to be run after gyp has been run so that the expected target | |
| 70 output directories are already created. | |
| 71 """ | |
| 72 assert sys.platform.startswith(('win32', 'cygwin')) | |
| 73 | |
| 74 def copy_runtime(target_dir, source_dir, dll_pattern): | |
| 75 """Copy both the msvcr and msvcp runtime DLLs, only if the target doesn't | |
| 76 exist, but the target directory does exist.""" | |
| 77 for which in ('p', 'r'): | |
| 78 dll = dll_pattern % which | |
| 79 target = os.path.join(target_dir, dll) | |
| 80 source = os.path.join(source_dir, dll) | |
| 81 # If gyp generated to that output dir, and the runtime isn't already | |
| 82 # there, then copy it over. | |
| 83 if (os.path.isdir(target_dir) and | |
| 84 (not os.path.isfile(target) or | |
| 85 os.stat(target).st_mtime != os.stat(source).st_mtime)): | |
| 86 print 'Copying %s to %s...' % (source, target) | |
| 87 if os.path.exists(target): | |
| 88 os.unlink(target) | |
| 89 shutil.copy2(source, target) | |
| 90 | |
| 91 x86, x64 = runtime_dirs | |
| 92 out_debug = os.path.join(output_dir, 'Debug') | |
| 93 out_debug_nacl64 = os.path.join(output_dir, 'Debug', 'x64') | |
| 94 out_release = os.path.join(output_dir, 'Release') | |
| 95 out_release_nacl64 = os.path.join(output_dir, 'Release', 'x64') | |
| 96 out_debug_x64 = os.path.join(output_dir, 'Debug_x64') | |
| 97 out_release_x64 = os.path.join(output_dir, 'Release_x64') | |
| 98 | |
| 99 if os.path.exists(out_debug) and not os.path.exists(out_debug_nacl64): | |
| 100 os.makedirs(out_debug_nacl64) | |
| 101 if os.path.exists(out_release) and not os.path.exists(out_release_nacl64): | |
| 102 os.makedirs(out_release_nacl64) | |
| 103 copy_runtime(out_debug, x86, 'msvc%s120d.dll') | |
| 104 copy_runtime(out_release, x86, 'msvc%s120.dll') | |
| 105 copy_runtime(out_debug_x64, x64, 'msvc%s120d.dll') | |
| 106 copy_runtime(out_release_x64, x64, 'msvc%s120.dll') | |
| 107 copy_runtime(out_debug_nacl64, x64, 'msvc%s120d.dll') | |
| 108 copy_runtime(out_release_nacl64, x64, 'msvc%s120.dll') | |
| 109 | |
| 110 | |
| 111 def _GetDesiredVsToolchainHashes(): | |
| 112 """Load a list of SHA1s corresponding to the toolchains that we want installed | |
| 113 to build with.""" | |
| 114 sha1path = os.path.join(script_dir, 'toolchain_vs2013.hash') | |
| 115 with open(sha1path, 'rb') as f: | |
| 116 return f.read().strip().splitlines() | |
| 117 | |
| 118 | |
| 119 def Update(): | |
| 120 """Requests an update of the toolchain to the specific hashes we have at | |
| 121 this revision. The update outputs a .json of the various configuration | |
| 122 information required to pass to gyp which we use in |GetToolchainDir()|. | |
| 123 """ | |
| 124 depot_tools_win_toolchain = \ | |
| 125 bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1'))) | |
| 126 if sys.platform in ('win32', 'cygwin') and depot_tools_win_toolchain: | |
| 127 import find_depot_tools | |
| 128 depot_tools_path = find_depot_tools.FindDepotTools() | |
| 129 json_data_file = os.path.join(script_dir, 'win_toolchain.json') | |
| 130 get_toolchain_args = [ | |
| 131 sys.executable, | |
| 132 os.path.join(depot_tools_path, | |
| 133 'win_toolchain', | |
| 134 'get_toolchain_if_necessary.py'), | |
| 135 '--output-json', json_data_file, | |
| 136 ] + _GetDesiredVsToolchainHashes() | |
| 137 subprocess.check_call(get_toolchain_args) | |
| 138 | |
| 139 return 0 | |
| 140 | |
| 141 | |
| 142 def GetToolchainDir(): | |
| 143 """Gets location information about the current toolchain (must have been | |
| 144 previously updated by 'update'). This is used for the GN build.""" | |
| 145 SetEnvironmentAndGetRuntimeDllDirs() | |
| 146 print '''vs_path = "%s" | |
| 147 sdk_path = "%s" | |
| 148 vs_version = "%s" | |
| 149 wdk_dir = "%s" | |
| 150 ''' % ( | |
| 151 os.environ['GYP_MSVS_OVERRIDE_PATH'], | |
| 152 os.environ['WINDOWSSDKDIR'], | |
| 153 os.environ['GYP_MSVS_VERSION'], | |
| 154 os.environ['WDK_DIR']) | |
| 155 | |
| 156 | |
| 157 def main(): | |
| 158 if not sys.platform.startswith(('win32', 'cygwin')): | |
| 159 return 0 | |
| 160 commands = { | |
| 161 'update': Update, | |
| 162 'get_toolchain_dir': GetToolchainDir, | |
| 163 # TODO(scottmg): Add copy_dlls for GN builds (gyp_chromium calls | |
| 164 # CopyVsRuntimeDlls via import, currently). | |
| 165 } | |
| 166 if len(sys.argv) < 2 or sys.argv[1] not in commands: | |
| 167 print >>sys.stderr, 'Expected one of: %s' % ', '.join(commands) | |
| 168 return 1 | |
| 169 return commands[sys.argv[1]]() | |
| 170 | |
| 171 | |
| 172 if __name__ == '__main__': | |
| 173 sys.exit(main()) | |
| OLD | NEW |