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

Side by Side Diff: build/toolchain/win/setup_toolchain.py

Issue 2023703002: Beginning work on GN build (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Really add //build. Add dart_bootstrap rule. Created 4 years, 6 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/toolchain/win/midl.gni ('k') | pkg/BUILD.gn » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Copyright (c) 2013 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.
4 #
5 # Copies the given "win tool" (which the toolchain uses to wrap compiler
6 # invocations) and the environment blocks for the 32-bit and 64-bit builds on
7 # Windows to the build directory.
8 #
9 # The arguments are the visual studio install location and the location of the
10 # win tool. The script assumes that the root build directory is the current dir
11 # and the files will be written to the current directory.
12
13 import errno
14 import json
15 import os
16 import re
17 import subprocess
18 import sys
19
20 SCRIPT_DIR = os.path.dirname(__file__)
21
22 def _ExtractImportantEnvironment(output_of_set):
23 """Extracts environment variables required for the toolchain to run from
24 a textual dump output by the cmd.exe 'set' command."""
25 envvars_to_save = (
26 'goma_.*', # TODO(scottmg): This is ugly, but needed for goma.
27 'include',
28 'lib',
29 'libpath',
30 'path',
31 'pathext',
32 'systemroot',
33 'temp',
34 'tmp',
35 )
36 env = {}
37 # This occasionally happens and leads to misleading SYSTEMROOT error messages
38 # if not caught here.
39 if output_of_set.count('=') == 0:
40 raise Exception('Invalid output_of_set. Value is:\n%s' % output_of_set)
41 for line in output_of_set.splitlines():
42 for envvar in envvars_to_save:
43 if re.match(envvar + '=', line.lower()):
44 var, setting = line.split('=', 1)
45 if envvar == 'path':
46 # Our own rules (for running gyp-win-tool) and other actions in
47 # Chromium rely on python being in the path. Add the path to this
48 # python here so that if it's not in the path when ninja is run
49 # later, python will still be found.
50 setting = os.path.dirname(sys.executable) + os.pathsep + setting
51 env[var.upper()] = setting
52 break
53 if sys.platform in ('win32', 'cygwin'):
54 for required in ('SYSTEMROOT', 'TEMP', 'TMP'):
55 if required not in env:
56 raise Exception('Environment variable "%s" '
57 'required to be set to valid path' % required)
58 return env
59
60
61 def _DetectVisualStudioPath():
62 """Return path to the GYP_MSVS_VERSION of Visual Studio.
63 """
64
65 # Use the code in build/vs_toolchain.py to avoid duplicating code.
66 chromium_dir = os.path.abspath(os.path.join(SCRIPT_DIR, '..', '..', '..'))
67 sys.path.append(os.path.join(chromium_dir, 'build'))
68 import vs_toolchain
69 return vs_toolchain.DetectVisualStudioPath()
70
71
72 def _LoadEnvFromBat(args):
73 """Given a bat command, runs it and returns env vars set by it."""
74 args = args[:]
75 args.extend(('&&', 'set'))
76 popen = subprocess.Popen(
77 args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
78 variables, _ = popen.communicate()
79 if popen.returncode != 0:
80 raise Exception('"%s" failed with error %d' % (args, popen.returncode))
81 return variables
82
83
84 def _LoadToolchainEnv(cpu, sdk_dir):
85 """Returns a dictionary with environment variables that must be set while
86 running binaries from the toolchain (e.g. INCLUDE and PATH for cl.exe)."""
87 # Check if we are running in the SDK command line environment and use
88 # the setup script from the SDK if so. |cpu| should be either
89 # 'x86' or 'x64'.
90 assert cpu in ('x86', 'x64')
91 if bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', 1))) and sdk_dir:
92 # Load environment from json file.
93 env = os.path.normpath(os.path.join(sdk_dir, 'Bin/SetEnv.%s.json' % cpu))
94 env = json.load(open(env))['env']
95 for k in env:
96 entries = [os.path.join(*([os.path.join(sdk_dir, 'bin')] + e))
97 for e in env[k]]
98 # clang-cl wants INCLUDE to be ;-separated even on non-Windows,
99 # lld-link wants LIB to be ;-separated even on non-Windows. Path gets :.
100 # The separator for INCLUDE here must match the one used in main() below.
101 sep = os.pathsep if k == 'PATH' else ';'
102 env[k] = sep.join(entries)
103 # PATH is a bit of a special case, it's in addition to the current PATH.
104 env['PATH'] = env['PATH'] + os.pathsep + os.environ['PATH']
105 # Augment with the current env to pick up TEMP and friends.
106 for k in os.environ:
107 if k not in env:
108 env[k] = os.environ[k]
109
110 varlines = []
111 for k in sorted(env.keys()):
112 varlines.append('%s=%s' % (str(k), str(env[k])))
113 variables = '\n'.join(varlines)
114
115 # Check that the json file contained the same environment as the .cmd file.
116 if sys.platform in ('win32', 'cygwin'):
117 script = os.path.normpath(os.path.join(sdk_dir, 'Bin/SetEnv.cmd'))
118 assert _ExtractImportantEnvironment(variables) == \
119 _ExtractImportantEnvironment(_LoadEnvFromBat([script, '/' + cpu]))
120 else:
121 if 'GYP_MSVS_OVERRIDE_PATH' not in os.environ:
122 os.environ['GYP_MSVS_OVERRIDE_PATH'] = _DetectVisualStudioPath()
123 # We only support x64-hosted tools.
124 script_path = os.path.normpath(os.path.join(
125 os.environ['GYP_MSVS_OVERRIDE_PATH'],
126 'VC/vcvarsall.bat'))
127 if not os.path.exists(script_path):
128 raise Exception('%s is missing - make sure VC++ tools are installed.' %
129 script_path)
130 args = [script_path, 'amd64_x86' if cpu == 'x86' else 'amd64']
131 variables = _LoadEnvFromBat(args)
132 return _ExtractImportantEnvironment(variables)
133
134
135 def _FormatAsEnvironmentBlock(envvar_dict):
136 """Format as an 'environment block' directly suitable for CreateProcess.
137 Briefly this is a list of key=value\0, terminated by an additional \0. See
138 CreateProcess documentation for more details."""
139 block = ''
140 nul = '\0'
141 for key, value in envvar_dict.iteritems():
142 block += key + '=' + value + nul
143 block += nul
144 return block
145
146
147 def _CopyTool(source_path):
148 """Copies the given tool to the current directory, including a warning not
149 to edit it."""
150 with open(source_path) as source_file:
151 tool_source = source_file.readlines()
152
153 # Add header and write it out to the current directory (which should be the
154 # root build dir). Don't write the file if a matching file already exists
155 # because that causes a cascade of unnecessary rebuilds.
156 match = False
157 contents = ''.join([tool_source[0],
158 '# Generated by setup_toolchain.py do not edit.\n']
159 + tool_source[1:])
160 out_path = 'gyp-win-tool'
161 try:
162 with open(out_path, 'rb') as read_tool_file:
163 existing_contents = read_tool_file.read()
164 if existing_contents == contents:
165 match = True
166 except:
167 pass
168 if not match:
169 with open(out_path, 'wb') as write_tool_file:
170 write_tool_file.write(contents)
171
172
173 def main():
174 if len(sys.argv) != 7:
175 print('Usage setup_toolchain.py '
176 '<visual studio path> <win tool path> <win sdk path> '
177 '<runtime dirs> <target_cpu> <include prefix>')
178 sys.exit(2)
179 tool_source = sys.argv[2]
180 win_sdk_path = sys.argv[3]
181 runtime_dirs = sys.argv[4]
182 target_cpu = sys.argv[5]
183 include_prefix = sys.argv[6]
184
185 _CopyTool(tool_source)
186
187 cpus = ('x86', 'x64')
188 assert target_cpu in cpus
189 vc_bin_dir = ''
190 include = ''
191
192 # TODO(scottmg|goma): Do we need an equivalent of
193 # ninja_use_custom_environment_files?
194
195 for cpu in cpus:
196 # Extract environment variables for subprocesses.
197 env = _LoadToolchainEnv(cpu, win_sdk_path)
198 env['PATH'] = runtime_dirs + os.pathsep + env['PATH']
199
200 if cpu == target_cpu:
201 for path in env['PATH'].split(os.pathsep):
202 if os.path.exists(os.path.join(path, 'cl.exe')):
203 vc_bin_dir = os.path.realpath(path)
204 break
205 # The separator for INCLUDE here must match the one used in
206 # _LoadToolchainEnv() above.
207 include = ' '.join([include_prefix + p
208 for p in env['INCLUDE'].split(';')])
209
210 env_block = _FormatAsEnvironmentBlock(env)
211 with open('environment.' + cpu, 'wb') as f:
212 f.write(env_block)
213
214 # Create a store app version of the environment.
215 if 'LIB' in env:
216 env['LIB'] = env['LIB'] .replace(r'\VC\LIB', r'\VC\LIB\STORE')
217 if 'LIBPATH' in env:
218 env['LIBPATH'] = env['LIBPATH'].replace(r'\VC\LIB', r'\VC\LIB\STORE')
219 env_block = _FormatAsEnvironmentBlock(env)
220 with open('environment.winrt_' + cpu, 'wb') as f:
221 f.write(env_block)
222
223 assert vc_bin_dir
224 assert '"' not in vc_bin_dir
225 print 'vc_bin_dir = "%s"' % vc_bin_dir
226 assert include
227 assert '"' not in include
228 print 'include_flags = "%s"' % include
229
230 if __name__ == '__main__':
231 main()
OLDNEW
« no previous file with comments | « build/toolchain/win/midl.gni ('k') | pkg/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698