Upstream version 8.37.180.0
[platform/framework/web/crosswalk.git] / src / android_webview / buildbot / deps_whitelist.py
1 #!/usr/bin/env python
2 # Copyright (c) 2013 The Chromium 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 #
6 """Logic to generate lists of DEPS used by various parts of
7 the android_webview continuous integration (buildbot) infrastructure.
8
9 Note: The root Chromium project (which is not explicitly listed here)
10 has a couple of third_party libraries checked in directly into it. This means
11 that the list of third parties present in this file is not a comprehensive
12 list of third party android_webview dependencies.
13 """
14
15 import argparse
16 import json
17 import logging
18 import os
19 import sys
20
21 # Add android_webview/tools to path to get at known_issues.
22 sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'tools'))
23 import known_issues
24
25
26 class DepsWhitelist(object):
27   def __init__(self):
28     # If a new DEPS entry is needed for the AOSP bot to compile please add it
29     # here first.
30     # This is a staging area for deps that are accepted by the android_webview
31     # team and are in the process of having the required branches being created
32     # in the Android tree.
33     self._compile_but_not_snapshot_dependencies = [
34       'third_party/libaddressinput/src/cpp',
35     ]
36
37     # Dependencies that need to be merged into the Android tree.
38     self._snapshot_into_android_dependencies = [
39       'sdch/open-vcdiff',
40       'testing/gtest',
41       'third_party/WebKit',
42       'third_party/angle',
43       'third_party/brotli/src',
44       ('third_party/eyesfree/src/android/java/src/com/googlecode/eyesfree/'
45        'braille'),
46       'third_party/freetype',
47       'third_party/icu',
48       'third_party/leveldatabase/src',
49       'third_party/libjingle/source/talk',
50       'third_party/libphonenumber/src/phonenumbers',
51       'third_party/libphonenumber/src/resources',
52       'third_party/libsrtp',
53       'third_party/libvpx',
54       'third_party/libyuv',
55       'third_party/mesa/src',
56       'third_party/openmax_dl',
57       'third_party/openssl',
58       'third_party/opus/src',
59       'third_party/ots',
60       'third_party/sfntly/cpp/src',
61       'third_party/skia',
62       'third_party/smhasher/src',
63       'third_party/usrsctp/usrsctplib',
64       'third_party/webrtc',
65       'third_party/yasm/source/patched-yasm',
66       'tools/grit',
67       'tools/gyp',
68       'v8',
69     ]
70
71     # We can save some time by not rsyncing code we don't use.
72     self._prune_from_rsync_build = [
73         'third_party/WebKit/LayoutTests',
74     ]
75
76     # Dependencies required to build android_webview.
77     self._compile_dependencies = (self._snapshot_into_android_dependencies +
78                                   self._compile_but_not_snapshot_dependencies)
79
80     # Dependencies required to run android_webview tests but not required to
81     # compile.
82     self._test_data_dependencies = [
83       'chrome/test/data/perf/third_party/octane',
84     ]
85
86   @staticmethod
87   def _read_deps_file(deps_file_path):
88     class FileImplStub(object):
89       """Stub for the File syntax."""
90       def __init__(self, file_location):
91         pass
92
93       @staticmethod
94       def GetPath():
95         return ''
96
97       @staticmethod
98       def GetFilename():
99         return ''
100
101       @staticmethod
102       def GetRevision():
103         return None
104
105     def from_stub(__, _=None):
106       """Stub for the From syntax."""
107       return ''
108
109     class VarImpl(object):
110       def __init__(self, custom_vars, local_scope):
111         self._custom_vars = custom_vars
112         self._local_scope = local_scope
113
114       def Lookup(self, var_name):
115         """Implements the Var syntax."""
116         if var_name in self._custom_vars:
117           return self._custom_vars[var_name]
118         elif var_name in self._local_scope.get("vars", {}):
119           return self._local_scope["vars"][var_name]
120         raise Exception("Var is not defined: %s" % var_name)
121
122     local_scope = {}
123     var = VarImpl({}, local_scope)
124     global_scope = {
125         'File': FileImplStub,
126         'From': from_stub,
127         'Var': var.Lookup,
128         'deps_os': {},
129     }
130     execfile(deps_file_path, global_scope, local_scope)
131     deps = local_scope.get('deps', {})
132     deps_os = local_scope.get('deps_os', {})
133     for os_specific_deps in deps_os.itervalues():
134       deps.update(os_specific_deps)
135     return deps.keys()
136
137   def _get_known_issues(self):
138     issues = []
139     for root, paths in known_issues.KNOWN_INCOMPATIBLE.items():
140       for path in paths:
141         issues.append(os.path.normpath(os.path.join(root, path)))
142     return issues
143
144   def _make_gclient_blacklist(self, deps_file_path, whitelisted_deps):
145     """Calculates the list of deps that need to be excluded from the deps_file
146     so that the only deps left are the one in the whitelist."""
147     all_deps = self._read_deps_file(deps_file_path)
148     # The list of deps read from the DEPS file are prefixed with the source
149     # tree root, which is 'src' for Chromium.
150     def prepend_root(path):
151       return os.path.join('src', path)
152     whitelisted_deps = map(prepend_root, whitelisted_deps)
153     deps_blacklist = set(all_deps).difference(set(whitelisted_deps))
154     return dict(map(lambda(x): (x, None), deps_blacklist))
155
156   def _make_blacklist(self, deps_file_path, whitelisted_deps):
157     """Calculates the list of paths we should exclude """
158     all_deps = self._read_deps_file(deps_file_path)
159     def remove_src_prefix(path):
160       return path.replace('src/', '', 1)
161     all_deps = map(remove_src_prefix, all_deps)
162     # Ignore all deps except those whitelisted.
163     blacklist = set(all_deps).difference(whitelisted_deps)
164     # Ignore the 'known issues'. Typically these are the licence incompatible
165     # things checked directly into Chromium.
166     blacklist = blacklist.union(self._get_known_issues())
167     # Ignore any other non-deps, non-licence paths we don't like.
168     blacklist = blacklist.union(self._prune_from_rsync_build)
169     return list(blacklist)
170
171   def get_deps_for_android_build(self, deps_file_path):
172     """This is used to calculate the custom_deps list for the Android bot.
173     """
174     if not deps_file_path:
175       raise Exception('You need to specify a DEPS file path.')
176     return self._make_gclient_blacklist(deps_file_path,
177                                         self._compile_dependencies)
178
179   def get_deps_for_android_build_and_test(self, deps_file_path):
180     """This is used to calculate the custom_deps list for the Android perf bot.
181     """
182     if not deps_file_path:
183       raise Exception('You need to specify a DEPS file path.')
184     return self._make_gclient_blacklist(deps_file_path,
185                                         self._compile_dependencies +
186                                         self._test_data_dependencies)
187
188   def get_blacklist_for_android_rsync_build(self, deps_file_path):
189     """Calculates the list of paths we should exclude when building Android
190     either because of license compatibility or because they are large and
191     uneeded.
192     """
193     if not deps_file_path:
194       raise Exception('You need to specify a DEPS file path.')
195     return self._make_blacklist(deps_file_path, self._compile_dependencies)
196
197   def get_deps_for_android_merge(self, _):
198     """Calculates the list of deps that need to be merged into the Android tree
199     in order to build the C++ and Java android_webview code."""
200     return self._snapshot_into_android_dependencies
201
202   def get_deps_for_license_check(self, _):
203     """Calculates the list of deps that need to be checked for Android license
204     compatibility"""
205     return self._compile_dependencies
206
207
208   def execute_method(self, method_name, deps_file_path):
209     methods = {
210       'android_build': self.get_deps_for_android_build,
211       'android_build_and_test':
212         self.get_deps_for_android_build_and_test,
213       'android_merge': self.get_deps_for_android_merge,
214       'license_check': self.get_deps_for_license_check,
215       'android_rsync_build': self.get_blacklist_for_android_rsync_build,
216     }
217     if not method_name in methods:
218       raise Exception('Method name %s is not valid. Valid choices are %s' %
219                       (method_name, methods.keys()))
220     return methods[method_name](deps_file_path)
221
222 def main():
223   parser = argparse.ArgumentParser()
224   parser.add_argument('--method', help='Method to use to fetch from whitelist.',
225                       required=True)
226   parser.add_argument('--path-to-deps', help='Path to DEPS file.')
227   parser.add_argument('--output-json', help='Name of file to write output to.')
228   parser.add_argument('verbose', action='store_true', default=False)
229   opts = parser.parse_args()
230
231   logging.getLogger().setLevel(logging.DEBUG if opts.verbose else logging.WARN)
232
233   deps_whitelist = DepsWhitelist()
234   blacklist = deps_whitelist.execute_method(opts.method, opts.path_to_deps)
235
236   if (opts.output_json):
237     output_dict = {
238         'blacklist' : blacklist
239     }
240     with open(opts.output_json, 'w') as output_json_file:
241       json.dump(output_dict, output_json_file)
242   else:
243     print blacklist
244
245   return 0
246
247
248 if __name__ == '__main__':
249   sys.exit(main())