OLD | NEW |
(Empty) | |
| 1 # Copyright 2013 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 # Extracts a Windows VS2013 toolchain from various downloadable pieces. |
| 6 |
| 7 |
| 8 from toolchain import * |
| 9 |
| 10 |
| 11 def GetIsoUrl(pro): |
| 12 """Get the .iso path.""" |
| 13 prefix = 'http://download.microsoft.com/download/' |
| 14 if pro: |
| 15 return (prefix + |
| 16 'A/F/1/AF128362-A6A8-4DB3-A39A-C348086472CC/VS2013_RTM_PRO_ENU.iso') |
| 17 else: |
| 18 return (prefix + |
| 19 '7/2/E/72E0F986-D247-4289-B9DC-C4FB07374894/VS2013_RTM_DskExp_ENU.iso') |
| 20 |
| 21 |
| 22 def DownloadMainIso(url): |
| 23 temp_dir = TempDir() |
| 24 target_path = os.path.join(temp_dir, os.path.basename(url)) |
| 25 Download(url, target_path) |
| 26 return target_path |
| 27 |
| 28 |
| 29 def GetSourceImage(local_dir, pro): |
| 30 url = GetIsoUrl(pro) |
| 31 if local_dir: |
| 32 return os.path.join(local_dir, os.path.basename(url)) |
| 33 else: |
| 34 return DownloadMainIso(url) |
| 35 |
| 36 |
| 37 def ExtractMsiList(iso_dir, packages): |
| 38 results = [] |
| 39 for (package, skippable) in packages: |
| 40 path_to_package = os.path.join(iso_dir, 'packages', package) |
| 41 if not os.path.exists(path_to_package) and skippable: |
| 42 sys.stdout.write('Pro-only %s skipped.\n' % package) |
| 43 continue |
| 44 results.append(ExtractMsi(path_to_package)) |
| 45 return results |
| 46 |
| 47 |
| 48 def ExtractComponents(image): |
| 49 extracted_iso = ExtractIso(image) |
| 50 results = ExtractMsiList(extracted_iso, [ |
| 51 (r'vcRuntimeAdditional_amd64\vc_runtimeAdditional_x64.msi', False), |
| 52 (r'vcRuntimeAdditional_x86\vc_runtimeAdditional_x86.msi', False), |
| 53 (r'vcRuntimeDebug_amd64\vc_runtimeDebug_x64.msi', False), |
| 54 (r'vcRuntimeDebug_x86\vc_runtimeDebug_x86.msi', False), |
| 55 (r'vcRuntimeMinimum_amd64\vc_runtimeMinimum_x64.msi', False), |
| 56 (r'vcRuntimeMinimum_x86\vc_runtimeMinimum_x86.msi', False), |
| 57 (r'vc_compilerCore86\vc_compilerCore86.msi', False), |
| 58 (r'vc_compilerCore86res\vc_compilerCore86res.msi', False), |
| 59 (r'vc_compilerx64nat\vc_compilerx64nat.msi', True), |
| 60 (r'vc_compilerx64natres\vc_compilerx64natres.msi', True), |
| 61 (r'vc_compilerx64x86\vc_compilerx64x86.msi', True), |
| 62 (r'vc_compilerx64x86res\vc_compilerx64x86res.msi', True), |
| 63 (r'vc_librarycore86\vc_librarycore86.msi', False), |
| 64 (r'vc_libraryDesktop\x64\vc_LibraryDesktopX64.msi', False), |
| 65 (r'vc_libraryDesktop\x86\vc_LibraryDesktopX86.msi', False), |
| 66 (r'vc_libraryextended\vc_libraryextended.msi', True), |
| 67 (r'Windows_SDK\Windows Software Development Kit-x86_en-us.msi', False), |
| 68 ('Windows_SDK\\' |
| 69 r'Windows Software Development Kit for Metro style Apps-x86_en-us.msi', |
| 70 False), |
| 71 ]) |
| 72 return results |
| 73 |
| 74 |
| 75 def CopyToFinalLocation(extracted_dirs, target_dir): |
| 76 sys.stdout.write('Copying to final location...\n') |
| 77 mappings = { |
| 78 'Program Files\\Microsoft Visual Studio 12.0\\': 'vs\\', |
| 79 'Windows Kits\\8.0\\': 'win8sdk\\', |
| 80 'System64\\': 'sys64\\', |
| 81 'System\\': 'sys32\\', |
| 82 } |
| 83 matches = [] |
| 84 for extracted_dir in extracted_dirs: |
| 85 for root, dirnames, filenames in os.walk(extracted_dir): |
| 86 for filename in filenames: |
| 87 matches.append((extracted_dir, os.path.join(root, filename))) |
| 88 |
| 89 copies = [] |
| 90 for prefix, full_path in matches: |
| 91 partial_path = full_path[len(prefix) + 1:] # +1 for trailing \ |
| 92 #print 'partial_path', partial_path |
| 93 for map_from, map_to in mappings.iteritems(): |
| 94 #print 'map_from:', map_from, ', map_to:', map_to |
| 95 if partial_path.startswith(map_from): |
| 96 target_path = os.path.join(map_to, partial_path[len(map_from):]) |
| 97 copies.append((full_path, os.path.join(target_dir, target_path))) |
| 98 |
| 99 for full_source, full_target in copies: |
| 100 target_dir = os.path.dirname(full_target) |
| 101 if not os.path.isdir(target_dir): |
| 102 os.makedirs(target_dir) |
| 103 shutil.copy2(full_source, full_target) |
| 104 |
| 105 |
| 106 def GenerateSetEnvCmd(target_dir, pro): |
| 107 """Generate a batch file that gyp expects to exist to set up the compiler |
| 108 environment. This is normally generated by a full install of the SDK, but we |
| 109 do it here manually since we do not do a full install.""" |
| 110 with open(os.path.join( |
| 111 target_dir, r'win8sdk\bin\SetEnv.cmd'), 'w') as file: |
| 112 file.write('@echo off\n') |
| 113 file.write(':: Generated by tools\\win\\toolchain\\toolchain2013.py.\n') |
| 114 # Common to x86 and x64 |
| 115 file.write('set PATH=%~dp0..\\..\\vs\\Common7\\IDE;%PATH%\n') |
| 116 file.write('set INCLUDE=%~dp0..\\..\\win8sdk\\Include\\um;' |
| 117 '%~dp0..\\..\\win8sdk\\Include\\shared;' |
| 118 '%~dp0..\\..\\vs\\VC\\include;' |
| 119 '%~dp0..\\..\\vs\\VC\\atlmfc\\include\n') |
| 120 file.write('if "%1"=="/x64" goto x64\n') |
| 121 |
| 122 # x86. If we're Pro, then use the amd64_x86 cross (we don't support x86 |
| 123 # host at all). |
| 124 if pro: |
| 125 file.write('set PATH=%~dp0..\\..\\win8sdk\\bin\\x86;' |
| 126 '%~dp0..\\..\\vs\\VC\\bin\\amd64_x86;' |
| 127 '%~dp0..\\..\\vs\\VC\\bin\\amd64;' # Needed for mspdb120.dll. |
| 128 '%PATH%\n') |
| 129 else: |
| 130 file.write('set PATH=%~dp0..\\..\\win8sdk\\bin\\x86;' |
| 131 '%~dp0..\\..\\vs\\VC\\bin;%PATH%\n') |
| 132 file.write('set LIB=%~dp0..\\..\\vs\\VC\\lib;' |
| 133 '%~dp0..\\..\\win8sdk\\Lib\\win8\\um\\x86;' |
| 134 '%~dp0..\\..\\vs\\VC\\atlmfc\\lib\n') |
| 135 file.write('goto done\n') |
| 136 |
| 137 # Express does not include a native 64 bit compiler, so we have to use |
| 138 # the x86->x64 cross. |
| 139 if not pro: |
| 140 # x86->x64 cross. |
| 141 file.write(':x64\n') |
| 142 file.write('set PATH=%~dp0..\\..\\win8sdk\\bin\\x64;' |
| 143 '%~dp0..\\..\\vs\\VC\\bin\\x86_amd64;' |
| 144 '%PATH%\n') |
| 145 else: |
| 146 # x64 native. |
| 147 file.write(':x64\n') |
| 148 file.write('set PATH=%~dp0..\\..\\win8sdk\\bin\\x64;' |
| 149 '%~dp0..\\..\\vs\\VC\\bin\\amd64;' |
| 150 '%PATH%\n') |
| 151 file.write('set LIB=%~dp0..\\..\\vs\\VC\\lib\\amd64;' |
| 152 '%~dp0..\\..\\win8sdk\\Lib\\win8\\um\\x64;' |
| 153 '%~dp0..\\..\\vs\\VC\\atlmfc\\lib\\amd64\n') |
| 154 file.write(':done\n') |
| 155 |
| 156 |
| 157 def GenerateTopLevelEnv(target_dir, pro): |
| 158 """Generate a batch file that sets up various environment variables that let |
| 159 the Chromium build files and gyp find SDKs and tools.""" |
| 160 with open(os.path.join(target_dir, r'env.bat'), 'w') as file: |
| 161 file.write('@echo off\n') |
| 162 file.write(':: Generated by tools\\win\\toolchain\\toolchain2013.py.\n') |
| 163 file.write('set GYP_DEFINES=windows_sdk_path="%~dp0win8sdk" ' |
| 164 'component=shared_library\n') |
| 165 file.write('set GYP_MSVS_VERSION=2013%s\n' % '' if pro else 'e') |
| 166 file.write('set GYP_MSVS_OVERRIDE_PATH=%~dp0\n') |
| 167 file.write('set GYP_GENERATORS=ninja\n') |
| 168 file.write('set WindowsSDKDir=%~dp0win8sdk\n') |
| 169 paths = [ |
| 170 r'Debug_NonRedist\x64\Microsoft.VC120.DebugCRT', |
| 171 r'Debug_NonRedist\x86\Microsoft.VC120.DebugCRT', |
| 172 r'x64\Microsoft.VC120.CRT', |
| 173 r'x86\Microsoft.VC120.CRT', |
| 174 ] |
| 175 additions = ';'.join(('%~dp0' + x) for x in paths) |
| 176 file.write('set PATH=%s;%%PATH%%\n' % additions) |
| 177 file.write('echo Environment set for toolchain in %~dp0.\n') |
| 178 file.write('cd /d %~dp0..\n') |
| 179 |
| 180 |
| 181 def main(): |
| 182 parser = OptionParser() |
| 183 parser.add_option('--targetdir', metavar='DIR', |
| 184 help='put toolchain into DIR', |
| 185 default=os.path.abspath('win_toolchain_2013')) |
| 186 parser.add_option('--noclean', action='store_false', dest='clean', |
| 187 help='do not remove temp files', |
| 188 default=True) |
| 189 parser.add_option('--local', metavar='DIR', |
| 190 help='use downloaded files from DIR') |
| 191 parser.add_option('--express', metavar='EXPRESS', |
| 192 help='use VS Express instead of Pro', action='store_true') |
| 193 options, args = parser.parse_args() |
| 194 try: |
| 195 target_dir = os.path.abspath(options.targetdir) |
| 196 if os.path.exists(target_dir): |
| 197 sys.stderr.write('%s already exists. Please [re]move it or use ' |
| 198 '--targetdir to select a different target.\n' % |
| 199 target_dir) |
| 200 return 1 |
| 201 pro = not options.express |
| 202 # Set the working directory to 7z subdirectory. 7-zip doesn't find its |
| 203 # codec dll very well, so this is the simplest way to make sure it runs |
| 204 # correctly, as we don't otherwise care about working directory. |
| 205 os.chdir(os.path.join(os.path.dirname(os.path.abspath(__file__)), '7z')) |
| 206 image = GetSourceImage(options.local, pro) |
| 207 extracted = ExtractComponents(image) |
| 208 CopyToFinalLocation(extracted, target_dir) |
| 209 |
| 210 GenerateSetEnvCmd(target_dir, pro) |
| 211 GenerateTopLevelEnv(target_dir, pro) |
| 212 finally: |
| 213 if options.clean: |
| 214 DeleteAllTempDirs() |
| 215 |
| 216 sys.stdout.write( |
| 217 '\nIn a (clean) cmd shell, you can now run\n\n' |
| 218 ' %s\\env.bat\n\n' |
| 219 'then\n\n' |
| 220 " gclient runhooks (or gclient sync if you haven't pulled deps yet)\n" |
| 221 ' ninja -C out\Debug chrome\n\n' |
| 222 'Note that this script intentionally does not modify any global\n' |
| 223 'settings like the registry, or system environment variables, so you\n' |
| 224 'will need to run the above env.bat whenever you start a new\n' |
| 225 'shell.\n\n' % target_dir) |
| 226 |
| 227 |
| 228 if __name__ == '__main__': |
| 229 main() |
OLD | NEW |