- add sources.
[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 import traceback
14
15
16 def MakeDirectory(dir_path):
17   try:
18     os.makedirs(dir_path)
19   except OSError:
20     pass
21
22
23 def DeleteDirectory(dir_path):
24   if os.path.exists(dir_path):
25     shutil.rmtree(dir_path)
26
27
28 def Touch(path):
29   MakeDirectory(os.path.dirname(path))
30   with open(path, 'a'):
31     os.utime(path, None)
32
33
34 def FindInDirectory(directory, filter):
35   files = []
36   for root, dirnames, filenames in os.walk(directory):
37     matched_files = fnmatch.filter(filenames, filter)
38     files.extend((os.path.join(root, f) for f in matched_files))
39   return files
40
41
42 def FindInDirectories(directories, filter):
43   all_files = []
44   for directory in directories:
45     all_files.extend(FindInDirectory(directory, filter))
46   return all_files
47
48
49 def ParseGypList(gyp_string):
50   # The ninja generator doesn't support $ in strings, so use ## to
51   # represent $.
52   # TODO(cjhopman): Remove when
53   # https://code.google.com/p/gyp/issues/detail?id=327
54   # is addressed.
55   gyp_string = gyp_string.replace('##', '$')
56   return shlex.split(gyp_string)
57
58
59 def CheckOptions(options, parser, required=[]):
60   for option_name in required:
61     if not getattr(options, option_name):
62       parser.error('--%s is required' % option_name.replace('_', '-'))
63
64 def WriteJson(obj, path, only_if_changed=False):
65   old_dump = None
66   if os.path.exists(path):
67     with open(path, 'r') as oldfile:
68       old_dump = oldfile.read()
69
70   new_dump = json.dumps(obj)
71
72   if not only_if_changed or old_dump != new_dump:
73     with open(path, 'w') as outfile:
74       outfile.write(new_dump)
75
76 def ReadJson(path):
77   with open(path, 'r') as jsonfile:
78     return json.load(jsonfile)
79
80
81 # This can be used in most cases like subprocess.check_call. The output,
82 # particularly when the command fails, better highlights the command's failure.
83 # This call will directly exit on a failure in the subprocess so that no python
84 # stacktrace is printed after the output of the failed command (and will
85 # instead print a python stack trace before the output of the failed command)
86 def CheckCallDie(args, suppress_output=False, cwd=None):
87   if not cwd:
88     cwd = os.getcwd()
89
90   child = subprocess.Popen(args,
91       stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=cwd)
92
93   stdout, _ = child.communicate()
94
95   if child.returncode:
96     stacktrace = traceback.extract_stack()
97     print >> sys.stderr, ''.join(traceback.format_list(stacktrace))
98     # A user should be able to simply copy and paste the command that failed
99     # into their shell.
100     copyable_command = ' '.join(map(pipes.quote, args))
101     copyable_command = ('( cd ' + os.path.abspath(cwd) + '; '
102         + copyable_command + ' )')
103     print >> sys.stderr, 'Command failed:', copyable_command, '\n'
104
105     if stdout:
106       print stdout,
107
108     # Directly exit to avoid printing stacktrace.
109     sys.exit(child.returncode)
110
111   else:
112     if stdout and not suppress_output:
113       print stdout,
114     return stdout
115
116
117 def GetModifiedTime(path):
118   # For a symlink, the modified time should be the greater of the link's
119   # modified time and the modified time of the target.
120   return max(os.lstat(path).st_mtime, os.stat(path).st_mtime)
121
122
123 def IsTimeStale(output, inputs):
124   if not os.path.exists(output):
125     return True
126
127   output_time = GetModifiedTime(output)
128   for input in inputs:
129     if GetModifiedTime(input) > output_time:
130       return True
131   return False
132
133
134 def IsDeviceReady():
135   device_state = CheckCallDie(['adb', 'get-state'], suppress_output=True)
136   return device_state.strip() == 'device'
137
138
139 def PrintWarning(message):
140   print 'WARNING: ' + message
141
142
143 def PrintBigWarning(message):
144   print '*****     ' * 8
145   PrintWarning(message)
146   print '*****     ' * 8