X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=generator%2Fnanopb_generator.py;h=730c0aabca5e7b943eeee77db12fae92862cd79c;hb=67add3259a6429cb4afc1bdb6345e8c057a55ca8;hp=67c422d924a642d1d91fbb539a70465c65e69409;hpb=9af96cd669f7f9189cdedcef110e7dbc1d526857;p=apps%2Fagl-service-can-low-level.git diff --git a/generator/nanopb_generator.py b/generator/nanopb_generator.py index 67c422d9..730c0aab 100644 --- a/generator/nanopb_generator.py +++ b/generator/nanopb_generator.py @@ -1,21 +1,41 @@ '''Generate header file for nanopb from a ProtoBuf FileDescriptorSet.''' -import google.protobuf.descriptor_pb2 as descriptor -import nanopb_pb2 +try: + import google.protobuf.descriptor_pb2 as descriptor +except: + print + print "*************************************************************" + print "*** Could not import the Google protobuf Python libraries ***" + print "*** Try installing package 'python-protobuf' or similar. ***" + print "*************************************************************" + print + raise + +try: + import nanopb_pb2 +except: + print + print "***************************************************************" + print "*** Could not import the precompiled nanopb_pb2.py. ***" + print "*** Run 'make' in the 'generator' folder to update the file.***" + print "***************************************************************" + print + raise + import os.path # Values are tuple (c type, pb ltype) FieldD = descriptor.FieldDescriptorProto datatypes = { FieldD.TYPE_BOOL: ('bool', 'PB_LTYPE_VARINT'), - FieldD.TYPE_DOUBLE: ('double', 'PB_LTYPE_FIXED'), - FieldD.TYPE_FIXED32: ('uint32_t', 'PB_LTYPE_FIXED'), - FieldD.TYPE_FIXED64: ('uint64_t', 'PB_LTYPE_FIXED'), - FieldD.TYPE_FLOAT: ('float', 'PB_LTYPE_FIXED'), + FieldD.TYPE_DOUBLE: ('double', 'PB_LTYPE_FIXED64'), + FieldD.TYPE_FIXED32: ('uint32_t', 'PB_LTYPE_FIXED32'), + FieldD.TYPE_FIXED64: ('uint64_t', 'PB_LTYPE_FIXED64'), + FieldD.TYPE_FLOAT: ('float', 'PB_LTYPE_FIXED32'), FieldD.TYPE_INT32: ('int32_t', 'PB_LTYPE_VARINT'), FieldD.TYPE_INT64: ('int64_t', 'PB_LTYPE_VARINT'), - FieldD.TYPE_SFIXED32: ('int32_t', 'PB_LTYPE_FIXED'), - FieldD.TYPE_SFIXED64: ('int64_t', 'PB_LTYPE_FIXED'), + FieldD.TYPE_SFIXED32: ('int32_t', 'PB_LTYPE_FIXED32'), + FieldD.TYPE_SFIXED64: ('int64_t', 'PB_LTYPE_FIXED64'), FieldD.TYPE_SINT32: ('int32_t', 'PB_LTYPE_SVARINT'), FieldD.TYPE_SINT64: ('int64_t', 'PB_LTYPE_SVARINT'), FieldD.TYPE_UINT32: ('uint32_t', 'PB_LTYPE_VARINT'), @@ -219,9 +239,6 @@ class Field: result += '\n pb_membersize(%s, %s[0]),' % (self.struct_name, self.name) result += ('\n pb_membersize(%s, %s) / pb_membersize(%s, %s[0]),' % (self.struct_name, self.name, self.struct_name, self.name)) - elif self.htype != 'PB_HTYPE_CALLBACK' and self.ltype == 'PB_LTYPE_BYTES': - result += '\n pb_membersize(%s, bytes),' % self.ctype - result += ' 0,' else: result += '\n pb_membersize(%s, %s),' % (self.struct_name, self.name) result += ' 0,' @@ -326,16 +343,16 @@ def toposort2(data): ''' for k, v in data.items(): v.discard(k) # Ignore self dependencies - extra_items_in_deps = reduce(set.union, data.values()) - set(data.keys()) - data.update({item:set() for item in extra_items_in_deps}) + extra_items_in_deps = reduce(set.union, data.values(), set()) - set(data.keys()) + data.update(dict([(item, set()) for item in extra_items_in_deps])) while True: ordered = set(item for item,dep in data.items() if not dep) if not ordered: break for item in sorted(ordered): yield item - data = {item: (dep - ordered) for item,dep in data.items() - if item not in ordered} + data = dict([(item, (dep - ordered)) for item,dep in data.items() + if item not in ordered]) assert not data, "A cyclic dependency exists amongst %r" % data def sort_dependencies(messages): @@ -350,7 +367,7 @@ def sort_dependencies(messages): if msgname in message_by_name: yield message_by_name[msgname] -def generate_header(headername, enums, messages): +def generate_header(dependencies, headername, enums, messages): '''Generate content for a header file. Generates strings, which should be concatenated and stored to file. ''' @@ -362,6 +379,11 @@ def generate_header(headername, enums, messages): yield '#define _PB_%s_\n' % symbol yield '#include \n\n' + for dependency in dependencies: + noext = os.path.splitext(dependency)[0] + yield '#include "%s.pb.h"\n' % noext + yield '\n' + yield '/* Enum definitions */\n' for enum in enums: yield str(enum) + '\n\n' @@ -380,6 +402,16 @@ def generate_header(headername, enums, messages): for msg in messages: yield msg.fields_declaration() + '\n' + count_required_fields = lambda m: len([f for f in msg.fields if f.htype == 'PB_HTYPE_REQUIRED']) + largest_msg = max(messages, key = count_required_fields) + largest_count = count_required_fields(largest_msg) + if largest_count > 64: + yield '\n/* Check that missing required fields will be properly detected */\n' + yield '#if PB_MAX_REQUIRED_FIELDS < %d\n' % largest_count + yield '#warning Properly detecting missing required fields in %s requires \\\n' % largest_msg.name + yield ' setting PB_MAX_REQUIRED_FIELDS to %d or more.\n' % largest_count + yield '#endif\n' + yield '\n#endif\n' def generate_source(headername, enums, messages): @@ -407,7 +439,7 @@ if __name__ == '__main__': print "Output fill be written to file.pb.h and file.pb.c" sys.exit(1) - data = open(sys.argv[1]).read() + data = open(sys.argv[1], 'rb').read() fdesc = descriptor.FileDescriptorSet.FromString(data) enums, messages = parse_file(fdesc.file[0]) @@ -418,12 +450,17 @@ if __name__ == '__main__': print "Writing to " + headername + " and " + sourcename + # List of .proto files that should not be included in the C header file + # even if they are mentioned in the source .proto. + excludes = ['nanopb.proto', 'google/protobuf/descriptor.proto'] + dependencies = [d for d in fdesc.file[0].dependency if d not in excludes] + header = open(headername, 'w') - for part in generate_header(headerbasename, enums, messages): + for part in generate_header(dependencies, headerbasename, enums, messages): header.write(part) source = open(sourcename, 'w') for part in generate_source(headerbasename, enums, messages): source.write(part) - \ No newline at end of file +