Browse Source

Import build env from VS 2015

Cheng Zhao 9 years ago
parent
commit
2497c73009
4 changed files with 94 additions and 3 deletions
  1. 5 1
      script/build.py
  2. 71 0
      script/lib/env_util.py
  3. 13 0
      script/lib/util.py
  4. 5 2
      script/update.py

+ 5 - 1
script/build.py

@@ -5,7 +5,8 @@ import os
 import subprocess
 import sys
 
-from lib.util import atom_gyp
+from lib.config import get_target_arch
+from lib.util import atom_gyp, import_vs_env
 
 
 CONFIGURATIONS = ['Release', 'Debug']
@@ -15,6 +16,9 @@ SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
 def main():
   os.chdir(SOURCE_ROOT)
 
+  # Update the VS build env.
+  import_vs_env(get_target_arch())
+
   ninja = os.path.join('vendor', 'depot_tools', 'ninja')
   if sys.platform == 'win32':
     ninja += '.exe'

+ 71 - 0
script/lib/env_util.py

@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+
+from __future__ import print_function
+
+import itertools
+import subprocess
+import sys
+
+
+def validate_pair(ob):
+  if not (len(ob) == 2):
+    print("Unexpected result:", ob, file=sys.stderr)
+    return False
+  else:
+    return True
+
+
+def consume(iter):
+  try:
+    while True: next(iter)
+  except StopIteration:
+    pass
+
+
+def get_environment_from_batch_command(env_cmd, initial=None):
+  """
+  Take a command (either a single command or list of arguments)
+  and return the environment created after running that command.
+  Note that if the command must be a batch file or .cmd file, or the
+  changes to the environment will not be captured.
+
+  If initial is supplied, it is used as the initial environment passed
+  to the child process.
+  """
+  if not isinstance(env_cmd, (list, tuple)):
+    env_cmd = [env_cmd]
+  # Construct the command that will alter the environment.
+  env_cmd = subprocess.list2cmdline(env_cmd)
+  # Create a tag so we can tell in the output when the proc is done.
+  tag = 'END OF BATCH COMMAND'
+  # Construct a cmd.exe command to do accomplish this.
+  cmd = 'cmd.exe /s /c "{env_cmd} && echo "{tag}" && set"'.format(**vars())
+  # Launch the process.
+  proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=initial)
+  # Parse the output sent to stdout.
+  lines = proc.stdout
+  # Consume whatever output occurs until the tag is reached.
+  consume(itertools.takewhile(lambda l: tag not in l, lines))
+  # Define a way to handle each KEY=VALUE line.
+  handle_line = lambda l: l.rstrip().split('=',1)
+  # Parse key/values into pairs.
+  pairs = map(handle_line, lines)
+  # Make sure the pairs are valid.
+  valid_pairs = filter(validate_pair, pairs)
+  # Construct a dictionary of the pairs.
+  result = dict(valid_pairs)
+  # Let the process finish.
+  proc.communicate()
+  return result
+
+
+def get_vs_env(vs_version, arch):
+  """
+  Returns the env object for VS building environment.
+
+  The vs_version can be strings like "12.0" (e.g. VS2013), the arch has to
+  be one of "x86", "amd64", "arm", "x86_amd64", "x86_arm", "amd64_x86",
+  "amd64_arm", e.g. the args passed to vcvarsall.bat.
+  """
+  vsvarsall = "C:\\Program Files (x86)\\Microsoft Visual Studio {0}\\VC\\vcvarsall.bat".format(vs_version)
+  return get_environment_from_batch_command([vsvarsall, arch])

+ 13 - 0
script/lib/util.py

@@ -16,6 +16,7 @@ import os
 import zipfile
 
 from config import is_verbose_mode
+from env_util import get_vs_env
 
 
 def get_host_arch():
@@ -223,3 +224,15 @@ def s3put(bucket, access_key, secret_key, prefix, key_prefix, files):
   ] + files
 
   execute(args, env)
+
+
+def import_vs_env(target_arch):
+  if sys.platform == 'cygwin':
+    return
+
+  if target_arch == 'ia32':
+    vs_arch = 'amd64_x86'
+  else:
+    vs_arch = 'x86_amd64'
+  env = get_vs_env('14.0', vs_arch)
+  os.environ.update(env)

+ 5 - 2
script/update.py

@@ -7,7 +7,7 @@ import subprocess
 import sys
 
 from lib.config import get_target_arch, PLATFORM
-from lib.util import get_host_arch
+from lib.util import get_host_arch, import_vs_env
 
 
 SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
@@ -49,11 +49,14 @@ def update_gyp():
 
 
 def run_gyp(target_arch, component):
+  # Update the VS build env.
+  import_vs_env(target_arch)
+
   env = os.environ.copy()
   if PLATFORM == 'linux' and target_arch != get_host_arch():
     env['GYP_CROSSCOMPILE'] = '1'
   elif PLATFORM == 'win32':
-    env['GYP_MSVS_VERSION'] = '2013'
+    env['GYP_MSVS_VERSION'] = '2015'
   python = sys.executable
   if sys.platform == 'cygwin':
     # Force using win32 python on cygwin.