#!/usr/bin/python3

import sys
import subprocess
import re
import os
import os.path
import string
import shutil
import errno
import queue
import threading
import pty
import signal

class TestThread(threading.Thread):
  """Runs 1 test and keeps track of its current state.

  A TestThread is either waiting to start the test, actually running it, done,
  running it, or stopped. The first 3 always happen in that order and can
  change to stopped at any time.

  It will finish (ie join() will return) once the process has exited, at which
  point accessing process to see the status is OK.

  Attributes:
    executable: The file path of the executable to run.
    args: A tuple of arguments to give the executable.
    env: The environment variables to set.
    done_queue: A queue.Queue to place self on once done running the test.
    start_semaphore: A threading.Semaphore to wait on before starting.
    process_lock: A lock around process.
    process: The currently executing test process or None. Synchronized by
        process_lock.
    stopped: True if we're stopped.
    output: A queue of lines of output from the test.
  """

  class OutputCopier(threading.Thread):
    """Copies the output of a test from its output pty into a queue.

    This is necessary because otherwise everything locks up if the test writes
    too much output and fills up the pty's buffer.
    """

    def __init__(self, name, fd, queue):
      super(TestThread.OutputCopier, self).__init__(
          name=(name + '.OutputCopier'))

      self.fd = fd
      self.queue = queue

    def run(self):
      with os.fdopen(self.fd) as to_read:
        try:
          for line in to_read:
            self.queue.put(line)
        except IOError as e:
# An EIO from the master side of the pty means we hit the end.
          if e.errno == errno.EIO:
            return
          else:
            raise e

  def __init__(self, executable, args, env, done_queue, start_semaphore):
    super(TestThread, self).__init__(
        name=os.path.split(executable)[-1])

    self.executable = executable
    self.args = args
    self.env = env
    self.done_queue = done_queue
    self.start_semaphore = start_semaphore

    self.output = queue.Queue()

    self.process_lock = threading.Lock()
    self.process = None
    self.stopped = False
    self.returncode = None
    self.output_copier = None

  def run(self):
    def setup_test_process():
# Shove it into its own process group so we can kill any subprocesses easily.
      os.setpgid(0, 0)

    with self.start_semaphore:
      with self.process_lock:
        if self.stopped:
          return
      test_output('Starting test %s...' % self.name)
      output_to_read, subprocess_output = pty.openpty()
      self.output_copier = TestThread.OutputCopier(self.name, output_to_read,
                                                   self.output)
      self.output_copier.start()
      try:
        with self.process_lock:
          self.process = subprocess.Popen((self.name,) + self.args,
                                          executable=self.executable,
                                          env=self.env,
                                          stderr=subprocess.STDOUT,
                                          stdout=subprocess_output,
                                          stdin=open(os.devnull, 'r'),
                                          preexec_fn=setup_test_process)
      finally:
        os.close(subprocess_output)
      self.process.wait()
      with self.process_lock:
        self.returncode = self.process.returncode
        self.process = None
        if not self.stopped:
          self.output_copier.join()
          self.done_queue.put(self)

  def kill_process(self):
    """Forcibly terminates any running process."""
    with self.process_lock:
      if not self.process:
        return
      try:
        os.killpg(self.process.pid, signal.SIGKILL)
      except OSError as e:
        if e.errno == errno.ESRCH:
          # We don't really care if it's already gone.
          pass
        else:
          raise e
  def stop(self):
    """Changes self to the stopped state."""
    with self.process_lock:
      self.stopped = True

def aos_path():
  """Returns:
    A relative path to the aos directory.
  """
  return os.path.join(os.path.dirname(__file__), '..')

def get_ip():
  """Retrieves the IP address to download code to."""
  FILENAME = os.path.normpath(os.path.join(aos_path(), '..',
                                           'output', 'ip_address.txt'))
  if not os.access(FILENAME, os.R_OK):
    os.makedirs(os.path.dirname(FILENAME), exist_ok=True)
    with open(FILENAME, 'w') as f:
      f.write('roboRIO-971.local')
  with open(FILENAME, 'r') as f:
    return f.readline().strip()

def get_temp_dir():
  """Retrieves the temporary directory to use when downloading."""
  return '/home/admin/tmp/aos_downloader'

def get_target_dir():
  """Retrieves the tempory deploy directory for downloading code."""
  return '/home/admin/robot_code'

def user_output(message):
  """Prints message to the user."""
  print('build.py: ' + message, file=sys.stderr)

# A lock to avoid making a mess intermingling test-related messages.
test_output_lock = threading.RLock()
def test_output(message):
  """Prints message to the user. Intended for messages related to tests."""
  with test_output_lock:
    print('tests: ' + message, file=sys.stdout)

def call_download_externals(argument):
  """Calls download_externals.sh for a given set of externals.

  Args:
    argument: The argument to pass to the shell script to tell it what to
        download.
  """
  subprocess.check_call(
      (os.path.join(aos_path(), 'build', 'download_externals.sh'),
       argument),
      stdin=open(os.devnull, 'r'))

class Processor(object):
  """Represents a processor architecture we can build for."""

  class UnknownPlatform(Exception):
    def __init__(self, message):
      super(Processor.UnknownPlatform, self).__init__()
      self.message = message

  class Platform(object):
    """Represents a single way to build the code."""

    def outdir(self):
      """Returns:
        The path of the directory build outputs get put in to.
      """
      return os.path.join(
          aos_path(), '..', 'output', self.outname())
    def build_ninja(self):
      """Returns:
        The path of the build.ninja file.
      """
      return os.path.join(self.outdir(), 'build.ninja')

    def do_deploy(self, dry_run, command):
      """Helper for subclasses to implement deploy.

      Args:
        dry_run: If True, prints the command instead of actually running it.
        command: A tuple of command-line arguments.
      """
      real_command = (('echo',) + command) if dry_run else command
      subprocess.check_call(real_command, stdin=open(os.devnull, 'r'))

    def deploy(self, dry_run):
      """Downloads the compiled code to the target computer."""
      raise NotImplementedError('deploy should be overriden')
    def outname(self):
      """Returns:
        The name of the directory the code will be compiled to.
      """
      raise NotImplementedError('outname should be overriden')
    def os(self):
      """Returns:
        The name of the operating system this platform is for.

        This will be used as the value of the OS gyp variable.
      """
      raise NotImplementedError('os should be overriden')
    def gyp_platform(self):
      """Returns:
        The platform name the .gyp files know.

        This will be used as the value of the PLATFORM gyp variable.
      """
      raise NotImplementedError('gyp_platform should be overriden')
    def architecture(self):
      """Returns:
        The processor architecture for this platform.

        This will be used as the value of the ARCHITECTURE gyp variable.
      """
      raise NotImplementedError('architecture should be overriden')
    def compiler(self):
      """Returns:
        The compiler used for this platform.

        Everything before the first _ will be used as the value of the
        COMPILER gyp variable and the whole thing will be used as the value
        of the FULL_COMPILER gyp variable.
      """
      raise NotImplementedError('compiler should be overriden')
    def sanitizer(self):
      """Returns:
        The sanitizer used on this platform.

        This will be used as the value of the SANITIZER gyp variable.

        "none" if there isn't one.
      """
      raise NotImplementedError('sanitizer should be overriden')
    def debug(self):
      """Returns:
        Whether or not this platform compiles with debugging information.

        The DEBUG gyp variable will be set to "yes" or "no" based on this.
      """
      raise NotImplementedError('debug should be overriden')
    def build_env(self):
      """Returns:
        A map of environment variables to set while building this platform.
      """
      raise NotImplementedError('build_env should be overriden')
    def priority(self):
      """Returns:
        A relative priority for this platform relative to other ones.

      Higher priority platforms will get built, tested, etc first. Generally,
      platforms which give higher-quality compiler errors etc should come first.
      """
      return 0

  def check_installed(self, platforms, is_deploy):
    """Makes sure that everything necessary to build platforms are installed."""
    raise NotImplementedError('check_installed should be overriden')
  def parse_platforms(self, platforms_string):
    """Args:
      string: A user-supplied string saying which platforms to select.

    Returns:
      A tuple of Platform objects.

    Raises:
      Processor.UnknownPlatform: Parsing string didn't work out.
    """
    raise NotImplementedError('parse_platforms should be overriden')
  def extra_gyp_flags(self):
    """Returns:
      A tuple of extra flags to pass to gyp (if any).
    """
    return ()
  def modify_ninja_file(self, ninja_file):
    """Modifies a freshly generated ninja file as necessary.

    Args:
      ninja_file: Path to the file to modify.
    """
    pass
  def download_externals(self, platforms):
    """Calls download_externals as appropriate to build platforms.

    Args:
      platforms: A list of platforms to download external libraries for.
    """
    raise NotImplementedError('download_externals should be overriden')

  def do_check_installed(self, other_packages):
    """Helper for subclasses to implement check_installed.

    Args:
      other_packages: A tuple of platform-specific packages to check for."""
    all_packages = other_packages
    # Necessary to build stuff.
    all_packages += ('ccache', 'make')
    # Necessary to download stuff to build.
    all_packages += ('wget', 'git', 'subversion', 'patch', 'unzip', 'bzip2')
    # Necessary to build externals stuff.
    all_packages += ('python', 'gcc', 'g++')
    not_found = []
    try:
      # TODO(brians): Check versions too.
      result = subprocess.check_output(
          ('dpkg-query',
           r"--showformat='${binary:Package}\t${db:Status-Abbrev}\n'",
           '--show') + all_packages,
          stdin=open(os.devnull, 'r'),
          stderr=subprocess.STDOUT)
      for line in result.decode('utf-8').rstrip().splitlines(True):
        match = re.match('^([^\t]+)\t[^i][^i]$', line)
        if match:
          not_found.append(match.group(1))
    except subprocess.CalledProcessError as e:
      output = e.output.decode('utf-8').rstrip()
      for line in output.splitlines(True):
        match = re.match(r'dpkg-query: no packages found matching (.*)',
                         line)
        if match:
          not_found.append(match.group(1))
    if not_found:
      user_output('Some packages not installed: %s.' % ', '.join(not_found))
      user_output('Try something like `sudo apt-get install %s`.' %
                  ' '.join(not_found))
      exit(1)

class PrimeProcessor(Processor):
  """A Processor subclass for building prime code."""

  class Platform(Processor.Platform):
    def __init__(self, architecture, folder, compiler, debug, sanitizer):
      super(PrimeProcessor.Platform, self).__init__()

      self.__architecture = architecture
      self.__folder = folder
      self.__compiler = compiler
      self.__debug = debug
      self.__sanitizer = sanitizer

    def __repr__(self):
      return 'PrimeProcessor.Platform(architecture=%s, compiler=%s, debug=%s' \
          ', sanitizer=%s)' \
          % (self.architecture(), self.compiler(), self.debug(),
             self.sanitizer())
    def __str__(self):
      return '%s-%s-%s%s-%s' % (self.architecture(), self.folder(),
                                self.compiler(),
                                '-debug' if self.debug() else '',
                                self.sanitizer())

    def os(self):
      return 'linux'
    def gyp_platform(self):
      return '%s-%s-%s' % (self.os(), self.architecture(), self.compiler())
    def architecture(self):
      return self.__architecture
    def folder(self):
      return self.__folder
    def compiler(self):
      return self.__compiler
    def sanitizer(self):
      return self.__sanitizer
    def debug(self):
      return self.__debug

    def outname(self):
      return str(self)

    def priority(self):
      r = 0
      if self.compiler() == 'clang':
        r += 100
      if self.sanitizer() != 'none':
        r -= 50
      elif self.debug():
        r -= 10
      if self.architecture() == 'amd64':
        r += 5
      return r

    def deploy(self, dry_run):
      """Downloads code to the prime in a way that avoids clashing too badly with
      starter (like the naive download everything one at a time)."""
      if not self.architecture().endswith('_frc'):
        raise Exception("Don't know how to download code to a %s." %
                        self.architecture())
      SUM = 'md5sum'
      TARGET_DIR = get_target_dir()
      TEMP_DIR = get_temp_dir()
      TARGET = 'admin@' + get_ip()

      from_dir = os.path.join(self.outdir(), 'outputs')
      sums = subprocess.check_output((SUM,) + tuple(os.listdir(from_dir)),
                                     stdin=open(os.devnull, 'r'),
                                     cwd=from_dir)
      to_download = subprocess.check_output(
          ('ssh', TARGET,
           """rm -rf {TMPDIR} && mkdir -p {TMPDIR} && \\
             mkdir -p {TO_DIR} && cd {TO_DIR} \\
             && echo '{SUMS}' | {SUM} -c \\
             |& grep -F FAILED | sed 's/^\\(.*\\): FAILED.*$/\\1/g'""".
           format(TMPDIR=TEMP_DIR, TO_DIR=TARGET_DIR, SUMS=sums.decode('utf-8'),
                  SUM=SUM)))
      if not to_download:
        user_output("Nothing to download")
        return
      self.do_deploy(
          dry_run,
          ('scp', '-o', 'Compression yes')
          + tuple([os.path.join(from_dir, f) for f in to_download.decode('utf-8').split('\n')[:-1]])
          + (('%s:%s' % (TARGET, TEMP_DIR)),))
      if not dry_run:
        mv_cmd = ['mv {TMPDIR}/* {TO_DIR} ']
        mv_cmd.append('&& chmod u+s {TO_DIR}/starter_exe ')
        mv_cmd.append('&& echo \'Done moving new executables into place\' ')
        mv_cmd.append('&& bash -c \'sync && sync && sync\'')
        subprocess.check_call(
            ('ssh', TARGET,
             ''.join(mv_cmd).format(TMPDIR=TEMP_DIR, TO_DIR=TARGET_DIR)))

    def build_env(self):
      OTHER_SYSROOT = '/usr/lib/llvm-3.5/'
      SYMBOLIZER_PATH = OTHER_SYSROOT + 'bin/llvm-symbolizer'
      r = {}
      if self.sanitizer() == 'address':
        r['ASAN_SYMBOLIZER_PATH'] = SYMBOLIZER_PATH
        r['ASAN_OPTIONS'] = \
            'detect_leaks=1:check_initialization_order=1:strict_init_order=1' \
            ':detect_stack_use_after_return=1:detect_odr_violation=2' \
            ':allow_user_segv_handler=1'
      elif self.sanitizer() == 'memory':
        r['MSAN_SYMBOLIZER_PATH'] = SYMBOLIZER_PATH
      elif self.sanitizer() == 'thread':
        r['TSAN_OPTIONS'] = 'external_symbolizer_path=' + SYMBOLIZER_PATH
        # This is apparently the default for newer versions, which disagrees
        # with documentation, so just turn it on explicitly.
        r['TSAN_OPTIONS'] += ':detect_deadlocks=1'
        # Print more useful stacks for mutex locking order problems.
        r['TSAN_OPTIONS'] += ':second_deadlock_stack=1'

      r['CCACHE_COMPRESS'] = 'yes'
      r['CCACHE_DIR'] = os.path.abspath(os.path.join(aos_path(), '..', 'output',
                                                     'ccache_dir'))
      r['CCACHE_HASHDIR'] = 'yes'
      if self.compiler().startswith('clang'):
        # clang doesn't like being run directly on the preprocessed files.
        r['CCACHE_CPP2'] = 'yes'
      # Without this, ccache slows down because of the generated header files.
      # The race condition that this opens up isn't a problem because the build
      # system finishes modifying header files before compiling anything that
      # uses them.
      r['CCACHE_SLOPPINESS'] = 'include_file_mtime'

      if self.architecture() == 'amd64':
        r['PATH'] = os.path.join(aos_path(), 'build', 'bin-ld.gold') + \
            ':' + os.environ['PATH']

      return r

  ARCHITECTURES = ('arm_frc', 'amd64')
  COMPILERS = ('clang', 'gcc')
  SANITIZERS = ('address', 'undefined', 'integer', 'memory', 'thread', 'none')
  SANITIZER_TEST_WARNINGS = {
      'memory': (True,
"""We don't have all of the libraries instrumented which leads to lots of false
  errors with msan (especially stdlibc++).
  TODO(brians): Figure out a way to deal with it."""),
  }
  PIE_SANITIZERS = ('memory', 'thread')

  def __init__(self, folder, is_test, is_deploy):
    super(PrimeProcessor, self).__init__()

    self.__folder = folder

    platforms = []
    for architecture in PrimeProcessor.ARCHITECTURES:
      for compiler in PrimeProcessor.COMPILERS:
        for debug in [True, False]:
          if architecture == 'amd64' and compiler == 'gcc':
            # We don't have a compiler to use here.
            continue
          platforms.append(
              self.Platform(architecture, folder, compiler, debug, 'none'))
    for sanitizer in PrimeProcessor.SANITIZERS:
      for compiler in ('clang',):
        if compiler == 'gcc_4.8' and (sanitizer == 'undefined' or
                                      sanitizer == 'integer' or
                                      sanitizer == 'memory'):
          # GCC 4.8 doesn't support these sanitizers.
          continue
        if sanitizer == 'none':
          # We already added sanitizer == 'none' above.
          continue
        platforms.append(
            self.Platform('amd64', folder, compiler, True, sanitizer))
    self.__platforms = frozenset(platforms)

    if is_test:
      default_platforms = self.select_platforms(architecture='amd64',
                                                debug=True)
      for sanitizer, warning in PrimeProcessor.SANITIZER_TEST_WARNINGS.items():
        if warning[0]:
          default_platforms -= self.select_platforms(sanitizer=sanitizer)
    elif is_deploy:
      default_platforms = self.select_platforms(architecture='arm_frc',
                                                compiler='gcc',
                                                debug=False)
    else:
      default_platforms = self.select_platforms(debug=False)
    self.__default_platforms = frozenset(default_platforms)

  def folder(self):
    return self.__folder
  def platforms(self):
    return self.__platforms
  def default_platforms(self):
    return self.__default_platforms

  def download_externals(self, platforms):
    to_download = set()
    for architecture in PrimeProcessor.ARCHITECTURES:
      pie_sanitizers = set()
      for sanitizer in PrimeProcessor.PIE_SANITIZERS:
        pie_sanitizers.update(self.select_platforms(architecture=architecture,
                                                    sanitizer=sanitizer))
      if platforms & pie_sanitizers:
        to_download.add(architecture + '-fPIE')

      if platforms & (self.select_platforms(architecture=architecture) -
                      pie_sanitizers):
        to_download.add(architecture)

    for download_target in to_download:
      call_download_externals(download_target)

  def parse_platforms(self, platform_string):
    if platform_string is None:
      return self.default_platforms()
    r = self.default_platforms()
    for part in platform_string.split(','):
      if part == 'all':
        r = self.platforms()
      elif part[0] == '+':
        r = r | self.select_platforms_string(part[1:])
      elif part[0] == '-':
        r = r - self.select_platforms_string(part[1:])
      elif part[0] == '=':
        r = self.select_platforms_string(part[1:])
      else:
        selected = self.select_platforms_string(part)
        r = r - (self.platforms() - selected)
        if not r:
          r = selected
    return r

  def select_platforms(self, architecture=None, compiler=None, debug=None,
                       sanitizer=None):
    r = []
    for platform in self.platforms():
      if architecture is None or platform.architecture() == architecture:
        if compiler is None or platform.compiler() == compiler:
          if debug is None or platform.debug() == debug:
            if sanitizer is None or platform.sanitizer() == sanitizer:
              r.append(platform)
    return set(r)

  def select_platforms_string(self, platforms_string):
    architecture, compiler, debug, sanitizer = None, None, None, None
    for part in platforms_string.split('-'):
      if part in PrimeProcessor.ARCHITECTURES:
        architecture = part
      elif part in PrimeProcessor.COMPILERS:
        compiler = part
      elif part in ['debug', 'dbg']:
        debug = True
      elif part in ['release', 'nodebug', 'ndb']:
        debug = False
      elif part in PrimeProcessor.SANITIZERS:
        sanitizer = part
      elif part == 'all':
        architecture = compiler = debug = sanitizer = None
      elif part == self.folder():
        pass
      else:
        raise Processor.UnknownPlatform(
            '"%s" not recognized as a platform string component.' % part)
    return self.select_platforms(
        architecture=architecture,
        compiler=compiler,
        debug=debug,
        sanitizer=sanitizer)

  def check_installed(self, platforms, is_deploy):
    packages = set(('lzip', 'm4', 'realpath'))
    packages.add('ruby')
    packages.add('clang-3.5')
    packages.add('clang-format-3.5')
    for platform in platforms:
      if platform.compiler() == 'clang' or platform.compiler() == 'gcc_4.8':
        packages.add('clang-3.5')
      if platform.compiler() == 'gcc_4.8':
        packages.add('libcloog-isl3:amd64')
      if is_deploy:
        packages.add('openssh-client')
      elif platform.architecture == 'arm_frc':
        packages.add('gcc-4.9-arm-frc-linux-gnueabi')
        packages.add('g++-4.9-arm-frc-linux-gnueabi')

    self.do_check_installed(tuple(packages))

def strsignal(num):
  # It ends up with SIGIOT instead otherwise, which is weird.
  if num == signal.SIGABRT:
    return 'SIGABRT'
  # SIGCLD is a weird way to spell it.
  if num == signal.SIGCHLD:
    return 'SIGCHLD'

  SIGNALS_TO_NAMES = dict((getattr(signal, n), n)
                          for n in dir(signal) if n.startswith('SIG')
                          and '_' not in n)
  return SIGNALS_TO_NAMES.get(num, 'Unknown signal %d' % num)

def main():
  sys.argv.pop(0)
  exec_name = sys.argv.pop(0)
  def print_help(exit_status=None, message=None):
    if message:
      print(message)
    sys.stdout.write(
"""Usage: {name} [-j n] [action] [-n] [platform] [target|extra_flag]...
Arguments:
  -j, --jobs               Explicitly specify how many jobs to run at a time.
                           Defaults to the number of processors + 2.
  -n, --dry-run            Don't actually do whatever.
                           Currently only meaningful for deploy.
  action                   What to do. Defaults to build.
                           build: Build the code.
                           clean: Remove all the built output.
                           tests: Build and then run tests.
                           deploy: Build and then download.
                           environment: Dump the environment for building.
  platform                 What variants of the code to build.
                           Defaults to something reasonable.
                           See below for details.
  target...                Which targets to build/test/etc.
                           Defaults to everything.
  extra_flag...            Extra flags associated with the targets.
                           --gtest_*: Arguments to pass on to tests.
                           --print_logs, --log_file=*: More test arguments.

Specifying targets:
 Targets are combinations of architecture, compiler, and debug flags. Which
  ones actually get run is built up as a set. It defaults to something
  reasonable for the action (specified below).
 The platform specification (the argument given to this script) is a comma-
  separated sequence of hyphen-separated platforms, each with an optional
  prefix.
 Each selector (the things separated by commas) selects all of the platforms
  which match all of its components. Its effect on the set of current platforms
  depends on the prefix character.
 Here are the prefix characters:
    +          Adds the selected platforms.
    -          Removes the selected platforms.
    =          Sets the current set to the selected platforms.
    [none]     Removes all non-selected platforms.
               If this makes the current set empty, acts like =.
  There is also the special psuedo-platform "all" which selects all platforms.
 All of the available platforms:
  {all_platforms}
 Default platforms for deploying:
  {deploy_platforms}
 Default platforms for testing:
  {test_platforms}
 Default platforms for everything else:
  {default_platforms}

Examples of specifying targets:
 build everything: "all"
 only build things with clang: "clang"
 build everything that uses GCC 4.8 (not just the defaults): "=gcc_4.8"
 build all of the arm targets that use clang: "clang-arm" or "arm-clang"
""".format(
    name=exec_name,
    all_platforms=str_platforms(PrimeProcessor('folder', False, False).platforms()),
    deploy_platforms=str_platforms(PrimeProcessor('folder', False, True).default_platforms()),
    test_platforms=str_platforms(PrimeProcessor('folder', True, False).default_platforms()),
    default_platforms=str_platforms(PrimeProcessor('folder', False, False).default_platforms()),
    ))
    if exit_status is not None:
      sys.exit(exit_status)

  def sort_platforms(platforms):
    return sorted(
        platforms, key=lambda platform: (-platform.priority(), str(platform)))

  def str_platforms(platforms):
    r = []
    for platform in sort_platforms(platforms):
      r.append(str(platform))
    if len(r) > 1:
      r[-1] = 'and ' + r[-1]
    return ', '.join(r)

  class Arguments(object):
    def __init__(self):
      self.jobs = os.sysconf('SC_NPROCESSORS_ONLN') + 2
      self.action_name = 'build'
      self.dry_run = False
      self.targets = []
      self.platform = None
      self.extra_flags = []

  args = Arguments()

  if len(sys.argv) < 2:
    print_help(1, 'Not enough arguments')
  args.processor = sys.argv.pop(0)
  args.folder = sys.argv.pop(0)
  args.main_gyp = sys.argv.pop(0)
  VALID_ACTIONS = ['build', 'clean', 'deploy', 'tests', 'environment']
  while sys.argv:
    arg = sys.argv.pop(0)
    if arg == '-j' or arg == '--jobs':
      args.jobs = int(sys.argv.pop(0))
      continue
    if arg in VALID_ACTIONS:
      args.action_name = arg
      continue
    if arg == '-n' or arg == '--dry-run':
      if args.action_name != 'deploy':
        print_help(1, '--dry-run is only valid for deploy')
      args.dry_run = True
      continue
    if arg == '-h' or arg == '--help':
      print_help(0)
    if (re.match('^--gtest_.*$', arg) or arg == '--print-logs' or
        re.match('^--log_file=.*$', arg)):
      if args.action_name == 'tests':
        args.extra_flags.append(arg)
        continue
      else:
        print_help(1, '%s is only valid for tests' % arg)
    if args.platform:
      args.targets.append(arg)
    else:
      args.platform = arg

  if args.processor == 'prime':
    processor = PrimeProcessor(args.folder,
                               args.action_name == 'tests',
                               args.action_name == 'deploy')
  else:
    print_help(1, message='Unknown processor "%s".' % args.processor)

  unknown_platform_error = None
  try:
    platforms = processor.parse_platforms(args.platform)
  except Processor.UnknownPlatform as e:
    unknown_platform_error = e.message
    args.targets.insert(0, args.platform)
    platforms = processor.parse_platforms(None)
  if not platforms:
    print_help(1, 'No platforms selected')

  processor.check_installed(platforms, args.action_name == 'deploy')
  processor.download_externals(platforms)

  class ToolsConfig(object):
    def __init__(self):
      self.variables = {'AOS': aos_path()}
      with open(os.path.join(aos_path(), 'build', 'tools_config'), 'r') as f:
        for line in f:
          if line[0] == '#':
            pass
          elif line.isspace():
            pass
          else:
            new_name, new_value = line.rstrip().split('=')
            for name, value in self.variables.items():
              new_value = new_value.replace('${%s}' % name, value)
            self.variables[new_name] = new_value
    def __getitem__(self, key):
      return self.variables[key]

  tools_config = ToolsConfig()

  def handle_clean_error(function, path, excinfo):
    _, _ = function, path
    if issubclass(OSError, excinfo[0]):
      if excinfo[1].errno == errno.ENOENT:
        # Who cares if the file we're deleting isn't there?
        return
    raise excinfo[1]

  def need_to_run_gyp(platform):
    """Determines if we need to run gyp again or not.

    The generated build files are supposed to re-run gyp again themselves, but
    that doesn't work (or at least it used to not) and we sometimes want to
    modify the results anyways.

    Args:
      platform: The platform to check for.
    """
    if not os.path.exists(platform.build_ninja()):
      return True
    if os.path.getmtime(__file__) > os.path.getmtime(platform.build_ninja()):
      return True
    dirs = os.listdir(os.path.join(aos_path(), '..'))
    # Looking through these folders takes a long time and isn't useful.
    if dirs.count('output'):
      dirs.remove('output')
    if dirs.count('.git'):
      dirs.remove('.git')
    return not not subprocess.check_output(
        ('find',) + tuple(os.path.join(aos_path(), '..', d) for d in dirs)
        + ('-newer', platform.build_ninja(),
           '(', '-name', '*.gyp', '-or', '-name', '*.gypi', ')'),
        stdin=open(os.devnull, 'r'))

  def env(platform):
    """Makes sure we pass through important environmental variables.

    Returns:
      An environment suitable for passing to subprocess.Popen and friends.
    """
    build_env = dict(platform.build_env())
    if not 'TERM' in build_env:
      build_env['TERM'] = os.environ['TERM']
    if not 'PATH' in build_env:
      build_env['PATH'] = os.environ['PATH']
    return build_env

  sorted_platforms = sort_platforms(platforms)
  user_output('Building %s...' % str_platforms(sorted_platforms))

  if args.action_name == 'tests':
    for sanitizer, warning in PrimeProcessor.SANITIZER_TEST_WARNINGS.items():
      warned_about = platforms & processor.select_platforms(sanitizer=sanitizer)
      if warned_about:
        user_output(warning[1])
        if warning[0]:
          # TODO(brians): Add a --force flag or something to override this?
          user_output('Refusing to run tests for sanitizer %s.' % sanitizer)
          exit(1)

  num = 1
  for platform in sorted_platforms:
    user_output('Building %s (%d/%d)...' % (platform, num, len(platforms)))
    if args.action_name == 'clean':
      shutil.rmtree(platform.outdir(), onerror=handle_clean_error)
    elif args.action_name == 'environment':
      user_output('Environment for building <<END')
      for name, value in env(platform).items():
        print('%s=%s' % (name, value))
      print('END')
    else:
      if need_to_run_gyp(platform):
        user_output('Running gyp...')
        gyp = subprocess.Popen(
            (tools_config['GYP'],
             '--check',
             '--depth=%s' % os.path.join(aos_path(), '..'),
             '--no-circular-check',
             '-f', 'ninja',
             '-I%s' % os.path.join(aos_path(), 'build', 'aos.gypi'),
             '-I/dev/stdin', '-Goutput_dir=output',
             '-DOS=%s' % platform.os(),
             '-DPLATFORM=%s' % platform.gyp_platform(),
             '-DARCHITECTURE=%s' % platform.architecture(),
             '-DCOMPILER=%s' % platform.compiler().split('_')[0],
             '-DFULL_COMPILER=%s' % platform.compiler(),
             '-DDEBUG=%s' % ('yes' if platform.debug() else 'no'),
             '-DSANITIZER=%s' % platform.sanitizer(),
             '-DEXTERNALS_EXTRA=%s' %
             ('-fPIE' if platform.sanitizer() in PrimeProcessor.PIE_SANITIZERS
              else '')) +
            processor.extra_gyp_flags() + (args.main_gyp,),
            stdin=subprocess.PIPE)
        gyp.communicate(("""
{
  'target_defaults': {
    'configurations': {
      '%s': {}
    }
  }
}""" % platform.outname()).encode())
        if gyp.returncode:
          user_output("Running gyp failed!")
          exit(1)
        processor.modify_ninja_file(platform.build_ninja())
        user_output('Done running gyp')
      else:
        user_output("Not running gyp")

      try:
        call = (tools_config['NINJA'],
                '-C', platform.outdir()) + tuple(args.targets)
        if args.jobs:
          call += ('-j', str(args.jobs))
        subprocess.check_call(call,
                              stdin=open(os.devnull, 'r'),
                              env=env(platform))
      except subprocess.CalledProcessError as e:
        if unknown_platform_error is not None:
          user_output(unknown_platform_error)
        raise e

    if args.action_name == 'deploy':
      platform.deploy(args.dry_run)
    elif args.action_name == 'tests':
      dirname = os.path.join(platform.outdir(), 'tests')
      done_queue = queue.Queue()
      running = []
      test_start_semaphore = threading.Semaphore(args.jobs)
      if args.targets:
        to_run = []
        for target in args.targets:
          if target.endswith('_test'):
            to_run.append(target)
      else:
        to_run = os.listdir(dirname)
      for f in to_run:
        thread = TestThread(os.path.join(dirname, f), tuple(args.extra_flags),
                            env(platform), done_queue,
                            test_start_semaphore)
        running.append(thread)
        thread.start()
      try:
        while running:
          done = done_queue.get()
          running.remove(done)
          with test_output_lock:
            test_output('Output from test %s:' % done.name)
            try:
              while True:
                line = done.output.get(False)
                if not sys.stdout.isatty():
                  # Remove color escape codes.
                  line = re.sub(r'\x1B\[[0-9;]*[a-zA-Z]', '', line)
                sys.stdout.write(line)
            except queue.Empty:
              pass
            if not done.returncode:
              test_output('Test %s succeeded' % done.name)
            else:
              if done.returncode < 0:
                sig = -done.returncode
                test_output('Test %s was killed by signal %d (%s)' % \
                            (done.name, sig, strsignal(sig)))
              elif done.returncode != 1:
                test_output('Test %s exited with %d' % \
                            (done.name, done.returncode))
              else:
                test_output('Test %s failed' % done.name)
              user_output('Aborting because of test failure for %s.' % \
                          platform)
              exit(1)
      finally:
        if running:
          test_output('Killing other tests...')
# Stop all of them before killing processes because otherwise stopping some of
# them tends to let other ones that are waiting to start go.
          for thread in running:
            thread.stop()
          for thread in running:
            test_output('\tKilling %s' % thread.name)
            thread.kill_process()
            thread.kill_process()
          test_output('Waiting for other tests to die')
          for thread in running:
            thread.kill_process()
            thread.join()
          test_output('Done killing other tests')

    user_output('Done building %s (%d/%d)' % (platform, num, len(platforms)))
    num += 1

if __name__ == '__main__':
  main()
