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 win8sdk
= toolchain_data
['win8sdk']
41 wdk
= toolchain_data
['wdk']
42 # TODO(scottmg): The order unfortunately matters in these. They should be
43 # split into separate keys for x86 and x64. (See CopyVsRuntimeDlls call
44 # below). http://crbug.com/345992
45 vs2013_runtime_dll_dirs
= toolchain_data
['runtime_dirs']
47 os
.environ
['GYP_MSVS_OVERRIDE_PATH'] = toolchain
48 os
.environ
['GYP_MSVS_VERSION'] = version
49 # We need to make sure windows_sdk_path is set to the automated
50 # toolchain values in GYP_DEFINES, but don't want to override any
51 # otheroptions.express
53 gyp_defines_dict
= gyp
.NameValueListToDict(gyp
.ShlexEnv('GYP_DEFINES'))
54 gyp_defines_dict
['windows_sdk_path'] = win8sdk
55 os
.environ
['GYP_DEFINES'] = ' '.join('%s=%s' % (k
, pipes
.quote(str(v
)))
56 for k
, v
in gyp_defines_dict
.iteritems())
57 os
.environ
['WINDOWSSDKDIR'] = win8sdk
58 os
.environ
['WDK_DIR'] = wdk
59 # Include the VS runtime in the PATH in case it's not machine-installed.
60 runtime_path
= ';'.join(vs2013_runtime_dll_dirs
)
61 os
.environ
['PATH'] = runtime_path
+ ';' + os
.environ
['PATH']
62 return vs2013_runtime_dll_dirs
65 def _CopyRuntimeImpl(target
, source
):
66 """Copy |source| to |target| if it doesn't already exist or if it
69 if (os
.path
.isdir(os
.path
.dirname(target
)) and
70 (not os
.path
.isfile(target
) or
71 os
.stat(target
).st_mtime
!= os
.stat(source
).st_mtime
)):
72 print 'Copying %s to %s...' % (source
, target
)
73 if os
.path
.exists(target
):
75 shutil
.copy2(source
, target
)
78 def _CopyRuntime(target_dir
, source_dir
, dll_pattern
):
79 """Copy both the msvcr and msvcp runtime DLLs, only if the target doesn't
80 exist, but the target directory does exist."""
81 for which
in ('p', 'r'):
82 dll
= dll_pattern
% which
83 target
= os
.path
.join(target_dir
, dll
)
84 source
= os
.path
.join(source_dir
, dll
)
85 _CopyRuntimeImpl(target
, source
)
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
93 This needs to be run after gyp has been run so that the expected target
94 output directories are already created.
96 assert sys
.platform
.startswith(('win32', 'cygwin'))
98 x86
, x64
= runtime_dirs
99 out_debug
= os
.path
.join(output_dir
, 'Debug')
100 out_debug_nacl64
= os
.path
.join(output_dir
, 'Debug', 'x64')
101 out_release
= os
.path
.join(output_dir
, 'Release')
102 out_release_nacl64
= os
.path
.join(output_dir
, 'Release', 'x64')
103 out_debug_x64
= os
.path
.join(output_dir
, 'Debug_x64')
104 out_release_x64
= os
.path
.join(output_dir
, 'Release_x64')
106 if os
.path
.exists(out_debug
) and not os
.path
.exists(out_debug_nacl64
):
107 os
.makedirs(out_debug_nacl64
)
108 if os
.path
.exists(out_release
) and not os
.path
.exists(out_release_nacl64
):
109 os
.makedirs(out_release_nacl64
)
110 _CopyRuntime(out_debug
, x86
, 'msvc%s120d.dll')
111 _CopyRuntime(out_release
, x86
, 'msvc%s120.dll')
112 _CopyRuntime(out_debug_x64
, x64
, 'msvc%s120d.dll')
113 _CopyRuntime(out_release_x64
, x64
, 'msvc%s120.dll')
114 _CopyRuntime(out_debug_nacl64
, x64
, 'msvc%s120d.dll')
115 _CopyRuntime(out_release_nacl64
, x64
, 'msvc%s120.dll')
117 # Copy the PGO runtime library to the release directories.
118 if os
.environ
.get('GYP_MSVS_OVERRIDE_PATH'):
119 pgo_x86_runtime_dir
= os
.path
.join(os
.environ
.get('GYP_MSVS_OVERRIDE_PATH'),
121 pgo_x64_runtime_dir
= os
.path
.join(pgo_x86_runtime_dir
, 'amd64')
122 pgo_runtime_dll
= 'pgort120.dll'
123 source_x86
= os
.path
.join(pgo_x86_runtime_dir
, pgo_runtime_dll
)
124 if os
.path
.exists(source_x86
):
125 _CopyRuntimeImpl(os
.path
.join(out_release
, pgo_runtime_dll
), source_x86
)
126 source_x64
= os
.path
.join(pgo_x64_runtime_dir
, pgo_runtime_dll
)
127 if os
.path
.exists(source_x64
):
128 _CopyRuntimeImpl(os
.path
.join(out_release_x64
, pgo_runtime_dll
),
132 def CopyDlls(target_dir
, configuration
, target_cpu
):
133 """Copy the VS runtime DLLs into the requested directory as needed.
135 configuration is one of 'Debug' or 'Release'.
136 target_cpu is one of 'x86' or 'x64'.
138 The debug configuration gets both the debug and release DLLs; the
139 release config only the latter.
141 vs2013_runtime_dll_dirs
= SetEnvironmentAndGetRuntimeDllDirs()
142 if not vs2013_runtime_dll_dirs
:
145 x64_runtime
, x86_runtime
= vs2013_runtime_dll_dirs
146 runtime_dir
= x64_runtime
if target_cpu
== 'x64' else x86_runtime
147 _CopyRuntime(target_dir
, runtime_dir
, 'msvc%s120.dll')
148 if configuration
== 'Debug':
149 _CopyRuntime(target_dir
, runtime_dir
, 'msvc%s120d.dll')
152 def _GetDesiredVsToolchainHashes():
153 """Load a list of SHA1s corresponding to the toolchains that we want installed
155 sha1path
= os
.path
.join(script_dir
, 'toolchain_vs2013.hash')
156 with
open(sha1path
, 'rb') as f
:
157 return f
.read().strip().splitlines()
161 """Requests an update of the toolchain to the specific hashes we have at
162 this revision. The update outputs a .json of the various configuration
163 information required to pass to gyp which we use in |GetToolchainDir()|.
165 depot_tools_win_toolchain
= \
166 bool(int(os
.environ
.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1')))
167 if sys
.platform
in ('win32', 'cygwin') and depot_tools_win_toolchain
:
168 import find_depot_tools
169 depot_tools_path
= find_depot_tools
.add_depot_tools_to_path()
170 get_toolchain_args
= [
172 os
.path
.join(depot_tools_path
,
174 'get_toolchain_if_necessary.py'),
175 '--output-json', json_data_file
,
176 ] + _GetDesiredVsToolchainHashes()
177 subprocess
.check_call(get_toolchain_args
)
182 def GetToolchainDir():
183 """Gets location information about the current toolchain (must have been
184 previously updated by 'update'). This is used for the GN build."""
185 runtime_dll_dirs
= SetEnvironmentAndGetRuntimeDllDirs()
187 # If WINDOWSSDKDIR is not set, search the default SDK path and set it.
188 if not 'WINDOWSSDKDIR' in os
.environ
:
189 default_sdk_path
= 'C:\\Program Files (x86)\\Windows Kits\\8.1'
190 if os
.path
.isdir(default_sdk_path
):
191 os
.environ
['WINDOWSSDKDIR'] = default_sdk_path
193 print '''vs_path = "%s"
199 os
.environ
['GYP_MSVS_OVERRIDE_PATH'],
200 os
.environ
['WINDOWSSDKDIR'],
201 os
.environ
['GYP_MSVS_VERSION'],
202 os
.environ
.get('WDK_DIR', ''),
203 ';'.join(runtime_dll_dirs
or ['None']))
207 if not sys
.platform
.startswith(('win32', 'cygwin')):
211 'get_toolchain_dir': GetToolchainDir
,
212 'copy_dlls': CopyDlls
,
214 if len(sys
.argv
) < 2 or sys
.argv
[1] not in commands
:
215 print >>sys
.stderr
, 'Expected one of: %s' % ', '.join(commands
)
217 return commands
[sys
.argv
[1]](*sys
.argv
[2:])
220 if __name__
== '__main__':