• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2# Copyright 2015 The PDFium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import datetime
7import glob
8import os
9import re
10import subprocess
11import sys
12
13def os_name():
14  if sys.platform.startswith('linux'):
15    return 'linux'
16  if sys.platform.startswith('win'):
17    return 'win'
18  if sys.platform.startswith('darwin'):
19    return 'mac'
20  raise Exception('Confused, can not determine OS, aborting.')
21
22
23def RunCommand(cmd):
24  try:
25    subprocess.check_call(cmd)
26    return None
27  except subprocess.CalledProcessError as e:
28    return e
29
30
31def RunCommandPropagateErr(cmd, stdout_has_errors=False,
32                           exit_status_on_error=None):
33  """Run a command as a subprocess.
34
35  Errors in that subprocess are printed out if it returns an error exit code.
36
37  Args:
38    cmd: Command to run as a list of strings.
39    stdout_has_errors: Whether to print stdout instead of stderr on an error
40        exit.
41    exit_status_on_error: If specified, upon an error in the subprocess the
42        caller script exits immediately with the given status.
43  """
44  p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
45  output, err = p.communicate()
46
47  if p.returncode:
48    PrintErr('\nError when invoking "%s"' % ' '.join(cmd))
49    if stdout_has_errors:
50      PrintErr(output)
51
52    PrintErr(err)
53
54    if exit_status_on_error is not None:
55      sys.exit(exit_status_on_error)
56
57    return None
58
59  return output
60
61
62# RunCommandExtractHashedFiles returns a tuple: (raised_exception, hashed_files)
63# It runs the given command. If it fails it will return an exception and None.
64# If it succeeds it will return None and the list of processed files extracted
65# from the output of the command. It expects lines in this format:
66#    MD5:<path_to_image_file>:<md5_hash_in_hex>
67# The returned hashed_files is a list of (file_path, MD5-hash) pairs.
68def RunCommandExtractHashedFiles(cmd):
69  try:
70    output = subprocess.check_output(cmd, universal_newlines=True)
71    ret = []
72    for line in output.split('\n'):
73      line = line.strip()
74      if line.startswith("MD5:"):
75          ret.append([x.strip() for x in line.lstrip("MD5:").rsplit(":", 1)])
76    return None, ret
77  except subprocess.CalledProcessError as e:
78    return e, None
79
80
81class DirectoryFinder:
82  '''A class for finding directories and paths under either a standalone
83  checkout or a chromium checkout of PDFium.'''
84
85  def __init__(self, build_location):
86    # |build_location| is typically "out/Debug" or "out/Release".
87    # Expect |my_dir| to be .../pdfium/testing/tools.
88    self.my_dir = os.path.dirname(os.path.realpath(__file__))
89    self.testing_dir = os.path.dirname(self.my_dir)
90    if (os.path.basename(self.my_dir) != 'tools' or
91        os.path.basename(self.testing_dir) != 'testing'):
92      raise Exception('Confused, can not find pdfium root directory, aborting.')
93    self.pdfium_dir = os.path.dirname(self.testing_dir)
94    # Find path to build directory.  This depends on whether this is a
95    # standalone build vs. a build as part of a chromium checkout. For
96    # standalone, we expect a path like .../pdfium/out/Debug, but for
97    # chromium, we expect a path like .../src/out/Debug two levels
98    # higher (to skip over the third_party/pdfium path component under
99    # which chromium sticks pdfium).
100    self.base_dir = self.pdfium_dir
101    one_up_dir = os.path.dirname(self.base_dir)
102    two_up_dir = os.path.dirname(one_up_dir)
103    if (os.path.basename(two_up_dir) == 'src' and
104        os.path.basename(one_up_dir) == 'third_party'):
105      self.base_dir = two_up_dir
106    self.build_dir = os.path.join(self.base_dir, build_location)
107    self.os_name = os_name()
108
109  def ExecutablePath(self, name):
110    '''Finds compiled binaries under the build path.'''
111    result = os.path.join(self.build_dir, name)
112    if self.os_name == 'win':
113      result = result + '.exe'
114    return result
115
116  def ScriptPath(self, name):
117    '''Finds other scripts in the same directory as this one.'''
118    return os.path.join(self.my_dir, name)
119
120  def WorkingDir(self, other_components=''):
121    '''Places generated files under the build directory, not source dir.'''
122    result = os.path.join(self.build_dir, 'gen', 'pdfium')
123    if other_components:
124      result = os.path.join(result, other_components)
125    return result
126
127  def TestingDir(self, other_components=''):
128    '''Finds test files somewhere under the testing directory.'''
129    result = self.testing_dir
130    if other_components:
131      result = os.path.join(result, other_components)
132    return result
133
134
135def GetBooleanGnArg(arg_name, build_dir, verbose=False):
136  '''Extract the value of a boolean flag in args.gn'''
137  cwd = os.getcwd()
138  os.chdir(build_dir)
139  gn_args_output = subprocess.check_output(
140      ['gn', 'args', '.', '--list=%s' % arg_name, '--short'])
141  os.chdir(cwd)
142  arg_match_output = re.search('%s = (.*)' % arg_name, gn_args_output).group(1)
143  if verbose:
144    print >> sys.stderr, "Found '%s' for value of %s" % (arg_match_output, arg)
145  return arg_match_output == 'true'
146
147
148def PrintWithTime(s):
149  """Prints s prepended by a timestamp."""
150  print '[%s] %s' % (datetime.datetime.now().strftime("%Y%m%d %H:%M:%S"),
151                     s)
152
153
154def PrintErr(s):
155  """Prints s to stderr."""
156  print >> sys.stderr, s
157