Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Side by Side Diff: base/trace_event/v2/tracing_protoc.py

Issue 1947373002: Tracing V2 prototype [NOT FOR REVIEW] Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: WORKS Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/trace_event/v2/trace_event.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2
3 # Hack required to give precedence to the Chromium's protobuf library instead
4 # of the debian's package.
5 import os
6 _CHROME_SRC = os.path.abspath(os.path.join(os.path.abspath(__file__), os.pardir,
7 os.pardir, os.pardir, os.pardir))
8 _PROTOBUF_DIR = os.path.join(_CHROME_SRC, 'third_party', 'protobuf', 'python')
9 import pkg_resources
10 pkg_resources.declare_namespace('google')
11 pkg_resources.fixup_namespace_packages(_PROTOBUF_DIR)
12 import google
13 assert _PROTOBUF_DIR in google.__path__[0]
14 import google.protobuf
15 assert _PROTOBUF_DIR in google.protobuf.__path__[0]
16 import google.protobuf.descriptor
17 from google.protobuf.descriptor import FieldDescriptor
18
19 import argparse
20 import shutil
21 import subprocess
22 import sys
23
24
25 class CppStubGenerator(object):
26 def __init__(self, proto_file_name):
27 self.proto_file_name = proto_file_name
28 self.processed_classes = set()
29 self.includes = set()
30 self.namespace = None
31 self.cpp_namespace = None
32
33
34 def GetCppClassName(self, full_name):
35 assert(full_name.startswith(self.namespace))
36 return full_name[len(self.namespace) + 1:].replace('.', '_')
37
38
39 def GenerateTranslationUnit(self):
40 db = google.protobuf.symbol_database.Default()
41 descriptors = [x.DESCRIPTOR for x in
42 db.GetMessages([self.proto_file_name]).itervalues()]
43 namespace_parts = descriptors[0].file.package.split('.')
44 self.namespace = '.'.join(namespace_parts)
45 self.cpp_namespace = '::' + '::'.join(namespace_parts)
46 ifdef_guard = '%s_%s_H' % (self.namespace, self.proto_file_name)
47 ifdef_guard = ifdef_guard.upper().replace('.', '_')
48
49 descriptors_code = ''
50 for descriptor in descriptors:
51 descriptors_code += self.GenerateClassRecursive(descriptor)
52
53 code = '// Autogenerated. DO NOT EDIT.\n'
54 code += '#ifndef %s\n' % ifdef_guard
55 code += '#define %s\n\n' % ifdef_guard
56
57 code += '#include "base/trace_event/v2/append_only_proto_message.h"\n'
58
59 for inc in self.includes:
60 code += '#include "%s"\n' % inc
61 code += '\n'
62
63 for ns in namespace_parts:
64 code += 'namespace %s {\n' % ns
65
66 code += '\n'
67
68 for full_name in self.processed_classes:
69 cpp_class_name = self.GetCppClassName(full_name)
70 if not cpp_class_name:
71 continue
72 code += 'class %s;\n' % cpp_class_name
73 code += descriptors_code
74
75 for ns in namespace_parts:
76 code += '} // namespace %s\n' % ns
77 code += '#endif // %s\n' % ifdef_guard
78 code += '\n'
79 return code
80
81
82 def GenerateClassRecursive(self, descriptor):
83 assert(isinstance(descriptor, google.protobuf.descriptor.Descriptor))
84 if descriptor.full_name in self.processed_classes:
85 return ''
86 self.processed_classes.add(descriptor.full_name)
87 code = ''
88 for nested_descriptor in descriptor.nested_types:
89 code += self.GenerateClassRecursive(nested_descriptor)
90 code += self.GenerateClass(descriptor)
91 return code
92
93
94 def GenerateClass(self, descriptor):
95 assert(isinstance(descriptor, google.protobuf.descriptor.Descriptor))
96 assert(descriptor.file.name == self.proto_file_name)
97 assert(descriptor.full_name.startswith(self.namespace))
98 _BASE_CLASS = '::base::trace_event::v2::AppendOnlyProtoMessage'
99 _SIMPLE_TYPES = {
100 FieldDescriptor.TYPE_INT32: ('int32_t', 'AppendVarIntSigned'),
101 FieldDescriptor.TYPE_INT64: ('int64_t', 'AppendVarIntSigned'),
102 FieldDescriptor.TYPE_UINT64: ('uint64_t', 'AppendVarIntUnsigned'),
103 FieldDescriptor.TYPE_UINT32: ('uint32_t', 'AppendVarIntUnsigned'),
104 FieldDescriptor.TYPE_BOOL: ('bool', 'AppendVarIntUnsigned'),
105 FieldDescriptor.TYPE_FLOAT: ('float', 'AppendFloat'),
106 FieldDescriptor.TYPE_DOUBLE: ('double', 'AppendDouble'),
107 FieldDescriptor.TYPE_STRING: ('const char*', 'AppendString'),
108 }
109
110 class_name = self.GetCppClassName(descriptor.full_name)
111 code = '\n'
112
113 for enum_descriptor in descriptor.enum_types:
114 code += self.GenerateEnum(class_name, enum_descriptor)
115
116 # Generate enum types.
117 code += 'class %s : public %s {\n' % (class_name, _BASE_CLASS)
118 code += ' public:\n'
119 for nested_type in descriptor.nested_types:
120 code += ' using %s = %s;\n' % (
121 nested_type.name, self.GetCppClassName(nested_type.full_name))
122 for enum_descriptor in descriptor.enum_types:
123 code += ' using %(enum_name)s = %(class_name)s_%(enum_name)s;\n' % {
124 'enum_name': enum_descriptor.name, 'class_name': class_name}
125
126 # Generate C++ class.
127 code += '\n'
128 code += ' explicit %(class_name)s() : %(base_class)s() {}\n' % {
129 'class_name': class_name,
130 'base_class': _BASE_CLASS }
131 code += ' ~%s() override {}\n' % class_name
132
133 for field in descriptor.fields:
134 assert not field.has_options or not field.GetOptions().packed, 'Packed fie lds are not supported'
135
136 camel_name = field.camelcase_name[:1].upper() + field.camelcase_name[1:]
137 code += ' static const int k%sFieldNumber = %d;\n' % (camel_name, field.n umber)
138
139 if field.type in _SIMPLE_TYPES:
140 cpp_type, marshal_fn = _SIMPLE_TYPES[field.type]
141 code += ' void set_%s(%s value) { %s(%d, value); }\n' % (
142 field.name, cpp_type, marshal_fn, field.number)
143
144 elif field.type == FieldDescriptor.TYPE_BYTES:
145 code += ' void set_%s(const void* value, size_t size) { AppendBytes(%d, value, size); }\n' % (
146 field.name, field.number)
147
148 elif field.type == FieldDescriptor.TYPE_ENUM:
149 cpp_type = '%s::%s' % (self.cpp_namespace, self.GetCppClassName(field.en um_type.full_name))
150 code += ' void set_%s(%s value) { AppendVarIntSigned(%d, static_cast<in t32_t>(value)); }\n' % (
151 field.name, cpp_type, field.number)
152
153 elif field.type == FieldDescriptor.TYPE_MESSAGE:
154 if field.message_type.file.name != descriptor.file.name:
155 self.includes.add(ProtoToHppFileName(field.message_type.file.name))
156
157 props = {
158 'base_class': _BASE_CLASS,
159 'full_class_name': '%s::%s' % (
160 self.cpp_namespace,
161 self.GetCppClassName(field.message_type.full_name)),
162 'field_name': field.name,
163 'field_number': field.number,
164 }
165 code += '''
166 %(full_class_name)s* add_%(field_name)s() {
167 return BeginNestedMessage<%(full_class_name)s>(%(field_number)d);
168 // %(full_class_name)s* inst = new %(full_class_name)s();
169 // inst->set_buffer_writer(buffer_writer());
170 // BeginNestedMessage(%(field_number)d, ::std::unique_ptr<%(base_class)s>(in st));
171 // return inst;
172 }\n''' % props
173 # if field.label != FieldDescriptor.LABEL_REPEATED:
174 # code += '''
175 # void set_allocated_%(field_name)s(%(full_class_name)s* value) {
176 # BeginNestedMessage(%(field_number)d, ::std::unique_ptr<%(base_class)s>(val ue));
177 # }\n''' % props
178 else:
179 assert False, 'Field "%s" not supported' % field.name
180
181 code += '};\n\n'
182 return code
183
184
185 def GenerateEnum(self, class_name, enum_descriptor):
186 assert(isinstance(enum_descriptor, google.protobuf.descriptor.EnumDescriptor ))
187 code = 'enum %s_%s {\n' % (class_name, enum_descriptor.name)
188 for enum_value in enum_descriptor.values:
189 code += ' %s_%s_%s = %d,\n' % (class_name, enum_descriptor.name,
190 enum_value.name, enum_value.number)
191 code += '};\n\n'
192 return code
193
194 def ProtoToHppFileName(proto_file_name):
195 return proto_file_name.replace('.proto', '.tracing-pb.h')
196
197 def main():
198 parser = argparse.ArgumentParser()
199 parser.add_argument('--protoc', help='Path to the standard protoc compiler.')
200 parser.add_argument('--proto-out-dir', help='Path for generated stubs.')
201 parser.add_argument('--proto-in-dir', help='Path for source protos.')
202 parser.add_argument('input_protos', nargs='+')
203
204 args = parser.parse_args()
205 protoc = os.path.abspath(args.protoc)
206 assert(os.path.exists(protoc))
207 out_dir = os.path.abspath(args.proto_out_dir)
208 if not os.path.isdir(out_dir):
209 os.makedirs(out_dir)
210
211 print 'Stage 1/2: .proto -> python (using official protoc)'
212 for input_proto_path in args.input_protos:
213 print ' ' + input_proto_path
214 cmd = [protoc, '--proto_path=' + args.proto_in_dir,
215 input_proto_path,
216 '--python_out=' + out_dir,
217 '--cpp_out=' + out_dir,
218 '--js_out=' + out_dir]
219 subprocess.check_call(cmd)
220
221 print '\nStage 2/2: python -> Fast C++ stubs'
222 sys.path.append(out_dir)
223 for input_proto_path in args.input_protos:
224 fname = os.path.basename(input_proto_path)
225 module_name = fname[0:-6] + '_pb2'
226 assert os.path.exists(os.path.join(out_dir, module_name + '.py'))
227 out_cpp_file_path = os.path.join(out_dir, ProtoToHppFileName(fname))
228 print ' %-32s -> %s' % (fname, out_cpp_file_path)
229 __import__(module_name)
230 with open(out_cpp_file_path, 'w') as fout:
231 gen = CppStubGenerator(fname)
232 fout.write(gen.GenerateTranslationUnit())
233
234 if __name__ == '__main__':
235 main()
OLDNEW
« no previous file with comments | « base/trace_event/v2/trace_event.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698