Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(745)

Side by Side Diff: build/vs_toolchain.py

Issue 2770193005: build with MSVS will only need VS console environment set up
Patch Set: build with MSVS will need VS console environment set up Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « build/config/win/visual_studio_version.gni ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright 2014 The Chromium Authors. All rights reserved. 2 # Copyright 2014 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 import glob 6 import glob
7 import json 7 import json
8 import os 8 import os
9 import pipes 9 import pipes
10 import platform 10 import platform
(...skipping 19 matching lines...) Expand all
30 returns the location of the VS runtime DLLs so they can be copied into 30 returns the location of the VS runtime DLLs so they can be copied into
31 the output directory after gyp generation. 31 the output directory after gyp generation.
32 32
33 Return value is [x64path, x86path] or None 33 Return value is [x64path, x86path] or None
34 """ 34 """
35 vs_runtime_dll_dirs = None 35 vs_runtime_dll_dirs = None
36 depot_tools_win_toolchain = \ 36 depot_tools_win_toolchain = \
37 bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1'))) 37 bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1')))
38 # When running on a non-Windows host, only do this if the SDK has explicitly 38 # When running on a non-Windows host, only do this if the SDK has explicitly
39 # been downloaded before (in which case json_data_file will exist). 39 # been downloaded before (in which case json_data_file will exist).
40 if ((sys.platform in ('win32', 'cygwin') or os.path.exists(json_data_file)) 40 if (depot_tools_win_toolchain and (sys.platform in ('win32', 'cygwin')
41 and depot_tools_win_toolchain): 41 or os.path.exists(json_data_file))):
42 if ShouldUpdateToolchain(): 42 if ShouldUpdateToolchain():
43 Update() 43 Update()
44 with open(json_data_file, 'r') as tempf: 44 with open(json_data_file, 'r') as tempf:
45 toolchain_data = json.load(tempf) 45 toolchain_data = json.load(tempf)
46 46
47 toolchain = toolchain_data['path'] 47 toolchain = toolchain_data['path']
48 version = toolchain_data['version'] 48 version = toolchain_data['version']
49 win_sdk = toolchain_data.get('win_sdk') 49 win_sdk = toolchain_data.get('win_sdk')
50 if not win_sdk: 50 if not win_sdk:
51 win_sdk = toolchain_data['win8sdk'] 51 win_sdk = toolchain_data['win8sdk']
(...skipping 13 matching lines...) Expand all
65 65
66 # We need to make sure windows_sdk_path is set to the automated 66 # We need to make sure windows_sdk_path is set to the automated
67 # toolchain values in GYP_DEFINES, but don't want to override any 67 # toolchain values in GYP_DEFINES, but don't want to override any
68 # otheroptions.express 68 # otheroptions.express
69 # values there. 69 # values there.
70 gyp_defines_dict = gyp.NameValueListToDict(gyp.ShlexEnv('GYP_DEFINES')) 70 gyp_defines_dict = gyp.NameValueListToDict(gyp.ShlexEnv('GYP_DEFINES'))
71 gyp_defines_dict['windows_sdk_path'] = win_sdk 71 gyp_defines_dict['windows_sdk_path'] = win_sdk
72 os.environ['GYP_DEFINES'] = ' '.join('%s=%s' % (k, pipes.quote(str(v))) 72 os.environ['GYP_DEFINES'] = ' '.join('%s=%s' % (k, pipes.quote(str(v)))
73 for k, v in gyp_defines_dict.iteritems()) 73 for k, v in gyp_defines_dict.iteritems())
74 74
75 os.environ['WINDOWSSDKDIR'] = win_sdk 75 os.environ['WindowsSdkDir'] = win_sdk
76 os.environ['WDK_DIR'] = wdk 76 os.environ['WDK_DIR'] = wdk
77 # Include the VS runtime in the PATH in case it's not machine-installed. 77 # Include the VS runtime in the PATH in case it's not machine-installed.
78 runtime_path = os.path.pathsep.join(vs_runtime_dll_dirs) 78 runtime_path = os.path.pathsep.join(vs_runtime_dll_dirs)
79 os.environ['PATH'] = runtime_path + os.path.pathsep + os.environ['PATH'] 79 os.environ['PATH'] = runtime_path + os.path.pathsep + os.environ['PATH']
80 elif sys.platform == 'win32' and not depot_tools_win_toolchain: 80 elif sys.platform == 'win32' and not depot_tools_win_toolchain:
81 if not 'GYP_MSVS_OVERRIDE_PATH' in os.environ: 81 GetVisualStudioVersion()
82 os.environ['GYP_MSVS_OVERRIDE_PATH'] = DetectVisualStudioPath() 82 DetectVisualStudioPath()
83 if not 'GYP_MSVS_VERSION' in os.environ:
84 os.environ['GYP_MSVS_VERSION'] = GetVisualStudioVersion()
85 83
86 # When using an installed toolchain these files aren't needed in the output 84 # When using an installed toolchain these files aren't needed in the output
87 # directory in order to run binaries locally, but they are needed in order 85 # directory in order to run binaries locally, but they are needed in order
88 # to create isolates or the mini_installer. Copying them to the output 86 # to create isolates or the mini_installer. Copying them to the output
89 # directory ensures that they are available when needed. 87 # directory ensures that they are available when needed.
90 bitness = platform.architecture()[0] 88 bitness = platform.architecture()[0]
91 # When running 64-bit python the x64 DLLs will be in System32 89 # When running 64-bit python the x64 DLLs will be in System32
92 x64_path = 'System32' if bitness == '64bit' else 'Sysnative' 90 x64_path = 'System32' if bitness == '64bit' else 'Sysnative'
93 x64_path = os.path.join(r'C:\Windows', x64_path) 91 x64_path = os.path.join(r'C:\Windows', x64_path)
94 vs_runtime_dll_dirs = [x64_path, r'C:\Windows\SysWOW64'] 92 vs_runtime_dll_dirs = [x64_path, r'C:\Windows\SysWOW64']
(...skipping 20 matching lines...) Expand all
115 except WindowsError: 113 except WindowsError:
116 return None 114 return None
117 115
118 116
119 def _RegistryGetValue(key, value): 117 def _RegistryGetValue(key, value):
120 try: 118 try:
121 return _RegistryGetValueUsingWinReg(key, value) 119 return _RegistryGetValueUsingWinReg(key, value)
122 except ImportError: 120 except ImportError:
123 raise Exception('The python library _winreg not found.') 121 raise Exception('The python library _winreg not found.')
124 122
125 123 year_to_version = {
124 '2013': '12.0',
125 '2015': '14.0',
126 '2017': '15.0',
127 }
126 def GetVisualStudioVersion(): 128 def GetVisualStudioVersion():
127 """Return GYP_MSVS_VERSION of Visual Studio. 129 """Return GYP_MSVS_VERSION of Visual Studio.
128 """ 130 """
129 return os.environ.get('GYP_MSVS_VERSION', CURRENT_DEFAULT_TOOLCHAIN_VERSION) 131 if 'VisualStudioVersion' not in os.environ:
132 raise ValueError('Please run from within a VS console (with ENV variables)')
133
134 ver = os.environ['VisualStudioVersion']
135 year = year_to_version.keys()[year_to_version.values().index(ver)]
136
137 if year not in year_to_version:
138 years = ', '.join(year_to_version.keys())
139 raise ValueError('Visual Studio version %s not supported.'
140 'Supported versions are: %s' % (year, years))
141
142 if 'GYP_MSVS_VERSION' in os.environ:
143 wanted = os.environ.get('GYP_MSVS_VERSION')
144 if wanted != year:
145 raise ValueError('GYP_MSVS_VERSION does not match VS console version'
146 '%s != %s(%s)' % (wanted, year, ver))
147 else:
148 os.environ['GYP_MSVS_VERSION'] = year
149
150 return year
130 151
131 152
132 def DetectVisualStudioPath(): 153 def DetectVisualStudioPath():
133 """Return path to the GYP_MSVS_VERSION of Visual Studio. 154 """Return path to the GYP_MSVS_VERSION of Visual Studio.
134 """ 155 """
135 156
136 # Note that this code is used from 157 # Note that this code is used from
137 # build/toolchain/win/setup_toolchain.py as well. 158 # build/toolchain/win/setup_toolchain.py as well.
138 version_as_year = GetVisualStudioVersion() 159 GetVisualStudioVersion()
139 year_to_version = { 160 if 'VSINSTALLDIR' not in os.environ:
140 '2013': '12.0', 161 raise ValueError('Please run from within a VS console (with ENV variables)')
141 '2015': '14.0', 162 if 'GYP_MSVS_OVERRIDE_PATH' in os.environ:
142 '2017': '15.0', 163 path = os.environ['GYP_MSVS_OVERRIDE_PATH']
143 }
144 if version_as_year not in year_to_version:
145 raise Exception(('Visual Studio version %s (from GYP_MSVS_VERSION)'
146 ' not supported. Supported versions are: %s') % (
147 version_as_year, ', '.join(year_to_version.keys())))
148 version = year_to_version[version_as_year]
149 if version_as_year == '2017':
150 # The VC++ 2017 install location needs to be located using COM instead of
151 # the registry. For details see:
152 # https://blogs.msdn.microsoft.com/heaths/2016/09/15/changes-to-visual-studi o-15-setup/
153 # For now we use a hardcoded default with an environment variable override.
154 path = r'C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional'
155 path = os.environ.get('vs2017_install', path)
156 if os.path.exists(path):
157 return path
158 else: 164 else:
159 keys = [r'HKLM\Software\Microsoft\VisualStudio\%s' % version, 165 path = os.environ['VSINSTALLDIR']
160 r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\%s' % version] 166 os.environ['GYP_MSVS_OVERRIDE_PATH'] = path
161 for key in keys:
162 path = _RegistryGetValue(key, 'InstallDir')
163 if not path:
164 continue
165 path = os.path.normpath(os.path.join(path, '..', '..'))
166 return path
167 167
168 raise Exception(('Visual Studio Version %s (from GYP_MSVS_VERSION)' 168 return path
169 ' not found.') % (version_as_year))
170 169
171 170 def _SdkFileSuffix():
brucedawson 2017/03/27 23:23:52 This needs a larger comment to explain what this n
172 def _VersionNumber():
173 """Gets the standard version number ('120', '140', etc.) based on 171 """Gets the standard version number ('120', '140', etc.) based on
174 GYP_MSVS_VERSION.""" 172 GYP_MSVS_VERSION."""
175 vs_version = GetVisualStudioVersion() 173 vs_version = GetVisualStudioVersion()
176 if vs_version == '2013': 174 if vs_version == '2013':
177 return '120' 175 return '120'
178 if vs_version == '2015': 176 if vs_version == '2015':
179 return '140' 177 return '140'
178 # even on 2017 (a.k.a. vc1410 version of files is 140)
180 if vs_version == '2017': 179 if vs_version == '2017':
181 return '150' 180 return '140'
182 raise ValueError('Unexpected GYP_MSVS_VERSION') 181 raise ValueError('Unexpected GYP_MSVS_VERSION')
183 182
184 183
185 def _CopyRuntimeImpl(target, source, verbose=True): 184 def _CopyRuntimeImpl(target, source, verbose=True):
186 """Copy |source| to |target| if it doesn't already exist or if it needs to be 185 """Copy |source| to |target| if it doesn't already exist or if it needs to be
187 updated (comparing last modified time as an approximate float match as for 186 updated (comparing last modified time as an approximate float match as for
188 some reason the values tend to differ by ~1e-07 despite being copies of the 187 some reason the values tend to differ by ~1e-07 despite being copies of the
189 same file... https://crbug.com/603603). 188 same file... https://crbug.com/603603).
190 """ 189 """
191 if (os.path.isdir(os.path.dirname(target)) and 190 if (os.path.isdir(os.path.dirname(target)) and
(...skipping 24 matching lines...) Expand all
216 """Copy both the msvcp and vccorlib runtime DLLs, only if the target doesn't 215 """Copy both the msvcp and vccorlib runtime DLLs, only if the target doesn't
217 exist, but the target directory does exist.""" 216 exist, but the target directory does exist."""
218 for file_part in ('msvcp', 'vccorlib', 'vcruntime'): 217 for file_part in ('msvcp', 'vccorlib', 'vcruntime'):
219 dll = dll_pattern % file_part 218 dll = dll_pattern % file_part
220 target = os.path.join(target_dir, dll) 219 target = os.path.join(target_dir, dll)
221 source = os.path.join(source_dir, dll) 220 source = os.path.join(source_dir, dll)
222 _CopyRuntimeImpl(target, source) 221 _CopyRuntimeImpl(target, source)
223 # Copy the UCRT files needed by VS 2015 from the Windows SDK. This location 222 # Copy the UCRT files needed by VS 2015 from the Windows SDK. This location
224 # includes the api-ms-win-crt-*.dll files that are not found in the Windows 223 # includes the api-ms-win-crt-*.dll files that are not found in the Windows
225 # directory. These files are needed for component builds. 224 # directory. These files are needed for component builds.
226 # If WINDOWSSDKDIR is not set use the default SDK path. This will be the case 225 win_sdk_dir = os.path.normpath(os.environ['WindowsSdkDir'])
227 # when DEPOT_TOOLS_WIN_TOOLCHAIN=0 and vcvarsall.bat has not been run.
228 win_sdk_dir = os.path.normpath(
229 os.environ.get('WINDOWSSDKDIR',
230 'C:\\Program Files (x86)\\Windows Kits\\10'))
231 ucrt_dll_dirs = os.path.join(win_sdk_dir, r'Redist\ucrt\DLLs', target_cpu) 226 ucrt_dll_dirs = os.path.join(win_sdk_dir, r'Redist\ucrt\DLLs', target_cpu)
232 ucrt_files = glob.glob(os.path.join(ucrt_dll_dirs, 'api-ms-win-*.dll')) 227 ucrt_files = glob.glob(os.path.join(ucrt_dll_dirs, 'api-ms-win-*.dll'))
233 assert len(ucrt_files) > 0 228 assert len(ucrt_files) > 0
234 for ucrt_src_file in ucrt_files: 229 for ucrt_src_file in ucrt_files:
235 file_part = os.path.basename(ucrt_src_file) 230 file_part = os.path.basename(ucrt_src_file)
236 ucrt_dst_file = os.path.join(target_dir, file_part) 231 ucrt_dst_file = os.path.join(target_dir, file_part)
237 _CopyRuntimeImpl(ucrt_dst_file, ucrt_src_file, False) 232 _CopyRuntimeImpl(ucrt_dst_file, ucrt_src_file, False)
238 _CopyRuntimeImpl(os.path.join(target_dir, 'ucrtbase' + suffix), 233 _CopyRuntimeImpl(os.path.join(target_dir, 'ucrtbase' + suffix),
239 os.path.join(source_dir, 'ucrtbase' + suffix)) 234 os.path.join(source_dir, 'ucrtbase' + suffix))
240 235
241 236
242 def _CopyRuntime(target_dir, source_dir, target_cpu, debug): 237 def _CopyRuntime(target_dir, source_dir, target_cpu, debug):
243 """Copy the VS runtime DLLs, only if the target doesn't exist, but the target 238 """Copy the VS runtime DLLs, only if the target doesn't exist, but the target
244 directory does exist. Handles VS 2013, VS 2015, and VS 2017.""" 239 directory does exist. Handles VS 2013, VS 2015, and VS 2017."""
245 suffix = "d.dll" if debug else ".dll" 240 suffix = "d.dll" if debug else ".dll"
241 dll_pattern = "%s" + _SdkFileSuffix() + suffix
246 if GetVisualStudioVersion() in ['2015', '2017']: 242 if GetVisualStudioVersion() in ['2015', '2017']:
247 # VS 2017 uses the same CRT DLLs as VS 2015. 243 # VS 2017 uses the same CRT DLLs as VS 2015.
248 _CopyUCRTRuntime(target_dir, source_dir, target_cpu, '%s140' + suffix, 244 _CopyUCRTRuntime(target_dir, source_dir, target_cpu, dll_pattern, suffix)
249 suffix)
250 else: 245 else:
251 _CopyRuntime2013(target_dir, source_dir, 'msvc%s120' + suffix) 246 _CopyRuntime2013(target_dir, source_dir, 'msvc' + dll_pattern)
brucedawson 2017/03/27 23:23:52 You'll need to rebase as the 2013 support was just
252 247
253 # Copy the PGO runtime library to the release directories. 248 # Copy the PGO runtime library to the release directories.
254 if not debug and os.environ.get('GYP_MSVS_OVERRIDE_PATH'): 249 if not debug and os.environ.get('GYP_MSVS_OVERRIDE_PATH'):
255 pgo_x86_runtime_dir = os.path.join(os.environ.get('GYP_MSVS_OVERRIDE_PATH'), 250 pgo_runtime_dll = 'pgort' + _SdkFileSuffix() + '.dll'
256 'VC', 'bin') 251 paths = subprocess.check_output(['where.exe', pgo_runtime_dll])\
257 pgo_x64_runtime_dir = os.path.join(pgo_x86_runtime_dir, 'amd64') 252 .strip()\
258 pgo_runtime_dll = 'pgort' + _VersionNumber() + '.dll' 253 .split('\n')
259 if target_cpu == "x86": 254 source = paths[-1].strip()
260 source_x86 = os.path.join(pgo_x86_runtime_dir, pgo_runtime_dll) 255 if os.path.exists(source):
261 if os.path.exists(source_x86): 256 _CopyRuntimeImpl(os.path.join(target_dir, pgo_runtime_dll), source)
262 _CopyRuntimeImpl(os.path.join(target_dir, pgo_runtime_dll), source_x86)
263 elif target_cpu == "x64":
264 source_x64 = os.path.join(pgo_x64_runtime_dir, pgo_runtime_dll)
265 if os.path.exists(source_x64):
266 _CopyRuntimeImpl(os.path.join(target_dir, pgo_runtime_dll),
267 source_x64)
268 else: 257 else:
269 raise NotImplementedError("Unexpected target_cpu value:" + target_cpu) 258 raise NotImplementedError("could not find " + pgo_runtime_dll)
270 259
271 260
272 def CopyVsRuntimeDlls(output_dir, runtime_dirs): 261 def CopyVsRuntimeDlls(output_dir, runtime_dirs):
273 """Copies the VS runtime DLLs from the given |runtime_dirs| to the output 262 """Copies the VS runtime DLLs from the given |runtime_dirs| to the output
274 directory so that even if not system-installed, built binaries are likely to 263 directory so that even if not system-installed, built binaries are likely to
275 be able to run. 264 be able to run.
276 265
277 This needs to be run after gyp has been run so that the expected target 266 This needs to be run after gyp has been run so that the expected target
278 output directories are already created. 267 output directories are already created.
279 268
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 force = True 372 force = True
384 373
385 depot_tools_win_toolchain = \ 374 depot_tools_win_toolchain = \
386 bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1'))) 375 bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1')))
387 if ((sys.platform in ('win32', 'cygwin') or force) and 376 if ((sys.platform in ('win32', 'cygwin') or force) and
388 depot_tools_win_toolchain): 377 depot_tools_win_toolchain):
389 import find_depot_tools 378 import find_depot_tools
390 depot_tools_path = find_depot_tools.add_depot_tools_to_path() 379 depot_tools_path = find_depot_tools.add_depot_tools_to_path()
391 # Necessary so that get_toolchain_if_necessary.py will put the VS toolkit 380 # Necessary so that get_toolchain_if_necessary.py will put the VS toolkit
392 # in the correct directory. 381 # in the correct directory.
393 os.environ['GYP_MSVS_VERSION'] = GetVisualStudioVersion() 382 GetVisualStudioVersion()
394 get_toolchain_args = [ 383 get_toolchain_args = [
395 sys.executable, 384 sys.executable,
396 os.path.join(depot_tools_path, 385 os.path.join(depot_tools_path,
397 'win_toolchain', 386 'win_toolchain',
398 'get_toolchain_if_necessary.py'), 387 'get_toolchain_if_necessary.py'),
399 '--output-json', json_data_file, 388 '--output-json', json_data_file,
400 ] + _GetDesiredVsToolchainHashes() 389 ] + _GetDesiredVsToolchainHashes()
401 if force: 390 if force:
402 get_toolchain_args.append('--force') 391 get_toolchain_args.append('--force')
403 subprocess.check_call(get_toolchain_args) 392 subprocess.check_call(get_toolchain_args)
404 393
405 return 0 394 return 0
406 395
407 396
408 def NormalizePath(path): 397 def NormalizePath(path):
409 while path.endswith("\\"): 398 while path.endswith("\\"):
410 path = path[:-1] 399 path = path[:-1]
411 return path 400 return path
412 401
413 402
414 def SetEnvironmentAndGetSDKDir(): 403 def SetEnvironmentAndGetSDKDir():
415 """Gets location information about the current sdk (must have been 404 """Gets location information about the current sdk (must have been
416 previously updated by 'update'). This is used for the GN build.""" 405 previously updated by 'update'). This is used for the GN build."""
417 runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs() 406 runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs()
418 407 return NormalizePath(os.environ['WindowsSdkDir'])
419 # If WINDOWSSDKDIR is not set, search the default SDK path and set it.
420 if not 'WINDOWSSDKDIR' in os.environ:
421 default_sdk_path = 'C:\\Program Files (x86)\\Windows Kits\\10'
422 if os.path.isdir(default_sdk_path):
423 os.environ['WINDOWSSDKDIR'] = default_sdk_path
424
425 return NormalizePath(os.environ['WINDOWSSDKDIR'])
426 408
427 409
428 def GetToolchainDir(): 410 def GetToolchainDir():
429 """Gets location information about the current toolchain (must have been 411 """Gets location information about the current toolchain (must have been
430 previously updated by 'update'). This is used for the GN build.""" 412 previously updated by 'update'). This is used for the GN build."""
431 runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs() 413 runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs()
432 win_sdk_dir = SetEnvironmentAndGetSDKDir() 414 win_sdk_dir = SetEnvironmentAndGetSDKDir()
433 415
434 print '''vs_path = "%s" 416 print '''vs_path = "%s"
435 sdk_path = "%s" 417 sdk_path = "%s"
(...skipping 15 matching lines...) Expand all
451 'copy_dlls': CopyDlls, 433 'copy_dlls': CopyDlls,
452 } 434 }
453 if len(sys.argv) < 2 or sys.argv[1] not in commands: 435 if len(sys.argv) < 2 or sys.argv[1] not in commands:
454 print >>sys.stderr, 'Expected one of: %s' % ', '.join(commands) 436 print >>sys.stderr, 'Expected one of: %s' % ', '.join(commands)
455 return 1 437 return 1
456 return commands[sys.argv[1]](*sys.argv[2:]) 438 return commands[sys.argv[1]](*sys.argv[2:])
457 439
458 440
459 if __name__ == '__main__': 441 if __name__ == '__main__':
460 sys.exit(main()) 442 sys.exit(main())
OLDNEW
« no previous file with comments | « build/config/win/visual_studio_version.gni ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698