Video Player: Enable chromecast support by default
[chromium-blink-merge.git] / build / vs_toolchain.py
blobaa4fec2d1282f6b10aec944417b2d4139e62759d
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
13 script_dir = os.path.dirname(os.path.realpath(__file__))
14 chrome_src = os.path.abspath(os.path.join(script_dir, os.pardir))
15 SRC_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
16 sys.path.insert(1, os.path.join(chrome_src, 'tools'))
17 sys.path.insert(0, os.path.join(chrome_src, 'tools', 'gyp', 'pylib'))
18 json_data_file = os.path.join(script_dir, 'win_toolchain.json')
21 import gyp
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)
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']
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
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.
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'))
74 def copy_runtime_impl(target, source):
75 """Copy |source| to |target| if it doesn't already exist or if it need to be
76 updated.
77 """
78 if (os.path.isdir(os.path.dirname(target)) and
79 (not os.path.isfile(target) or
80 os.stat(target).st_mtime != os.stat(source).st_mtime)):
81 print 'Copying %s to %s...' % (source, target)
82 if os.path.exists(target):
83 os.unlink(target)
84 shutil.copy2(source, target)
86 def copy_runtime(target_dir, source_dir, dll_pattern):
87 """Copy both the msvcr and msvcp runtime DLLs, only if the target doesn't
88 exist, but the target directory does exist."""
89 for which in ('p', 'r'):
90 dll = dll_pattern % which
91 target = os.path.join(target_dir, dll)
92 source = os.path.join(source_dir, dll)
93 copy_runtime_impl(target, source)
95 x86, x64 = runtime_dirs
96 out_debug = os.path.join(output_dir, 'Debug')
97 out_debug_nacl64 = os.path.join(output_dir, 'Debug', 'x64')
98 out_release = os.path.join(output_dir, 'Release')
99 out_release_nacl64 = os.path.join(output_dir, 'Release', 'x64')
100 out_debug_x64 = os.path.join(output_dir, 'Debug_x64')
101 out_release_x64 = os.path.join(output_dir, 'Release_x64')
103 if os.path.exists(out_debug) and not os.path.exists(out_debug_nacl64):
104 os.makedirs(out_debug_nacl64)
105 if os.path.exists(out_release) and not os.path.exists(out_release_nacl64):
106 os.makedirs(out_release_nacl64)
107 copy_runtime(out_debug, x86, 'msvc%s120d.dll')
108 copy_runtime(out_release, x86, 'msvc%s120.dll')
109 copy_runtime(out_debug_x64, x64, 'msvc%s120d.dll')
110 copy_runtime(out_release_x64, x64, 'msvc%s120.dll')
111 copy_runtime(out_debug_nacl64, x64, 'msvc%s120d.dll')
112 copy_runtime(out_release_nacl64, x64, 'msvc%s120.dll')
114 # Copy the PGO runtime library to the release directories.
115 if os.environ.get('GYP_MSVS_OVERRIDE_PATH'):
116 pgo_x86_runtime_dir = os.path.join(os.environ.get('GYP_MSVS_OVERRIDE_PATH'),
117 'VC', 'bin')
118 pgo_x64_runtime_dir = os.path.join(pgo_x86_runtime_dir, 'amd64')
119 pgo_runtime_dll = 'pgort120.dll'
120 source_x86 = os.path.join(pgo_x86_runtime_dir, pgo_runtime_dll)
121 if os.path.exists(source_x86):
122 copy_runtime_impl(os.path.join(out_release, pgo_runtime_dll), source_x86)
123 source_x64 = os.path.join(pgo_x64_runtime_dir, pgo_runtime_dll)
124 if os.path.exists(source_x64):
125 copy_runtime_impl(os.path.join(out_release_x64, pgo_runtime_dll),
126 source_x64)
129 def _GetDesiredVsToolchainHashes():
130 """Load a list of SHA1s corresponding to the toolchains that we want installed
131 to build with."""
132 sha1path = os.path.join(script_dir, 'toolchain_vs2013.hash')
133 with open(sha1path, 'rb') as f:
134 return f.read().strip().splitlines()
137 def Update():
138 """Requests an update of the toolchain to the specific hashes we have at
139 this revision. The update outputs a .json of the various configuration
140 information required to pass to gyp which we use in |GetToolchainDir()|.
142 depot_tools_win_toolchain = \
143 bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1')))
144 if sys.platform in ('win32', 'cygwin') and depot_tools_win_toolchain:
145 import find_depot_tools
146 depot_tools_path = find_depot_tools.add_depot_tools_to_path()
147 json_data_file = os.path.join(script_dir, 'win_toolchain.json')
148 get_toolchain_args = [
149 sys.executable,
150 os.path.join(depot_tools_path,
151 'win_toolchain',
152 'get_toolchain_if_necessary.py'),
153 '--output-json', json_data_file,
154 ] + _GetDesiredVsToolchainHashes()
155 subprocess.check_call(get_toolchain_args)
157 return 0
160 def GetToolchainDir():
161 """Gets location information about the current toolchain (must have been
162 previously updated by 'update'). This is used for the GN build."""
163 SetEnvironmentAndGetRuntimeDllDirs()
164 print '''vs_path = "%s"
165 sdk_path = "%s"
166 vs_version = "%s"
167 wdk_dir = "%s"
168 ''' % (
169 os.environ['GYP_MSVS_OVERRIDE_PATH'],
170 os.environ['WINDOWSSDKDIR'],
171 os.environ['GYP_MSVS_VERSION'],
172 os.environ['WDK_DIR'])
175 def main():
176 if not sys.platform.startswith(('win32', 'cygwin')):
177 return 0
178 commands = {
179 'update': Update,
180 'get_toolchain_dir': GetToolchainDir,
181 # TODO(scottmg): Add copy_dlls for GN builds (gyp_chromium calls
182 # CopyVsRuntimeDlls via import, currently).
184 if len(sys.argv) < 2 or sys.argv[1] not in commands:
185 print >>sys.stderr, 'Expected one of: %s' % ', '.join(commands)
186 return 1
187 return commands[sys.argv[1]]()
190 if __name__ == '__main__':
191 sys.exit(main())