File: build_nexe_tools.py

package info (click to toggle)
chromium-browser 41.0.2272.118-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie-kfreebsd
  • size: 2,189,132 kB
  • sloc: cpp: 9,691,462; ansic: 3,341,451; python: 712,689; asm: 518,779; xml: 208,926; java: 169,820; sh: 119,353; perl: 68,907; makefile: 28,311; yacc: 13,305; objc: 11,385; tcl: 3,186; cs: 2,225; sql: 2,217; lex: 2,215; lisp: 1,349; pascal: 1,256; awk: 407; ruby: 155; sed: 53; php: 14; exp: 11
file content (136 lines) | stat: -rw-r--r-- 4,374 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/usr/bin/python
# Copyright 2014 The Native Client Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Utilities for running build commands.

A set of utilities for running build commands.
"""

import os
import subprocess
import sys
import tempfile
import time

sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import pynacl.platform

class Error(Exception):
  pass


def FixPath(path):
  # On Windows, |path| can be a long relative path: ..\..\..\..\out\Foo\bar...
  # If the full path -- os.path.join(os.getcwd(), path) -- is longer than 255
  # characters, then any operations that open or check for existence will fail.
  # We can't use os.path.abspath here, because that calls into a Windows
  # function that still has the path length limit. Instead, we'll cheat and
  # normalize the path lexically.
  path = os.path.normpath(os.path.join(os.getcwd(), path))
  if pynacl.platform.IsWindows():
    if len(path) > 255:
      raise Error('Path "%s" is too long (%d characters), and will fail.' % (
          path, len(path)))
  return path


def IsFile(path):
  return os.path.isfile(FixPath(path))


def MakeDir(outdir):
  outdir = FixPath(outdir)
  if outdir and not os.path.exists(outdir):
    # There may be a race creating this directory, so ignore failure.
    try:
      os.makedirs(outdir)
    except OSError:
      pass


def RemoveFile(path):
  os.remove(FixPath(path))


class CommandRunner(object):
  """Basic commandline runner that can run and log commands."""

  def __init__(self, options):
    self.deferred_log = []
    self.commands_are_scripts = False
    self.verbose = options.verbose

  def SetCommandsAreScripts(self, v):
    self.commands_are_scripts = v

  def Log(self, msg):
    if self.verbose:
      sys.stderr.write(str(msg) + '\n')
    else:
      self.deferred_log.append(str(msg) + '\n')

  def EmitDeferredLog(self):
    for line in self.deferred_log:
      sys.stderr.write(line)
    self.deferred_log = []

  def CleanOutput(self, out):
    if IsFile(out):
      # Since nobody can remove a file opened by somebody else on Windows,
      # we will retry removal.  After trying certain times, we gives up
      # and reraise the WindowsError.
      retry = 0
      while True:
        try:
          RemoveFile(out)
          return
        except WindowsError, inst:
          if retry > 5:
            raise Error('FAILED to CleanOutput: ' + out)
          self.Log('WindowsError %s while removing %s retry=%d' %
                   (inst, out, retry))
        sleep_time = 2**retry
        sleep_time = sleep_time if sleep_time < 10 else 10
        time.sleep(sleep_time)
        retry += 1

  def Run(self, cmd_line, get_output=False, normalize_slashes=True,
          possibly_script=True, **kwargs):
    """Helper which runs a command line.

    Returns the error code if get_output is False.
    Returns the output if get_output is True.
    """
    if normalize_slashes:
      # Use POSIX style path on Windows for POSIX based toolchains
      # (just for arguments, not for the path to the command itself).
      # If Run() is not invoking a POSIX based toolchain there is no
      # need to do this normalization.
      cmd_line = ([cmd_line[0]] +
                  [cmd.replace('\\', '/') for cmd in cmd_line[1:]])
    # Windows has a command line length limitation of 8191 characters,
    # so store commands in a response file ("@foo") if needed.
    temp_file = None
    if len(' '.join(cmd_line)) > 8000:
      with tempfile.NamedTemporaryFile(delete=False) as temp_file:
        temp_file.write(' '.join(cmd_line[1:]))
      cmd_line = [cmd_line[0], '@' + temp_file.name]

    self.Log(' '.join(cmd_line))
    try:
      runner = subprocess.check_output if get_output else subprocess.call
      if (possibly_script and self.commands_are_scripts and
          pynacl.platform.IsWindows()):
        # Executables that are scripts and not binaries don't want to run
        # on Windows without a shell.
        result = runner(' '.join(cmd_line), shell=True, **kwargs)
      else:
        result = runner(cmd_line, **kwargs)
    except Exception as err:
      raise Error('%s\nFAILED: %s' % (' '.join(cmd_line), str(err)))
    finally:
      if temp_file is not None:
        RemoveFile(temp_file.name)
    return result