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.
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.
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.
20 def _ExtractImportantEnvironment(output_of_set
):
21 """Extracts environment variables required for the toolchain to run from
22 a textual dump output by the cmd.exe 'set' command."""
24 'goma_.*', # TODO(scottmg): This is ugly, but needed for goma.
35 for line
in output_of_set
.splitlines():
36 for envvar
in envvars_to_save
:
37 if re
.match(envvar
+ '=', line
.lower()):
38 var
, setting
= line
.split('=', 1)
40 # Our own rules (for running gyp-win-tool) and other actions in
41 # Chromium rely on python being in the path. Add the path to this
42 # python here so that if it's not in the path when ninja is run
43 # later, python will still be found.
44 setting
= os
.path
.dirname(sys
.executable
) + os
.pathsep
+ setting
45 env
[var
.upper()] = setting
47 for required
in ('SYSTEMROOT', 'TEMP', 'TMP'):
48 if required
not in env
:
49 raise Exception('Environment variable "%s" '
50 'required to be set to valid path' % required
)
54 def _SetupScript(target_cpu
, sdk_dir
):
55 """Returns a command (with arguments) to be used to set up the
57 # Check if we are running in the SDK command line environment and use
58 # the setup script from the SDK if so. |target_cpu| should be either
60 assert target_cpu
in ('x86', 'x64')
61 if bool(int(os
.environ
.get('DEPOT_TOOLS_WIN_TOOLCHAIN', 1))) and sdk_dir
:
62 return [os
.path
.normpath(os
.path
.join(sdk_dir
, 'Bin/SetEnv.Cmd')),
65 # We only support x64-hosted tools.
66 # TODO(scottmg|dpranke): Non-depot_tools toolchain: need to get Visual
67 # Studio install location from registry.
68 return [os
.path
.normpath(os
.path
.join(os
.environ
['GYP_MSVS_OVERRIDE_PATH'],
70 'amd64_x86' if target_cpu
== 'x86' else 'amd64']
73 def _FormatAsEnvironmentBlock(envvar_dict
):
74 """Format as an 'environment block' directly suitable for CreateProcess.
75 Briefly this is a list of key=value\0, terminated by an additional \0. See
76 CreateProcess documentation for more details."""
79 for key
, value
in envvar_dict
.iteritems():
80 block
+= key
+ '=' + value
+ nul
85 def _CopyTool(source_path
):
86 """Copies the given tool to the current directory, including a warning not
88 with
open(source_path
) as source_file
:
89 tool_source
= source_file
.readlines()
91 # Add header and write it out to the current directory (which should be the
93 with
open("gyp-win-tool", 'w') as tool_file
:
94 tool_file
.write(''.join([tool_source
[0],
95 '# Generated by setup_toolchain.py do not edit.\n']
100 if len(sys
.argv
) != 6:
101 print('Usage setup_toolchain.py '
102 '<visual studio path> <win tool path> <win sdk path> '
103 '<runtime dirs> <target_cpu>')
105 tool_source
= sys
.argv
[2]
106 win_sdk_path
= sys
.argv
[3]
107 runtime_dirs
= sys
.argv
[4]
108 target_cpu
= sys
.argv
[5]
110 _CopyTool(tool_source
)
112 cpus
= ('x86', 'x64')
113 assert target_cpu
in cpus
116 # TODO(scottmg|goma): Do we need an equivalent of
117 # ninja_use_custom_environment_files?
120 # Extract environment variables for subprocesses.
121 args
= _SetupScript(cpu
, win_sdk_path
)
122 args
.extend(('&&', 'set'))
123 popen
= subprocess
.Popen(
124 args
, shell
=True, stdout
=subprocess
.PIPE
, stderr
=subprocess
.STDOUT
)
125 variables
, _
= popen
.communicate()
126 env
= _ExtractImportantEnvironment(variables
)
127 env
['PATH'] = runtime_dirs
+ ';' + env
['PATH']
129 if cpu
== target_cpu
:
130 for path
in env
['PATH'].split(os
.pathsep
):
131 if os
.path
.exists(os
.path
.join(path
, 'cl.exe')):
132 vc_bin_dir
= os
.path
.realpath(path
)
135 # The Windows SDK include directories must be first. They both have a sal.h,
136 # and the SDK one is newer and the SDK uses some newer features from it not
137 # present in the Visual Studio one.
140 additional_includes
= ('{sdk_dir}\\Include\\shared;' +
141 '{sdk_dir}\\Include\\um;' +
142 '{sdk_dir}\\Include\\winrt;').format(
143 sdk_dir
=win_sdk_path
)
144 env
['INCLUDE'] = additional_includes
+ env
['INCLUDE']
145 env_block
= _FormatAsEnvironmentBlock(env
)
146 with
open('environment.' + cpu
, 'wb') as f
:
150 print 'vc_bin_dir = "%s"' % vc_bin_dir
153 if __name__
== '__main__':