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