38 import xml.etree.ElementTree
41 Rule = collections.namedtuple(
'Rule',
'name type srcs deps proto_files')
43 BAZEL_BIN =
'tools/bazel'
47 '''Returns a rule from bazel XML rule.'''
51 if child.tag ==
'list' and child.attrib[
'name'] ==
'srcs':
53 if tag.tag ==
'label':
54 srcs.append(tag.attrib[
'value'])
55 if child.tag ==
'list' and child.attrib[
'name'] ==
'deps':
57 if tag.tag ==
'label':
58 deps.append(tag.attrib[
'value'])
59 return Rule(elem.attrib[
'name'], elem.attrib[
'class'], srcs, deps, [])
70 rule = rules.get(name,
None)
73 if dep
not in visited:
77 if src.endswith(
'.proto'):
83 '''Runs bazel query on given package file and returns all upb rules.'''
86 result = subprocess.check_output(
87 [BAZEL_BIN,
'query',
'--output',
'xml',
'--noimplicit_deps',
'//:all'])
88 root = xml.etree.ElementTree.fromstring(result)
92 if elem.tag ==
'rule' and elem.attrib[
'class']
in [
94 'upb_proto_reflection_library',
98 all_deps = [dep
for rule
in rules
for dep
in rule.deps]
99 result = subprocess.check_output([
100 BAZEL_BIN,
'query',
'--output',
'xml',
'--noimplicit_deps',
101 ' union '.join(
'deps({0})'.
format(d)
for d
in all_deps)
103 root = xml.etree.ElementTree.fromstring(result)
107 dep_rules[dep_rule.name] = dep_rule
110 if not rule.type.startswith(
'upb_proto_'):
112 if len(rule.deps) == 1:
113 rule.proto_files.extend(
119 result = subprocess.check_output([BAZEL_BIN,
'build'] +
120 [rule.name
for rule
in rules])
124 return proto_path.replace(
':',
'/').replace(
'.proto', ext)
128 BAZEL_BIN_ROOT =
'bazel-bin/'
129 if elink[0].startswith(
'@'):
131 return os.path.join(BAZEL_BIN_ROOT,
'external',
132 elink[0].replace(
'@',
'').replace(
'//',
''))
135 return BAZEL_BIN_ROOT
139 EXTERNAL_LINKS = [(
'@com_google_protobuf//',
':src/'),
140 (
'@com_google_googleapis//',
''),
141 (
'@com_github_cncf_udpa//',
''),
142 (
'@com_envoyproxy_protoc_gen_validate//',
''),
143 (
'@envoy_api//',
''), (
'@opencensus_proto//',
'')]
144 for external_link
in EXTERNAL_LINKS:
145 if file.startswith(external_link[0]):
153 if rule.type ==
'upb_proto_library':
155 output_dir = args.upb_out
158 output_dir = args.upbdefs_out
159 for proto_file
in rule.proto_files:
161 proto_file = proto_file[
len(elink[0]) +
len(elink[1]):]
162 for ext
in (
'.h',
'.c'):
165 dst = os.path.join(output_dir, file)
167 for src, dst
in files.items():
171 print(
' -> {0}'.
format(dst))
172 os.makedirs(os.path.split(dst)[0], exist_ok=
True)
173 shutil.copyfile(src, dst)
176 parser = argparse.ArgumentParser(description=
'UPB code-gen from bazel')
177 parser.add_argument(
'--verbose', default=
False, action=
'store_true')
178 parser.add_argument(
'--upb_out',
179 default=
'src/core/ext/upb-generated',
180 help=
'Output directory for upb targets')
181 parser.add_argument(
'--upbdefs_out',
182 default=
'src/core/ext/upbdefs-generated',
183 help=
'Output directory for upbdefs targets')
187 args = parser.parse_args()
192 print(
' name={0} type={1} proto_files={2}'.
format(
193 rule.name, rule.type, rule.proto_files))
199 if __name__ ==
'__main__':