Upstream version 6.35.121.0
[platform/framework/web/crosswalk.git] / src / build / android / gyp / util / build_utils.py
1 # Copyright 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 import fnmatch
6 import json
7 import os
8 import pipes
9 import shlex
10 import shutil
11 import subprocess
12 import sys
13
14
15 def MakeDirectory(dir_path):
16   try:
17     os.makedirs(dir_path)
18   except OSError:
19     pass
20
21
22 def DeleteDirectory(dir_path):
23   if os.path.exists(dir_path):
24     shutil.rmtree(dir_path)
25
26
27 def Touch(path):
28   MakeDirectory(os.path.dirname(path))
29   with open(path, 'a'):
30     os.utime(path, None)
31
32
33 def FindInDirectory(directory, filename_filter):
34   files = []
35   for root, _dirnames, filenames in os.walk(directory):
36     matched_files = fnmatch.filter(filenames, filename_filter)
37     files.extend((os.path.join(root, f) for f in matched_files))
38   return files
39
40
41 def FindInDirectories(directories, filename_filter):
42   all_files = []
43   for directory in directories:
44     all_files.extend(FindInDirectory(directory, filename_filter))
45   return all_files
46
47
48 def ParseGypList(gyp_string):
49   # The ninja generator doesn't support $ in strings, so use ## to
50   # represent $.
51   # TODO(cjhopman): Remove when
52   # https://code.google.com/p/gyp/issues/detail?id=327
53   # is addressed.
54   gyp_string = gyp_string.replace('##', '$')
55   return shlex.split(gyp_string)
56
57
58 def CheckOptions(options, parser, required=None):
59   if not required:
60     return
61   for option_name in required:
62     if not getattr(options, option_name):
63       parser.error('--%s is required' % option_name.replace('_', '-'))
64
65 def WriteJson(obj, path, only_if_changed=False):
66   old_dump = None
67   if os.path.exists(path):
68     with open(path, 'r') as oldfile:
69       old_dump = oldfile.read()
70
71   new_dump = json.dumps(obj)
72
73   if not only_if_changed or old_dump != new_dump:
74     with open(path, 'w') as outfile:
75       outfile.write(new_dump)
76
77 def ReadJson(path):
78   with open(path, 'r') as jsonfile:
79     return json.load(jsonfile)
80
81
82 class CalledProcessError(Exception):
83   """This exception is raised when the process run by CheckOutput
84   exits with a non-zero exit code."""
85
86   def __init__(self, cwd, args, output):
87     super(CalledProcessError, self).__init__()
88     self.cwd = cwd
89     self.args = args
90     self.output = output
91
92   def __str__(self):
93     # A user should be able to simply copy and paste the command that failed
94     # into their shell.
95     copyable_command = '( cd {}; {} )'.format(os.path.abspath(self.cwd),
96         ' '.join(map(pipes.quote, self.args)))
97     return 'Command failed: {}\n{}'.format(copyable_command, self.output)
98
99
100 # This can be used in most cases like subprocess.check_output(). The output,
101 # particularly when the command fails, better highlights the command's failure.
102 # If the command fails, raises a build_utils.CalledProcessError.
103 def CheckOutput(args, cwd=None, print_stdout=False, print_stderr=True,
104                 fail_if_stderr=False):
105   if not cwd:
106     cwd = os.getcwd()
107
108   child = subprocess.Popen(args,
109       stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd)
110   stdout, stderr = child.communicate()
111
112   if child.returncode or (stderr and fail_if_stderr):
113     raise CalledProcessError(cwd, args, stdout + stderr)
114
115   if print_stdout:
116     sys.stdout.write(stdout)
117   if print_stderr:
118     sys.stderr.write(stderr)
119
120   return stdout
121
122
123 def GetModifiedTime(path):
124   # For a symlink, the modified time should be the greater of the link's
125   # modified time and the modified time of the target.
126   return max(os.lstat(path).st_mtime, os.stat(path).st_mtime)
127
128
129 def IsTimeStale(output, inputs):
130   if not os.path.exists(output):
131     return True
132
133   output_time = GetModifiedTime(output)
134   for i in inputs:
135     if GetModifiedTime(i) > output_time:
136       return True
137   return False
138
139
140 def IsDeviceReady():
141   device_state = CheckOutput(['adb', 'get-state'])
142   return device_state.strip() == 'device'
143
144
145 def PrintWarning(message):
146   print 'WARNING: ' + message
147
148
149 def PrintBigWarning(message):
150   print '*****     ' * 8
151   PrintWarning(message)
152   print '*****     ' * 8