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 7the android_webview continuous integration (buildbot) infrastructure. 8 9Note: The root Chromium project (which is not explicitly listed here) 10has a couple of third_party libraries checked in directly into it. This means 11that the list of third parties present in this file is not a comprehensive 12list of third party android_webview dependencies. 13""" 14 15import argparse 16import json 17import logging 18import os 19import sys 20 21 22class DepsWhitelist(object): 23 def __init__(self): 24 # If a new DEPS entry is needed for the AOSP bot to compile please add it 25 # here first. 26 # This is a staging area for deps that are accepted by the android_webview 27 # team and are in the process of having the required branches being created 28 # in the Android tree. 29 self._compile_but_not_snapshot_dependencies = [ 30 'third_party/mesa/src', 31 ] 32 33 # Dependencies that need to be merged into the Android tree. 34 self._snapshot_into_android_dependencies = [ 35 'sdch/open-vcdiff', 36 'testing/gtest', 37 'third_party/WebKit', 38 'third_party/angle_dx11', 39 ('third_party/eyesfree/src/android/java/src/com/googlecode/eyesfree/' 40 'braille'), 41 'third_party/freetype', 42 'third_party/icu', 43 'third_party/leveldatabase/src', 44 'third_party/libjingle/source/talk', 45 'third_party/libphonenumber/src/phonenumbers', 46 'third_party/libphonenumber/src/resources', 47 'third_party/openssl', 48 'third_party/opus/src', 49 'third_party/ots', 50 'third_party/skia/gyp', 51 'third_party/skia/include', 52 'third_party/skia/src', 53 'third_party/smhasher/src', 54 'third_party/v8-i18n', 55 'third_party/yasm/source/patched-yasm', 56 'tools/grit', 57 'tools/gyp', 58 'v8', 59 ] 60 61 # Dependencies required to build android_webview. 62 self._compile_dependencies = (self._snapshot_into_android_dependencies + 63 self._compile_but_not_snapshot_dependencies) 64 65 # Dependencies required to run android_webview tests but not required to 66 # compile. 67 self._test_data_dependencies = [ 68 'chrome/test/data/perf/third_party/octane', 69 ] 70 71 @staticmethod 72 def _read_deps_file(deps_file_path): 73 class FileImplStub(object): 74 """Stub for the File syntax.""" 75 def __init__(self, file_location): 76 pass 77 78 @staticmethod 79 def GetPath(): 80 return '' 81 82 @staticmethod 83 def GetFilename(): 84 return '' 85 86 @staticmethod 87 def GetRevision(): 88 return None 89 90 def from_stub(__, _=None): 91 """Stub for the From syntax.""" 92 return '' 93 94 class VarImpl(object): 95 def __init__(self, custom_vars, local_scope): 96 self._custom_vars = custom_vars 97 self._local_scope = local_scope 98 99 def Lookup(self, var_name): 100 """Implements the Var syntax.""" 101 if var_name in self._custom_vars: 102 return self._custom_vars[var_name] 103 elif var_name in self._local_scope.get("vars", {}): 104 return self._local_scope["vars"][var_name] 105 raise Exception("Var is not defined: %s" % var_name) 106 107 local_scope = {} 108 var = VarImpl({}, local_scope) 109 global_scope = { 110 'File': FileImplStub, 111 'From': from_stub, 112 'Var': var.Lookup, 113 'deps_os': {}, 114 } 115 execfile(deps_file_path, global_scope, local_scope) 116 deps = local_scope.get('deps', {}) 117 deps_os = local_scope.get('deps_os', {}) 118 for os_specific_deps in deps_os.itervalues(): 119 deps.update(os_specific_deps) 120 return deps.keys() 121 122 def _make_gclient_blacklist(self, deps_file_path, whitelisted_deps): 123 """Calculates the list of deps that need to be excluded from the deps_file 124 so that the only deps left are the one in the whitelist.""" 125 all_deps = self._read_deps_file(deps_file_path) 126 # The list of deps read from the DEPS file are prefixed with the source 127 # tree root, which is 'src' for Chromium. 128 def prepend_root(path): 129 return os.path.join('src', path) 130 whitelisted_deps = map(prepend_root, whitelisted_deps) 131 deps_blacklist = set(all_deps).difference(set(whitelisted_deps)) 132 return dict(map(lambda(x): (x, None), deps_blacklist)) 133 134 def get_deps_for_android_build(self, deps_file_path): 135 """This is used to calculate the custom_deps list for the Android bot. 136 """ 137 if not deps_file_path: 138 raise Exception('You need to specify a DEPS file path.') 139 return self._make_gclient_blacklist(deps_file_path, 140 self._compile_dependencies) 141 142 def get_deps_for_android_build_and_test(self, deps_file_path): 143 """This is used to calculate the custom_deps list for the Android perf bot. 144 """ 145 if not deps_file_path: 146 raise Exception('You need to specify a DEPS file path.') 147 return self._make_gclient_blacklist(deps_file_path, 148 self._compile_dependencies + 149 self._test_data_dependencies) 150 151 def get_deps_for_android_merge(self, _): 152 """Calculates the list of deps that need to be merged into the Android tree 153 in order to build the C++ and Java android_webview code.""" 154 return self._snapshot_into_android_dependencies 155 156 def get_deps_for_license_check(self, _): 157 """Calculates the list of deps that need to be checked for Android license 158 compatibility""" 159 return self._compile_dependencies 160 161 def execute_method(self, method_name, deps_file_path): 162 methods = { 163 'android_build': self.get_deps_for_android_build, 164 'android_build_and_test': 165 self.get_deps_for_android_build_and_test, 166 'android_merge': self.get_deps_for_android_merge, 167 'license_check': self.get_deps_for_license_check 168 } 169 if not method_name in methods: 170 raise Exception('Method name %s is not valid. Valid choices are %s' % 171 (method_name, methods.keys())) 172 return methods[method_name](deps_file_path) 173 174def main(): 175 parser = argparse.ArgumentParser() 176 parser.add_argument('--method', help='Method to use to fetch from whitelist.', 177 required=True) 178 parser.add_argument('--path-to-deps', help='Path to DEPS file.') 179 parser.add_argument('--output-json', help='Name of file to write output to.') 180 parser.add_argument('verbose', action='store_true', default=False) 181 opts = parser.parse_args() 182 183 logging.getLogger().setLevel(logging.DEBUG if opts.verbose else logging.WARN) 184 185 deps_whitelist = DepsWhitelist() 186 blacklist = deps_whitelist.execute_method(opts.method, opts.path_to_deps) 187 188 if (opts.output_json): 189 output_dict = { 190 'blacklist' : blacklist 191 } 192 with open(opts.output_json, 'w') as output_json_file: 193 json.dump(output_dict, output_json_file) 194 else: 195 print blacklist 196 197 return 0 198 199 200if __name__ == '__main__': 201 sys.exit(main()) 202