Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / build / android / gyp / util / build_utils.py
blob1fac120658f9ee621fecbad02bce8733d5a109f6
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.
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
16 def MakeDirectory(dir_path):
17 try:
18 os.makedirs(dir_path)
19 except OSError:
20 pass
23 def DeleteDirectory(dir_path):
24 if os.path.exists(dir_path):
25 shutil.rmtree(dir_path)
28 def Touch(path):
29 MakeDirectory(os.path.dirname(path))
30 with open(path, 'a'):
31 os.utime(path, None)
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
42 def FindInDirectories(directories, filter):
43 all_files = []
44 for directory in directories:
45 all_files.extend(FindInDirectory(directory, filter))
46 return all_files
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)
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('_', '-'))
65 def ReadJson(path):
66 with open(path, 'r') as jsonfile:
67 return json.load(jsonfile)
70 # This can be used in most cases like subprocess.check_call. The output,
71 # particularly when the command fails, better highlights the command's failure.
72 # This call will directly exit on a failure in the subprocess so that no python
73 # stacktrace is printed after the output of the failed command.
74 def CheckCallDie(args, suppress_output=False, cwd=None):
75 if not cwd:
76 cwd = os.getcwd()
78 child = subprocess.Popen(args,
79 stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=cwd)
81 stdout, _ = child.communicate()
83 if child.returncode:
84 stacktrace = traceback.extract_stack()
85 print >> sys.stderr, ''.join(traceback.format_list(stacktrace))
86 # A user should be able to simply copy and paste the command that failed
87 # into their shell.
88 copyable_command = ' '.join(map(pipes.quote, args))
89 copyable_command = ('( cd ' + os.path.abspath(cwd) + '; '
90 + copyable_command + ' )')
91 print >> sys.stderr, 'Command failed:', copyable_command, '\n'
93 if stdout:
94 print stdout,
96 # Directly exit to avoid printing stacktrace.
97 sys.exit(child.returncode)
99 else:
100 if stdout and not suppress_output:
101 print stdout,
102 return stdout
105 def GetModifiedTime(path):
106 # For a symlink, the modified time should be the greater of the link's
107 # modified time and the modified time of the target.
108 return max(os.lstat(path).st_mtime, os.stat(path).st_mtime)
111 def IsTimeStale(output, inputs):
112 if not os.path.exists(output):
113 return True
115 output_time = GetModifiedTime(output)
116 for input in inputs:
117 if GetModifiedTime(input) > output_time:
118 return True
119 return False