1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# Copyright (c) 2013 The Chromium Authors. All rights reserved.
2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# found in the LICENSE file.
4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)import errno
6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import os
7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import re
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)import subprocess
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import sys
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)"""
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Copies the given "win tool" (which the toolchain uses to wrap compiler
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)invocations) and the environment blocks for the 32-bit and 64-bit builds on
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Windows to the build directory.
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)The arguments are the visual studio install location and the location of the
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)win tool. The script assumes that the root build directory is the current dir
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)and the files will be written to the current directory.
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)"""
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)def ExtractImportantEnvironment():
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  """Extracts environment variables required for the toolchain from the
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  current environment."""
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  envvars_to_save = (
2623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      'goma_.*',  # TODO(scottmg): This is ugly, but needed for goma.
27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      'include',  # Needed by midl compiler.
2823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      'path',
2923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      'pathext',
3023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      'systemroot',
3123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      'temp',
3223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      'tmp',
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      )
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  result = {}
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for envvar in envvars_to_save:
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if envvar in os.environ:
3723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      envvar = envvar.lower()
3823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      if envvar == 'path':
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        # Our own rules (for running gyp-win-tool) and other actions in
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        # Chromium rely on python being in the path. Add the path to this
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        # python here so that if it's not in the path when ninja is run
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        # later, python will still be found.
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        result[envvar.upper()] = os.path.dirname(sys.executable) + \
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            os.pathsep + os.environ[envvar]
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      else:
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        result[envvar.upper()] = os.environ[envvar]
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for required in ('SYSTEMROOT', 'TEMP', 'TMP'):
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if required not in result:
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      raise Exception('Environment variable "%s" '
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                      'required to be set to valid path' % required)
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return result
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)def FormatAsEnvironmentBlock(envvar_dict):
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  """Format as an 'environment block' directly suitable for CreateProcess.
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Briefly this is a list of key=value\0, terminated by an additional \0. See
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  CreateProcess documentation for more details."""
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  block = ''
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  nul = '\0'
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for key, value in envvar_dict.iteritems():
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    block += key + '=' + value + nul
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  block += nul
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return block
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)def CopyTool(source_path):
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  """Copies the given tool to the current directory, including a warning not
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  to edit it."""
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  with open(source_path) as source_file:
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    tool_source = source_file.readlines()
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  # Add header and write it out to the current directory (which should be the
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  # root build dir).
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  with open("gyp-win-tool", 'w') as tool_file:
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    tool_file.write(''.join([tool_source[0],
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                             '# Generated by setup_toolchain.py do not edit.\n']
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                            + tool_source[1:]))
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)if len(sys.argv) != 4:
8023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  print('Usage setup_toolchain.py '
8123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        '<visual studio path> <win tool path> <win sdk path>')
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  sys.exit(2)
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)vs_path = sys.argv[1]
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)tool_source = sys.argv[2]
8523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)win_sdk_path = sys.argv[3]
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CopyTool(tool_source)
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)important_env_vars = ExtractImportantEnvironment()
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)path = important_env_vars["PATH"].split(";")
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Add 32-bit compiler path to the beginning and write the block.
9323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)path32 = [os.path.join(vs_path, "VC\\BIN")] + \
9423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)         [os.path.join(win_sdk_path, "bin\\x86")] + \
9523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)         path
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)important_env_vars["PATH"] = ";".join(path32)
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)environ = FormatAsEnvironmentBlock(important_env_vars)
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)with open('environment.x86', 'wb') as env_file:
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  env_file.write(environ)
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Add 64-bit compiler path to the beginning and write the block.
10223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)path64 = [os.path.join(vs_path, "VC\\BIN\\amd64")] + \
10323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)         [os.path.join(win_sdk_path, "bin\\x64")] + \
10423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)         path
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)important_env_vars["PATH"] = ";".join(path64)
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)environ = FormatAsEnvironmentBlock(important_env_vars)
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)with open('environment.x64', 'wb') as env_file:
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  env_file.write(environ)
109