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.
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')
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.
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 if not os
.path
.exists(json_data_file
):
35 with
open(json_data_file
, 'r') as tempf
:
36 toolchain_data
= json
.load(tempf
)
38 toolchain
= toolchain_data
['path']
39 version
= toolchain_data
['version']
40 win_sdk
= toolchain_data
.get('win_sdk')
42 win_sdk
= toolchain_data
['win8sdk']
43 wdk
= toolchain_data
['wdk']
44 # TODO(scottmg): The order unfortunately matters in these. They should be
45 # split into separate keys for x86 and x64. (See CopyVsRuntimeDlls call
46 # below). http://crbug.com/345992
47 vs2013_runtime_dll_dirs
= toolchain_data
['runtime_dirs']
49 os
.environ
['GYP_MSVS_OVERRIDE_PATH'] = toolchain
50 os
.environ
['GYP_MSVS_VERSION'] = version
51 # We need to make sure windows_sdk_path is set to the automated
52 # toolchain values in GYP_DEFINES, but don't want to override any
53 # otheroptions.express
55 gyp_defines_dict
= gyp
.NameValueListToDict(gyp
.ShlexEnv('GYP_DEFINES'))
56 gyp_defines_dict
['windows_sdk_path'] = win_sdk
57 os
.environ
['GYP_DEFINES'] = ' '.join('%s=%s' % (k
, pipes
.quote(str(v
)))
58 for k
, v
in gyp_defines_dict
.iteritems())
59 os
.environ
['WINDOWSSDKDIR'] = win_sdk
60 os
.environ
['WDK_DIR'] = wdk
61 # Include the VS runtime in the PATH in case it's not machine-installed.
62 runtime_path
= ';'.join(vs2013_runtime_dll_dirs
)
63 os
.environ
['PATH'] = runtime_path
+ ';' + os
.environ
['PATH']
64 return vs2013_runtime_dll_dirs
68 """Gets the standard version number ('120', '140', etc.) based on
70 if os
.environ
['GYP_MSVS_VERSION'] == '2013':
72 elif os
.environ
['GYP_MSVS_VERSION'] == '2015':
75 raise ValueError('Unexpected GYP_MSVS_VERSION')
78 def _CopyRuntimeImpl(target
, source
):
79 """Copy |source| to |target| if it doesn't already exist or if it
82 if (os
.path
.isdir(os
.path
.dirname(target
)) and
83 (not os
.path
.isfile(target
) or
84 os
.stat(target
).st_mtime
!= os
.stat(source
).st_mtime
)):
85 print 'Copying %s to %s...' % (source
, target
)
86 if os
.path
.exists(target
):
88 shutil
.copy2(source
, target
)
91 def _CopyRuntime2013(target_dir
, source_dir
, dll_pattern
):
92 """Copy both the msvcr and msvcp runtime DLLs, only if the target doesn't
93 exist, but the target directory does exist."""
94 for file_part
in ('p', 'r'):
95 dll
= dll_pattern
% file_part
96 target
= os
.path
.join(target_dir
, dll
)
97 source
= os
.path
.join(source_dir
, dll
)
98 _CopyRuntimeImpl(target
, source
)
101 def _CopyRuntime2015(target_dir
, source_dir
, dll_pattern
):
102 """Copy both the msvcp and vccorlib runtime DLLs, only if the target doesn't
103 exist, but the target directory does exist."""
104 for file_part
in ('msvcp', 'vccorlib'):
105 dll
= dll_pattern
% file_part
106 target
= os
.path
.join(target_dir
, dll
)
107 source
= os
.path
.join(source_dir
, dll
)
108 _CopyRuntimeImpl(target
, source
)
111 def CopyVsRuntimeDlls(output_dir
, runtime_dirs
):
112 """Copies the VS runtime DLLs from the given |runtime_dirs| to the output
113 directory so that even if not system-installed, built binaries are likely to
116 This needs to be run after gyp has been run so that the expected target
117 output directories are already created.
119 assert sys
.platform
.startswith(('win32', 'cygwin'))
121 x86
, x64
= runtime_dirs
122 out_debug
= os
.path
.join(output_dir
, 'Debug')
123 out_debug_nacl64
= os
.path
.join(output_dir
, 'Debug', 'x64')
124 out_release
= os
.path
.join(output_dir
, 'Release')
125 out_release_nacl64
= os
.path
.join(output_dir
, 'Release', 'x64')
126 out_debug_x64
= os
.path
.join(output_dir
, 'Debug_x64')
127 out_release_x64
= os
.path
.join(output_dir
, 'Release_x64')
129 if os
.path
.exists(out_debug
) and not os
.path
.exists(out_debug_nacl64
):
130 os
.makedirs(out_debug_nacl64
)
131 if os
.path
.exists(out_release
) and not os
.path
.exists(out_release_nacl64
):
132 os
.makedirs(out_release_nacl64
)
133 if os
.environ
.get('GYP_MSVS_VERSION') == '2015':
134 _CopyRuntime2015(out_debug
, x86
, '%s140d.dll')
135 _CopyRuntime2015(out_release
, x86
, '%s140.dll')
136 _CopyRuntime2015(out_debug_x64
, x64
, '%s140d.dll')
137 _CopyRuntime2015(out_release_x64
, x64
, '%s140.dll')
138 _CopyRuntime2015(out_debug_nacl64
, x64
, '%s140d.dll')
139 _CopyRuntime2015(out_release_nacl64
, x64
, '%s140.dll')
141 # VS2013 is the default.
142 _CopyRuntime2013(out_debug
, x86
, 'msvc%s120d.dll')
143 _CopyRuntime2013(out_release
, x86
, 'msvc%s120.dll')
144 _CopyRuntime2013(out_debug_x64
, x64
, 'msvc%s120d.dll')
145 _CopyRuntime2013(out_release_x64
, x64
, 'msvc%s120.dll')
146 _CopyRuntime2013(out_debug_nacl64
, x64
, 'msvc%s120d.dll')
147 _CopyRuntime2013(out_release_nacl64
, x64
, 'msvc%s120.dll')
149 # Copy the PGO runtime library to the release directories.
150 if os
.environ
.get('GYP_MSVS_OVERRIDE_PATH'):
151 pgo_x86_runtime_dir
= os
.path
.join(os
.environ
.get('GYP_MSVS_OVERRIDE_PATH'),
153 pgo_x64_runtime_dir
= os
.path
.join(pgo_x86_runtime_dir
, 'amd64')
154 pgo_runtime_dll
= 'pgort' + _VersionNumber() + '.dll'
155 source_x86
= os
.path
.join(pgo_x86_runtime_dir
, pgo_runtime_dll
)
156 if os
.path
.exists(source_x86
):
157 _CopyRuntimeImpl(os
.path
.join(out_release
, pgo_runtime_dll
), source_x86
)
158 source_x64
= os
.path
.join(pgo_x64_runtime_dir
, pgo_runtime_dll
)
159 if os
.path
.exists(source_x64
):
160 _CopyRuntimeImpl(os
.path
.join(out_release_x64
, pgo_runtime_dll
),
164 def CopyDlls(target_dir
, configuration
, target_cpu
):
165 """Copy the VS runtime DLLs into the requested directory as needed.
167 configuration is one of 'Debug' or 'Release'.
168 target_cpu is one of 'x86' or 'x64'.
170 The debug configuration gets both the debug and release DLLs; the
171 release config only the latter.
173 vs2013_runtime_dll_dirs
= SetEnvironmentAndGetRuntimeDllDirs()
174 if not vs2013_runtime_dll_dirs
:
177 x64_runtime
, x86_runtime
= vs2013_runtime_dll_dirs
178 runtime_dir
= x64_runtime
if target_cpu
== 'x64' else x86_runtime
180 target_dir
, runtime_dir
, 'msvc%s' + _VersionNumber() + '.dll')
181 if configuration
== 'Debug':
183 target_dir
, runtime_dir
, 'msvc%s' + _VersionNumber() + 'd.dll')
186 def _GetDesiredVsToolchainHashes():
187 """Load a list of SHA1s corresponding to the toolchains that we want installed
189 if os
.environ
.get('GYP_MSVS_VERSION') == '2015':
190 return ['49ae4b60d898182fc3f521c2fcda82c453915011']
193 return ['ee7d718ec60c2dc5d255bbe325909c2021a7efef']
197 """Requests an update of the toolchain to the specific hashes we have at
198 this revision. The update outputs a .json of the various configuration
199 information required to pass to gyp which we use in |GetToolchainDir()|.
201 depot_tools_win_toolchain
= \
202 bool(int(os
.environ
.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1')))
203 if sys
.platform
in ('win32', 'cygwin') and depot_tools_win_toolchain
:
204 import find_depot_tools
205 depot_tools_path
= find_depot_tools
.add_depot_tools_to_path()
206 get_toolchain_args
= [
208 os
.path
.join(depot_tools_path
,
210 'get_toolchain_if_necessary.py'),
211 '--output-json', json_data_file
,
212 ] + _GetDesiredVsToolchainHashes()
213 subprocess
.check_call(get_toolchain_args
)
218 def GetToolchainDir():
219 """Gets location information about the current toolchain (must have been
220 previously updated by 'update'). This is used for the GN build."""
221 runtime_dll_dirs
= SetEnvironmentAndGetRuntimeDllDirs()
223 # If WINDOWSSDKDIR is not set, search the default SDK path and set it.
224 if not 'WINDOWSSDKDIR' in os
.environ
:
225 default_sdk_path
= 'C:\\Program Files (x86)\\Windows Kits\\8.1'
226 if os
.path
.isdir(default_sdk_path
):
227 os
.environ
['WINDOWSSDKDIR'] = default_sdk_path
229 print '''vs_path = "%s"
235 os
.environ
['GYP_MSVS_OVERRIDE_PATH'],
236 os
.environ
['WINDOWSSDKDIR'],
237 os
.environ
['GYP_MSVS_VERSION'],
238 os
.environ
.get('WDK_DIR', ''),
239 ';'.join(runtime_dll_dirs
or ['None']))
243 if not sys
.platform
.startswith(('win32', 'cygwin')):
247 'get_toolchain_dir': GetToolchainDir
,
248 'copy_dlls': CopyDlls
,
250 if len(sys
.argv
) < 2 or sys
.argv
[1] not in commands
:
251 print >>sys
.stderr
, 'Expected one of: %s' % ', '.join(commands
)
253 return commands
[sys
.argv
[1]](*sys
.argv
[2:])
256 if __name__
== '__main__':