| 
					
				 | 
			
			
				@@ -0,0 +1,943 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#!/usr/bin/env python 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+# Copyright 2020 The gRPC Authors 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+# 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+# Licensed under the Apache License, Version 2.0 (the "License"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+# you may not use this file except in compliance with the License. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+# You may obtain a copy of the License at 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+# 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#     http://www.apache.org/licenses/LICENSE-2.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+# 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+# Unless required by applicable law or agreed to in writing, software 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+# distributed under the License is distributed on an "AS IS" BASIS, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+# See the License for the specific language governing permissions and 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+# limitations under the License. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import subprocess 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import yaml 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import xml.etree.ElementTree as ET 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import os 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import sys 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import build_cleaner 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+_ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../..')) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+os.chdir(_ROOT) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def _bazel_query_xml_tree(query): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    """Get xml output of bazel query invocation, parsed as XML tree""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    output = subprocess.check_output( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ['tools/bazel', 'query', '--noimplicit_deps', '--output', 'xml', query]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return ET.fromstring(output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def _rule_dict_from_xml_node(rule_xml_node): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    result = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'class': rule_xml_node.attrib.get('class'), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'name': rule_xml_node.attrib.get('name'), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'srcs': [], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'hdrs': [], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'deps': [], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'data': [], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'tags': [], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'args': [], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'generator_function': None, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'size': None, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for child in rule_xml_node: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # all the metadata we want is stored under "list" tags 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if child.tag == 'list': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            list_name = child.attrib['name'] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if list_name in ['srcs', 'hdrs', 'deps', 'data', 'tags', 'args']: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                result[list_name] += [item.attrib['value'] for item in child] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if child.tag == 'string': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            string_name = child.attrib['name'] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if string_name in ['generator_function', 'size']: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                result[string_name] = child.attrib['value'] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return result 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def _extract_rules_from_bazel_xml(xml_tree): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    result = {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for child in xml_tree: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if child.tag == 'rule': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            rule_dict = _rule_dict_from_xml_node(child) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            rule_clazz = rule_dict['class'] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            rule_name = rule_dict['name'] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if rule_clazz in [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    'cc_library', 'cc_binary', 'cc_test', 'cc_proto_library', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    'proto_library' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ]: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if rule_name in result: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    raise Exception('Rule %s already present' % rule_name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                result[rule_name] = rule_dict 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return result 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def _get_bazel_label(target_name): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if ':' in target_name: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return '//%s' % target_name 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return '//:%s' % target_name 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def _extract_source_file_path(label): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    """Gets relative path to source file from bazel deps listing""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if label.startswith('//'): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        label = label[len('//'):] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # labels in form //:src/core/lib/surface/call_test_only.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if label.startswith(':'): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        label = label[len(':'):] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # labels in form //test/core/util:port.cc 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    label = label.replace(':', '/') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return label 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def _extract_public_headers(bazel_rule): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    """Gets list of public headers from a bazel rule""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    result = [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for dep in bazel_rule['hdrs']: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if dep.startswith('//:include/') and dep.endswith('.h'): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            result.append(_extract_source_file_path(dep)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return list(sorted(result)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def _extract_nonpublic_headers(bazel_rule): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    """Gets list of non-public headers from a bazel rule""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    result = [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for dep in bazel_rule['hdrs']: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if dep.startswith('//') and not dep.startswith( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                '//:include/') and dep.endswith('.h'): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            result.append(_extract_source_file_path(dep)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return list(sorted(result)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def _extract_sources(bazel_rule): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    """Gets list of source files from a bazel rule""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    result = [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for dep in bazel_rule['srcs']: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if dep.startswith('//') and (dep.endswith('.cc') or dep.endswith('.c') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                     or dep.endswith('.proto')): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            result.append(_extract_source_file_path(dep)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return list(sorted(result)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def _extract_deps(bazel_rule): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    """Gets list of deps from from a bazel rule""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return list(sorted(bazel_rule['deps'])) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def _create_target_from_bazel_rule(target_name, bazel_rules): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # extract the deps from bazel 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bazel_rule = bazel_rules[_get_bazel_label(target_name)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    result = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'name': target_name, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_PUBLIC_HEADERS_BAZEL': _extract_public_headers(bazel_rule), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_HEADERS_BAZEL': _extract_nonpublic_headers(bazel_rule), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_SRC_BAZEL': _extract_sources(bazel_rule), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_DEPS_BAZEL': _extract_deps(bazel_rule), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return result 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def _sort_by_build_order(lib_names, lib_dict, deps_key_name, verbose=False): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    """Sort library names to form correct build order. Use metadata from lib_dict""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # we find correct build order by performing a topological sort 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # expected output: if library B depends on A, A should be listed first 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # all libs that are not in the dictionary are considered external. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    external_deps = list( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        sorted(filter(lambda lib_name: lib_name not in lib_dict, lib_names))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if verbose: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        print('topo_ordering ' + str(lib_names)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        print('    external_deps ' + str(external_deps)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    result = list(external_deps)  # external deps will be listed first 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    while len(result) < len(lib_names): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        more_results = [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for lib in lib_names: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if lib not in result: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                dep_set = set(lib_dict[lib].get(deps_key_name, [])) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                dep_set = dep_set.intersection(lib_names) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                # if lib only depends on what's already built, add it to the results 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if not dep_set.difference(set(result)): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    more_results.append(lib) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if not more_results: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            raise Exception( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                'Cannot sort topologically, there seems to be a cyclic dependency' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if verbose: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            print('    adding ' + str(more_results)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        result = result + list( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            sorted(more_results 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                  ))  # when build order doesn't matter, sort lexicographically 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return result 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+# TODO(jtattermusch): deduplicate with transitive_dependencies.py (which has a slightly different logic) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def _populate_transitive_deps(bazel_rules): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    """Add 'transitive_deps' field for each of the rules""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    transitive_deps = {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for rule_name in bazel_rules.iterkeys(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        transitive_deps[rule_name] = set(bazel_rules[rule_name]['deps']) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    while True: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        deps_added = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for rule_name in bazel_rules.iterkeys(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            old_deps = transitive_deps[rule_name] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            new_deps = set(old_deps) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            for dep_name in old_deps: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                new_deps.update(transitive_deps.get(dep_name, set())) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            deps_added += len(new_deps) - len(old_deps) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            transitive_deps[rule_name] = new_deps 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # if none of the transitive dep sets has changed, we're done 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if deps_added == 0: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            break 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for rule_name, bazel_rule in bazel_rules.iteritems(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        bazel_rule['transitive_deps'] = list(sorted(transitive_deps[rule_name])) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def _external_dep_name_from_bazel_dependency(bazel_dep): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    """Returns name of dependency if external bazel dependency is provided or None""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if bazel_dep.startswith('@com_google_absl//'): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # special case for add dependency on one of the absl libraries (there is not just one absl library) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        prefixlen = len('@com_google_absl//') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return bazel_dep[prefixlen:] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    elif bazel_dep == '//external:upb_lib': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return 'upb' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    elif bazel_dep == '//external:benchmark': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return 'benchmark' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # all the other external deps such as gflags, protobuf, cares, zlib 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # don't need to be listed explicitly, they are handled automatically 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # by the build system (make, cmake) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return None 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def _expand_intermediate_deps(target_dict, public_dep_names, bazel_rules): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # Some of the libraries defined by bazel won't be exposed in build.yaml 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # We call these "intermediate" dependencies. This method expands 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # the intermediate deps for given target (populates library's 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # headers, sources and dicts as if the intermediate dependency never existed) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # use this dictionary to translate from bazel labels to dep names 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bazel_label_to_dep_name = {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for dep_name in public_dep_names: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        bazel_label_to_dep_name[_get_bazel_label(dep_name)] = dep_name 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    target_name = target_dict['name'] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bazel_deps = target_dict['_DEPS_BAZEL'] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # initial values 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public_headers = set(target_dict['_PUBLIC_HEADERS_BAZEL']) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    headers = set(target_dict['_HEADERS_BAZEL']) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    src = set(target_dict['_SRC_BAZEL']) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    deps = set() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    expansion_blacklist = set() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    to_expand = set(bazel_deps) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    while to_expand: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # start with the last dependency to be built 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        build_order = _sort_by_build_order(list(to_expand), bazel_rules, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                           'transitive_deps') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        bazel_dep = build_order[-1] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        to_expand.remove(bazel_dep) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        is_public = bazel_dep in bazel_label_to_dep_name 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        external_dep_name_maybe = _external_dep_name_from_bazel_dependency( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            bazel_dep) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if is_public: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            # this is not an intermediate dependency we so we add it 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            # to the list of public dependencies to the list, in the right format 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            deps.add(bazel_label_to_dep_name[bazel_dep]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            # we do not want to expand any intermediate libraries that are already included 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            # by the dependency we just added 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            expansion_blacklist.update( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                bazel_rules[bazel_dep]['transitive_deps']) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        elif external_dep_name_maybe: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            deps.add(external_dep_name_maybe) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        elif bazel_dep.startswith( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                '//external:') or not bazel_dep.startswith('//'): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            # all the other external deps can be skipped 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            pass 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        elif bazel_dep in expansion_blacklist: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            # do not expand if a public dependency that depends on this has already been expanded 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            pass 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if bazel_dep in bazel_rules: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                # this is an intermediate library, expand it 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                public_headers.update( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    _extract_public_headers(bazel_rules[bazel_dep])) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                headers.update( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    _extract_nonpublic_headers(bazel_rules[bazel_dep])) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                src.update(_extract_sources(bazel_rules[bazel_dep])) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                new_deps = _extract_deps(bazel_rules[bazel_dep]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                to_expand.update(new_deps) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                raise Exception(bazel_dep + ' not in bazel_rules') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # make the 'deps' field transitive, but only list non-intermediate deps and selected external deps 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bazel_transitive_deps = bazel_rules[_get_bazel_label( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        target_name)]['transitive_deps'] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for transitive_bazel_dep in bazel_transitive_deps: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        public_name = bazel_label_to_dep_name.get(transitive_bazel_dep, None) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if public_name: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            deps.add(public_name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        external_dep_name_maybe = _external_dep_name_from_bazel_dependency( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            transitive_bazel_dep) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if external_dep_name_maybe: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            # expanding all absl libraries is technically correct but creates too much noise 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if not external_dep_name_maybe.startswith('absl'): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                deps.add(external_dep_name_maybe) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    target_dict['public_headers'] = list(sorted(public_headers)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    target_dict['headers'] = list(sorted(headers)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    target_dict['src'] = list(sorted(src)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    target_dict['deps'] = list(sorted(deps)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def _generate_build_metadata(build_extra_metadata, bazel_rules): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lib_names = build_extra_metadata.keys() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    result = {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for lib_name in lib_names: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        lib_dict = _create_target_from_bazel_rule(lib_name, bazel_rules) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        _expand_intermediate_deps(lib_dict, lib_names, bazel_rules) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # populate extra properties from build metadata 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        lib_dict.update(build_extra_metadata.get(lib_name, {})) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # store to results 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        result[lib_name] = lib_dict 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # rename some targets to something else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # this needs to be made after we're done with most of processing logic 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # otherwise the already-renamed libraries will have different names than expected 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for lib_name in lib_names: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        to_name = build_extra_metadata.get(lib_name, {}).get('_RENAME', None) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if to_name: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            # store lib under the new name and also change its 'name' property 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if to_name in result: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                raise Exception('Cannot rename target ' + lib_name + ', ' + 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                to_name + ' already exists.') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            lib_dict = result.pop(lib_name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            lib_dict['name'] = to_name 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            result[to_name] = lib_dict 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            # dep names need to be updated as well 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            for lib_dict_to_update in result.values(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                lib_dict_to_update['deps'] = list( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    map(lambda dep: to_name if dep == lib_name else dep, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        lib_dict_to_update['deps'])) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # make sure deps are listed in reverse topological order (e.g. "grpc gpr" and not "gpr grpc") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for lib_dict in result.itervalues(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        lib_dict['deps'] = list( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            reversed(_sort_by_build_order(lib_dict['deps'], result, 'deps'))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return result 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def _convert_to_build_yaml_like(lib_dict): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lib_names = list( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        filter( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            lambda lib_name: lib_dict[lib_name].get('_TYPE', 'library') == 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            'library', lib_dict.keys())) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    target_names = list( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        filter( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            lambda lib_name: lib_dict[lib_name].get('_TYPE', 'library') == 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            'target', lib_dict.keys())) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    test_names = list( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        filter( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            lambda lib_name: lib_dict[lib_name].get('_TYPE', 'library') == 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            'test', lib_dict.keys())) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # list libraries and targets in predefined order 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lib_list = list(map(lambda lib_name: lib_dict[lib_name], lib_names)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    target_list = list(map(lambda lib_name: lib_dict[lib_name], target_names)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    test_list = list(map(lambda lib_name: lib_dict[lib_name], test_names)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # get rid of temporary private fields prefixed with "_" and some other useless fields 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for lib in lib_list: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for field_to_remove in filter(lambda k: k.startswith('_'), lib.keys()): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            lib.pop(field_to_remove, None) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for target in target_list: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for field_to_remove in filter(lambda k: k.startswith('_'), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                      target.keys()): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            target.pop(field_to_remove, None) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        target.pop('public_headers', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                   None)  # public headers make no sense for targets 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for test in test_list: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for field_to_remove in filter(lambda k: k.startswith('_'), test.keys()): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            test.pop(field_to_remove, None) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        test.pop('public_headers', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                 None)  # public headers make no sense for tests 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    build_yaml_like = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'libs': lib_list, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'filegroups': [], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'targets': target_list, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'tests': test_list, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return build_yaml_like 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def _extract_cc_tests(bazel_rules): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    """Gets list of cc_test tests from bazel rules""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    result = [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for bazel_rule in bazel_rules.itervalues(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if bazel_rule['class'] == 'cc_test': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            test_name = bazel_rule['name'] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if test_name.startswith('//'): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                prefixlen = len('//') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                result.append(test_name[prefixlen:]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return list(sorted(result)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def _filter_cc_tests(tests): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    """Filters out tests that we don't want or we cannot build them reasonably""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # most qps tests are autogenerated, we are fine without them 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    tests = list( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        filter(lambda test: not test.startswith('test/cpp/qps:'), tests)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # we have trouble with census dependency outside of bazel 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    tests = list( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        filter(lambda test: not test.startswith('test/cpp/ext/filters/census:'), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+               tests)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    tests = list( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        filter( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            lambda test: not test.startswith( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                'test/cpp/microbenchmarks:bm_opencensus_plugin'), tests)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # missing opencensus/stats/stats.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    tests = list( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        filter( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            lambda test: not test.startswith( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                'test/cpp/end2end:server_load_reporting_end2end_test'), tests)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    tests = list( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        filter( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            lambda test: not test.startswith( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                'test/cpp/server/load_reporter:lb_load_reporter_test'), tests)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # The test uses --running_under_bazel cmdline argument 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # To avoid the trouble needing to adjust it, we just skip the test 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    tests = list( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        filter( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            lambda test: not test.startswith( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                'test/cpp/naming:resolver_component_tests_runner_invoker'), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            tests)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # the test requires 'client_crash_test_server' to be built 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    tests = list( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        filter( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            lambda test: not test.startswith('test/cpp/end2end:time_change_test' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            ), tests)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # the test requires 'client_crash_test_server' to be built 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    tests = list( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        filter( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            lambda test: not test.startswith( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                'test/cpp/end2end:client_crash_test'), tests)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # the test requires 'server_crash_test_client' to be built 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    tests = list( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        filter( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            lambda test: not test.startswith( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                'test/cpp/end2end:server_crash_test'), tests)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # test never existed under build.yaml and it fails -> skip it 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    tests = list( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        filter( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            lambda test: not test.startswith( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                'test/core/tsi:ssl_session_cache_test'), tests)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return tests 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def _generate_build_extra_metadata_for_tests(tests, bazel_rules): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    test_metadata = {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for test in tests: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        test_dict = {'build': 'test', '_TYPE': 'target'} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        bazel_rule = bazel_rules[_get_bazel_label(test)] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        bazel_tags = bazel_rule['tags'] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if 'manual' in bazel_tags: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            # don't run the tests marked as "manual" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            test_dict['run'] = False 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if 'no_uses_polling' in bazel_tags: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            test_dict['uses_polling'] = False 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if 'grpc_fuzzer' == bazel_rule['generator_function']: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            # currently we hand-list fuzzers instead of generating them automatically 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            # because there's no way to obtain maxlen property from bazel BUILD file. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            print('skipping fuzzer ' + test) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            continue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # if any tags that restrict platform compatibility are present, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # generate the "platforms" field accordingly 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # TODO(jtattermusch): there is also a "no_linux" tag, but we cannot take 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # it into account as it is applied by grpc_cc_test when poller expansion 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # is made (for tests where uses_polling=True). So for now, we just 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # assume all tests are compatible with linux and ignore the "no_linux" tag 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # completely. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        known_platform_tags = set(['no_windows', 'no_mac']) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if set(bazel_tags).intersection(known_platform_tags): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            platforms = [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            # assume all tests are compatible with linux and posix 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            platforms.append('linux') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            platforms.append( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                'posix')  # there is no posix-specific tag in bazel BUILD 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if not 'no_mac' in bazel_tags: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                platforms.append('mac') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if not 'no_windows' in bazel_tags: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                platforms.append('windows') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            test_dict['platforms'] = platforms 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if '//external:benchmark' in bazel_rule['transitive_deps']: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            test_dict['benchmark'] = True 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            test_dict['defaults'] = 'benchmark' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        cmdline_args = bazel_rule['args'] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if cmdline_args: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            test_dict['args'] = list(cmdline_args) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        uses_gtest = '//external:gtest' in bazel_rule['transitive_deps'] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if uses_gtest: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            test_dict['gtest'] = True 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if test.startswith('test/cpp') or uses_gtest: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            test_dict['language'] = 'c++' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        elif test.startswith('test/core'): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            test_dict['language'] = 'c' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            raise Exception('wrong test' + test) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # short test name without the path. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # There can be name collisions, but we will resolve them later 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        simple_test_name = os.path.basename(_extract_source_file_path(test)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        test_dict['_RENAME'] = simple_test_name 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        test_metadata[test] = test_dict 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # detect duplicate test names 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    tests_by_simple_name = {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for test_name, test_dict in test_metadata.iteritems(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        simple_test_name = test_dict['_RENAME'] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if not simple_test_name in tests_by_simple_name: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            tests_by_simple_name[simple_test_name] = [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        tests_by_simple_name[simple_test_name].append(test_name) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # choose alternative names for tests with a name collision 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for collision_list in tests_by_simple_name.itervalues(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if len(collision_list) > 1: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            for test_name in collision_list: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                long_name = test_name.replace('/', '_').replace(':', '_') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                print( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    'short name of "%s" collides with another test, renaming to %s' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    % (test_name, long_name)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                test_metadata[test_name]['_RENAME'] = long_name 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # TODO(jtattermusch): in bazel, add "_test" suffix to the test names 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # test does not have "_test" suffix: fling 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # test does not have "_test" suffix: fling_stream 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # test does not have "_test" suffix: client_ssl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # test does not have "_test" suffix: handshake_server_with_readahead_handshaker 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # test does not have "_test" suffix: handshake_verify_peer_options 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # test does not have "_test" suffix: server_ssl 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return test_metadata 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+# extra metadata that will be used to construct build.yaml 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+# there are mostly extra properties that we weren't able to obtain from the bazel build 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+# _TYPE: whether this is library, target or test 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+# _RENAME: whether this target should be renamed to a different name (to match expectations of make and cmake builds) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+# NOTE: secure is 'check' by default, so setting secure = False below does matter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+_BUILD_EXTRA_METADATA = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'third_party/address_sorting:address_sorting': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'all', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'secure': False, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'address_sorting' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'gpr': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'all', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'secure': False 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'grpc': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'all', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'baselib': True, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'secure': True, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'dll': True, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'generate_plugin_registry': True 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'grpc++': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'all', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'baselib': True, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'dll': True 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'grpc++_alts': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'all', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'baselib': True 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'grpc++_error_details': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'all' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'grpc++_reflection': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'all' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'grpc++_unsecure': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'all', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'baselib': True, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'secure': False, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'dll': True 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # TODO(jtattermusch): do we need to set grpc_csharp_ext's LDFLAGS for wrapping memcpy in the same way as in build.yaml? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'grpc_csharp_ext': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'all', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'dll': 'only' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'grpc_unsecure': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'all', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'baselib': True, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'secure': False, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'dll': True, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'generate_plugin_registry': True 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'grpcpp_channelz': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'all' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'src/compiler:grpc_plugin_support': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'protoc', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'secure': False, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'grpc_plugin_support' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'src/compiler:grpc_cpp_plugin': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'protoc', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'secure': False, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'grpc_cpp_plugin' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'src/compiler:grpc_csharp_plugin': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'protoc', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'secure': False, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'grpc_csharp_plugin' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'src/compiler:grpc_node_plugin': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'protoc', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'secure': False, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'grpc_node_plugin' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'src/compiler:grpc_objective_c_plugin': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'protoc', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'secure': False, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'grpc_objective_c_plugin' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'src/compiler:grpc_php_plugin': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'protoc', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'secure': False, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'grpc_php_plugin' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'src/compiler:grpc_python_plugin': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'protoc', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'secure': False, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'grpc_python_plugin' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'src/compiler:grpc_ruby_plugin': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'protoc', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'secure': False, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'grpc_ruby_plugin' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # TODO(jtattermusch): consider adding grpc++_core_stats 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # test support libraries 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/core/util:grpc_test_util': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'private', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'grpc_test_util' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/core/util:grpc_test_util_unsecure': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'private', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'secure': False, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'grpc_test_util_unsecure' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # TODO(jtattermusch): consider adding grpc++_test_util_unsecure - it doesn't seem to be used by bazel build (don't forget to set secure: False) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/cpp/util:test_config': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'private', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'grpc++_test_config' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/cpp/util:test_util': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'private', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'grpc++_test_util' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # end2end test support libraries 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/core/end2end:end2end_tests': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'private', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'secure': True, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'end2end_tests' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/core/end2end:end2end_nosec_tests': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'private', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'secure': False, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'end2end_nosec_tests' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # benchmark support libraries 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/cpp/microbenchmarks:helpers': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'test', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'defaults': 'benchmark', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'benchmark_helpers' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/cpp/interop:interop_client': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'test', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'run': False, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'interop_client' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/cpp/interop:interop_server': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'test', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'run': False, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'interop_server' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/cpp/interop:http2_client': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'test', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'run': False, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'http2_client' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/cpp/qps:qps_json_driver': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'test', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'run': False, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'qps_json_driver' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/cpp/qps:qps_worker': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'test', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'run': False, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'qps_worker' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/cpp/util:grpc_cli': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'test', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'run': False, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'grpc_cli' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # TODO(jtattermusch): create_jwt and verify_jwt breaks distribtests because it depends on grpc_test_utils and thus requires tests to be built 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # For now it's ok to disable them as these binaries aren't very useful anyway. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    #'test/core/security:create_jwt': { 'language': 'c', 'build': 'tool', '_TYPE': 'target', '_RENAME': 'grpc_create_jwt' }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    #'test/core/security:verify_jwt': { 'language': 'c', 'build': 'tool', '_TYPE': 'target', '_RENAME': 'grpc_verify_jwt' }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # TODO(jtattermusch): add remaining tools such as grpc_print_google_default_creds_token (they are not used by bazel build) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # Fuzzers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/core/security:alts_credentials_fuzzer': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'fuzzer', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'corpus_dirs': ['test/core/security/corpus/alts_credentials_corpus'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'maxlen': 2048, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'alts_credentials_fuzzer' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/core/end2end/fuzzers:client_fuzzer': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'fuzzer', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'corpus_dirs': ['test/core/end2end/fuzzers/client_fuzzer_corpus'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'maxlen': 2048, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'dict': 'test/core/end2end/fuzzers/hpack.dictionary', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'client_fuzzer' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/core/transport/chttp2:hpack_parser_fuzzer': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'fuzzer', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'corpus_dirs': ['test/core/transport/chttp2/hpack_parser_corpus'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'maxlen': 512, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'dict': 'test/core/end2end/fuzzers/hpack.dictionary', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'hpack_parser_fuzzer_test' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/core/http:request_fuzzer': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'fuzzer', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'corpus_dirs': ['test/core/http/request_corpus'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'maxlen': 2048, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'http_request_fuzzer_test' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/core/http:response_fuzzer': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'fuzzer', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'corpus_dirs': ['test/core/http/response_corpus'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'maxlen': 2048, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'http_response_fuzzer_test' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/core/json:json_fuzzer': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'fuzzer', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'corpus_dirs': ['test/core/json/corpus'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'maxlen': 512, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'json_fuzzer_test' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/core/nanopb:fuzzer_response': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'fuzzer', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'corpus_dirs': ['test/core/nanopb/corpus_response'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'maxlen': 128, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'nanopb_fuzzer_response_test' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/core/nanopb:fuzzer_serverlist': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'fuzzer', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'corpus_dirs': ['test/core/nanopb/corpus_serverlist'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'maxlen': 128, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'nanopb_fuzzer_serverlist_test' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/core/slice:percent_decode_fuzzer': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'fuzzer', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'corpus_dirs': ['test/core/slice/percent_decode_corpus'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'maxlen': 32, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'percent_decode_fuzzer' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/core/slice:percent_encode_fuzzer': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'fuzzer', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'corpus_dirs': ['test/core/slice/percent_encode_corpus'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'maxlen': 32, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'percent_encode_fuzzer' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/core/end2end/fuzzers:server_fuzzer': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'fuzzer', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'corpus_dirs': ['test/core/end2end/fuzzers/server_fuzzer_corpus'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'maxlen': 2048, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'dict': 'test/core/end2end/fuzzers/hpack.dictionary', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'server_fuzzer' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/core/security:ssl_server_fuzzer': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'fuzzer', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'corpus_dirs': ['test/core/security/corpus/ssl_server_corpus'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'maxlen': 2048, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'ssl_server_fuzzer' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'test/core/client_channel:uri_fuzzer_test': { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'language': 'c++', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'build': 'fuzzer', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'corpus_dirs': ['test/core/client_channel/uri_corpus'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'maxlen': 128, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_TYPE': 'target', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        '_RENAME': 'uri_fuzzer_test' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # TODO(jtattermusch): these fuzzers had no build.yaml equivalent 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # test/core/compression:message_compress_fuzzer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # test/core/compression:message_decompress_fuzzer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # test/core/compression:stream_compression_fuzzer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # test/core/compression:stream_decompression_fuzzer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # test/core/slice:b64_decode_fuzzer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    # test/core/slice:b64_encode_fuzzer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+# We need a complete picture of all the targets and dependencies we're interested in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+# so we run multiple bazel queries and merge the results. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+_BAZEL_DEPS_QUERIES = [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'deps("//test/...")', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'deps("//:all")', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'deps("//src/compiler/...")', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    'deps("//src/proto/...")', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+bazel_rules = {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+for query in _BAZEL_DEPS_QUERIES: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bazel_rules.update( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        _extract_rules_from_bazel_xml(_bazel_query_xml_tree(query))) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+_populate_transitive_deps(bazel_rules) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+tests = _filter_cc_tests(_extract_cc_tests(bazel_rules)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+test_metadata = _generate_build_extra_metadata_for_tests(tests, bazel_rules) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+all_metadata = {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+all_metadata.update(_BUILD_EXTRA_METADATA) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+all_metadata.update(test_metadata) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+all_targets_dict = _generate_build_metadata(all_metadata, bazel_rules) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+build_yaml_like = _convert_to_build_yaml_like(all_targets_dict) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+# if a test uses source files from src/ directly, it's a little bit suspicious 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+for tgt in build_yaml_like['targets']: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if tgt['build'] == 'test': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for src in tgt['src']: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if src.startswith('src/') and not src.endswith('.proto'): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                print('source file from under "src/" tree used in test ' + 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                      tgt['name'] + ': ' + src) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+build_yaml_string = build_cleaner.cleaned_build_yaml_dict_as_string( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    build_yaml_like) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+with open('build_autogenerated.yaml', 'w') as file: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    file.write(build_yaml_string) 
			 |