<webview>: Move clearData() API to stable.
[chromium-blink-merge.git] / build / vs_toolchain.py
blob247703b8654094dd91eb4767eff3593eaa5561e7
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.
5 import json
6 import os
7 import pipes
8 import shutil
9 import subprocess
10 import sys
11 import tempfile
14 script_dir = os.path.dirname(os.path.realpath(__file__))
15 chrome_src = os.path.abspath(os.path.join(script_dir, os.pardir))
16 SRC_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
17 sys.path.insert(1, os.path.join(chrome_src, 'tools'))
18 sys.path.insert(0, os.path.join(chrome_src, 'tools', 'gyp', 'pylib'))
21 import gyp
24 def GetDesiredVsToolchainHashes():
25 """Load a list of SHA1s corresponding to the toolchains that we want installed
26 to build with."""
27 sha1path = os.path.join(script_dir, 'toolchain_vs2013.hash')
28 with open(sha1path, 'rb') as f:
29 return f.read().strip().splitlines()
32 def DownloadVsToolchain():
33 """Download the Visual Studio toolchain on Windows.
35 If on Windows, request that depot_tools install/update the automatic
36 toolchain, and then use it (unless opted-out) and return a tuple containing
37 the x64 and x86 paths. Otherwise return None.
38 """
39 vs2013_runtime_dll_dirs = None
40 depot_tools_win_toolchain = \
41 bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1')))
42 if sys.platform in ('win32', 'cygwin') and depot_tools_win_toolchain:
43 import find_depot_tools
44 depot_tools_path = find_depot_tools.add_depot_tools_to_path()
45 temp_handle, data_file = tempfile.mkstemp(suffix='.json')
46 os.close(temp_handle)
47 get_toolchain_args = [
48 sys.executable,
49 os.path.join(depot_tools_path,
50 'win_toolchain',
51 'get_toolchain_if_necessary.py'),
52 '--output-json', data_file,
53 ] + GetDesiredVsToolchainHashes()
54 subprocess.check_call(get_toolchain_args)
56 with open(data_file, 'r') as tempf:
57 toolchain_data = json.load(tempf)
58 os.unlink(data_file)
60 toolchain = toolchain_data['path']
61 version = toolchain_data['version']
62 version_is_pro = version[-1] != 'e'
63 win8sdk = toolchain_data['win8sdk']
64 wdk = toolchain_data['wdk']
65 # TODO(scottmg): The order unfortunately matters in these. They should be
66 # split into separate keys for x86 and x64. (See CopyVsRuntimeDlls call
67 # below). http://crbug.com/345992
68 vs2013_runtime_dll_dirs = toolchain_data['runtime_dirs']
70 os.environ['GYP_MSVS_OVERRIDE_PATH'] = toolchain
71 os.environ['GYP_MSVS_VERSION'] = version
72 # We need to make sure windows_sdk_path is set to the automated
73 # toolchain values in GYP_DEFINES, but don't want to override any
74 # otheroptions.express
75 # values there.
76 gyp_defines_dict = gyp.NameValueListToDict(gyp.ShlexEnv('GYP_DEFINES'))
77 gyp_defines_dict['windows_sdk_path'] = win8sdk
78 os.environ['GYP_DEFINES'] = ' '.join('%s=%s' % (k, pipes.quote(str(v)))
79 for k, v in gyp_defines_dict.iteritems())
80 os.environ['WINDOWSSDKDIR'] = win8sdk
81 os.environ['WDK_DIR'] = wdk
82 # Include the VS runtime in the PATH in case it's not machine-installed.
83 runtime_path = ';'.join(vs2013_runtime_dll_dirs)
84 os.environ['PATH'] = runtime_path + ';' + os.environ['PATH']
85 return vs2013_runtime_dll_dirs
88 def CopyVsRuntimeDlls(output_dir, runtime_dirs):
89 """Copies the VS runtime DLLs from the given |runtime_dirs| to the output
90 directory so that even if not system-installed, built binaries are likely to
91 be able to run.
93 This needs to be run after gyp has been run so that the expected target
94 output directories are already created.
95 """
96 assert sys.platform.startswith(('win32', 'cygwin'))
98 def copy_runtime(target_dir, source_dir, dll_pattern):
99 """Copy both the msvcr and msvcp runtime DLLs, only if the target doesn't
100 exist, but the target directory does exist."""
101 for which in ('p', 'r'):
102 dll = dll_pattern % which
103 target = os.path.join(target_dir, dll)
104 source = os.path.join(source_dir, dll)
105 # If gyp generated to that output dir, and the runtime isn't already
106 # there, then copy it over.
107 if (os.path.isdir(target_dir) and
108 (not os.path.isfile(target) or
109 os.stat(target).st_mtime != os.stat(source).st_mtime)):
110 print 'Copying %s to %s...' % (source, target)
111 if os.path.exists(target):
112 os.unlink(target)
113 shutil.copy2(source, target)
115 x86, x64 = runtime_dirs
116 out_debug = os.path.join(output_dir, 'Debug')
117 out_debug_nacl64 = os.path.join(output_dir, 'Debug', 'x64')
118 out_release = os.path.join(output_dir, 'Release')
119 out_release_nacl64 = os.path.join(output_dir, 'Release', 'x64')
120 out_debug_x64 = os.path.join(output_dir, 'Debug_x64')
121 out_release_x64 = os.path.join(output_dir, 'Release_x64')
123 if os.path.exists(out_debug) and not os.path.exists(out_debug_nacl64):
124 os.makedirs(out_debug_nacl64)
125 if os.path.exists(out_release) and not os.path.exists(out_release_nacl64):
126 os.makedirs(out_release_nacl64)
127 copy_runtime(out_debug, x86, 'msvc%s120d.dll')
128 copy_runtime(out_release, x86, 'msvc%s120.dll')
129 copy_runtime(out_debug_x64, x64, 'msvc%s120d.dll')
130 copy_runtime(out_release_x64, x64, 'msvc%s120.dll')
131 copy_runtime(out_debug_nacl64, x64, 'msvc%s120d.dll')
132 copy_runtime(out_release_nacl64, x64, 'msvc%s120.dll')
135 def main():
136 if len(sys.argv) < 2:
137 print >>sys.stderr, 'Expected either "get_toolchain_dir" or "copy_dlls"'
138 return 1
139 if sys.argv[1] == 'get_toolchain_dir':
140 DownloadVsToolchain()
141 print '["%s", "%s"]' % (
142 os.environ['GYP_MSVS_OVERRIDE_PATH'], os.environ['WINDOWSSDKDIR'])
143 else:
144 print >>sys.stderr, 'TODO: not implemented "%s"' % sys.argv[1]
145 return 1
146 return 0
149 if __name__ == '__main__':
150 sys.exit(main())