tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

wrapper_utils.py (3083B)


      1 # Copyright 2016 The Chromium Authors
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 """Helper functions for gcc_toolchain.gni wrappers."""
      6 
      7 import gzip
      8 import os
      9 import re
     10 import subprocess
     11 import shlex
     12 import shutil
     13 import sys
     14 import threading
     15 
     16 import whole_archive
     17 
     18 _BAT_PREFIX = 'cmd /c call '
     19 
     20 
     21 def _GzipThenDelete(src_path, dest_path):
     22  # Results for Android map file with GCC on a z620:
     23  # Uncompressed: 207MB
     24  # gzip -9: 16.4MB, takes 8.7 seconds.
     25  # gzip -1: 21.8MB, takes 2.0 seconds.
     26  # Piping directly from the linker via -print-map (or via -Map with a fifo)
     27  # adds a whopping 30-45 seconds!
     28  with open(src_path, 'rb') as f_in, gzip.GzipFile(dest_path, 'wb', 1) as f_out:
     29    shutil.copyfileobj(f_in, f_out)
     30  os.unlink(src_path)
     31 
     32 
     33 def CommandToRun(command):
     34  """Generates commands compatible with Windows.
     35 
     36  When running on a Windows host and using a toolchain whose tools are
     37  actually wrapper scripts (i.e. .bat files on Windows) rather than binary
     38  executables, the |command| to run has to be prefixed with this magic.
     39  The GN toolchain definitions take care of that for when GN/Ninja is
     40  running the tool directly.  When that command is passed in to this
     41  script, it appears as a unitary string but needs to be split up so that
     42  just 'cmd' is the actual command given to Python's subprocess module.
     43 
     44  Args:
     45    command: List containing the UNIX style |command|.
     46 
     47  Returns:
     48    A list containing the Windows version of the |command|.
     49  """
     50  if command[0].startswith(_BAT_PREFIX):
     51    command = command[0].split(None, 3) + command[1:]
     52  return command
     53 
     54 
     55 def RunLinkWithOptionalMapFile(command, env=None, map_file=None):
     56  """Runs the given command, adding in -Wl,-Map when |map_file| is given.
     57 
     58  Also takes care of gzipping when |map_file| ends with .gz.
     59 
     60  Args:
     61    command: List of arguments comprising the command.
     62    env: Environment variables.
     63    map_file: Path to output map_file.
     64 
     65  Returns:
     66    The exit code of running |command|.
     67  """
     68  tmp_map_path = None
     69  if map_file and map_file.endswith('.gz'):
     70    tmp_map_path = map_file + '.tmp'
     71    command.append('-Wl,-Map,' + tmp_map_path)
     72  elif map_file:
     73    command.append('-Wl,-Map,' + map_file)
     74 
     75  # We want to link rlibs as --whole-archive if they are part of a unit test
     76  # target. This is determined by switch `-LinkWrapper,add-whole-archive`.
     77  command = whole_archive.wrap_with_whole_archive(command)
     78 
     79  result = subprocess.call(command, env=env)
     80 
     81  if tmp_map_path and result == 0:
     82    threading.Thread(
     83        target=lambda: _GzipThenDelete(tmp_map_path, map_file)).start()
     84  elif tmp_map_path and os.path.exists(tmp_map_path):
     85    os.unlink(tmp_map_path)
     86 
     87  return result
     88 
     89 
     90 def CaptureCommandStderr(command, env=None):
     91  """Returns the stderr of a command.
     92 
     93  Args:
     94    command: A list containing the command and arguments.
     95    env: Environment variables for the new process.
     96  """
     97  child = subprocess.Popen(command, stderr=subprocess.PIPE, env=env)
     98  _, stderr = child.communicate()
     99  return child.returncode, stderr