X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=generator%2Fnanopb_generator.py;h=0926db29f6b8ddac8b5692022623709380e4c582;hb=842c960d5df4b7715b0c7d2c00adeddf84389421;hp=86c554a283062db2b62175f7a813088ccdc611a9;hpb=ec517e2108f4e7cc31cffc4fdc2a11cebfabfc66;p=apps%2Fagl-service-can-low-level.git diff --git a/generator/nanopb_generator.py b/generator/nanopb_generator.py index 86c554a2..0926db29 100755 --- a/generator/nanopb_generator.py +++ b/generator/nanopb_generator.py @@ -1,25 +1,41 @@ #!/usr/bin/python '''Generate header file for nanopb from a ProtoBuf FileDescriptorSet.''' -nanopb_version = "nanopb-0.2.5-dev" +nanopb_version = "nanopb-0.2.7-dev" + +import sys try: + # Add some dummy imports to keep packaging tools happy. import google, distutils.util # bbfreeze seems to need these + import pkg_resources # pyinstaller / protobuf 2.5 seem to need these +except: + # Don't care, we will error out later if it is actually important. + pass + +try: import google.protobuf.text_format as text_format + 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 + sys.stderr.write(''' + ************************************************************* + *** Could not import the Google protobuf Python libraries *** + *** Try installing package 'python-protobuf' or similar. *** + ************************************************************* + ''' + '\n') raise -import proto.nanopb_pb2 as nanopb_pb2 -import proto.descriptor_pb2 as descriptor - - - +try: + import proto.nanopb_pb2 as nanopb_pb2 + import proto.plugin_pb2 as plugin_pb2 +except: + sys.stderr.write(''' + ******************************************************************** + *** Failed to import the protocol definitions for generator. *** + *** You have to run 'make' in the nanopb/generator/proto folder. *** + ******************************************************************** + ''' + '\n') + raise # --------------------------------------------------------------------------- # Generation of single fields @@ -153,6 +169,7 @@ class Field: self.max_count = None self.array_decl = "" self.enc_size = None + self.ctype = None # Parse field options if field_options.HasField("max_size"): @@ -298,6 +315,12 @@ class Field: data = self.default.decode('string_escape') data = ['0x%02x' % ord(c) for c in data] default = '{%d, {%s}}' % (len(data), ','.join(data)) + elif self.pbtype in ['FIXED32', 'UINT32']: + default += 'u' + elif self.pbtype in ['FIXED64', 'UINT64']: + default += 'ull' + elif self.pbtype in ['SFIXED64', 'INT64']: + default += 'll' if declaration_only: return 'extern const %s %s_default%s;' % (ctype, self.struct_name + self.name, array_decl) @@ -799,6 +822,23 @@ def generate_source(headername, enums, messages, extensions, options): if worst > 255 or checks: yield '\n/* Check that field information fits in pb_field_t */\n' + if worst > 65535 or checks: + yield '#if !defined(PB_FIELD_32BIT)\n' + if worst > 65535: + yield '#error Field descriptor for %s is too large. Define PB_FIELD_32BIT to fix this.\n' % worst_field + else: + assertion = ' && '.join(str(c) + ' < 65536' for c in checks) + msgs = '_'.join(str(n) for n in checks_msgnames) + yield '/* If you get an error here, it means that you need to define PB_FIELD_32BIT\n' + yield ' * compile-time option. You can do that in pb.h or on compiler command line.\n' + yield ' * \n' + yield ' * The reason you need to do this is that some of your messages contain tag\n' + yield ' * numbers or field sizes that are larger than what can fit in 8 or 16 bit\n' + yield ' * field descriptors.\n' + yield ' */\n' + yield 'STATIC_ASSERT((%s), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_%s)\n'%(assertion,msgs) + yield '#endif\n\n' + if worst < 65536: yield '#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)\n' if worst > 255: @@ -806,18 +846,15 @@ def generate_source(headername, enums, messages, extensions, options): else: assertion = ' && '.join(str(c) + ' < 256' for c in checks) msgs = '_'.join(str(n) for n in checks_msgnames) + yield '/* If you get an error here, it means that you need to define PB_FIELD_16BIT\n' + yield ' * compile-time option. You can do that in pb.h or on compiler command line.\n' + yield ' * \n' + yield ' * The reason you need to do this is that some of your messages contain tag\n' + yield ' * numbers or field sizes that are larger than what can fit in the default\n' + yield ' * 8 bit descriptors.\n' + yield ' */\n' yield 'STATIC_ASSERT((%s), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_%s)\n'%(assertion,msgs) yield '#endif\n\n' - - if worst > 65535 or checks: - yield '#if !defined(PB_FIELD_32BIT)\n' - if worst > 65535: - yield '#error Field descriptor for %s is too large. Define PB_FIELD_32BIT to fix this.\n' % worst_field - else: - assertion = ' && '.join(str(c) + ' < 65536' for c in checks) - msgs = '_'.join(str(n) for n in checks_msgnames) - yield 'STATIC_ASSERT((%s), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_%s)\n'%(assertion,msgs) - yield '#endif\n' # Add check for sizeof(double) has_double = False @@ -863,6 +900,7 @@ class Globals: '''Ugly global variables, should find a good way to pass these.''' verbose_options = False separate_options = [] + matched_namemasks = set() def get_nanopb_suboptions(subdesc, options, name): '''Get copy of options, and merge information from subdesc.''' @@ -873,6 +911,7 @@ def get_nanopb_suboptions(subdesc, options, name): dotname = '.'.join(name.parts) for namemask, options in Globals.separate_options: if fnmatch(dotname, namemask): + Globals.matched_namemasks.add(namemask) new_options.MergeFrom(options) # Handle options defined in .proto @@ -892,8 +931,8 @@ def get_nanopb_suboptions(subdesc, options, name): new_options.MergeFrom(ext) if Globals.verbose_options: - print "Options for " + dotname + ":" - print text_format.MessageToString(new_options) + sys.stderr.write("Options for " + dotname + ": ") + sys.stderr.write(text_format.MessageToString(new_options) + "\n") return new_options @@ -957,13 +996,14 @@ def process_file(filename, fdesc, options): # No %s specified, use the filename as-is optfilename = options.options_file - if options.verbose: - print 'Reading options from ' + optfilename - if os.path.isfile(optfilename): + if options.verbose: + sys.stderr.write('Reading options from ' + optfilename + '\n') + Globals.separate_options = read_options_file(open(optfilename, "rU")) else: Globals.separate_options = [] + Globals.matched_namemasks = set() # Parse the file file_options = get_nanopb_suboptions(fdesc, toplevel_options, Names([filename])) @@ -986,6 +1026,14 @@ def process_file(filename, fdesc, options): sourcedata = ''.join(generate_source(headerbasename, enums, messages, extensions, options)) + # Check if there were any lines in .options that did not match a member + unmatched = [n for n,o in Globals.separate_options if n not in Globals.matched_namemasks] + if unmatched and not options.quiet: + sys.stderr.write("Following patterns in " + optfilename + " did not match any fields: " + + ', '.join(unmatched) + "\n") + if not Globals.verbose_options: + sys.stderr.write("Use protoc --nanopb-out=-v:. to see a list of the field names.\n") + return {'headername': headername, 'headerdata': headerdata, 'sourcename': sourcename, 'sourcedata': sourcedata} @@ -1007,7 +1055,8 @@ def main_cli(): results = process_file(filename, None, options) if not options.quiet: - print "Writing to " + results['headername'] + " and " + results['sourcename'] + sys.stderr.write("Writing to " + results['headername'] + " and " + + results['sourcename'] + "\n") open(results['headername'], 'w').write(results['headerdata']) open(results['sourcename'], 'w').write(results['sourcedata']) @@ -1022,7 +1071,6 @@ def main_plugin(): msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY) msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) - import proto.plugin_pb2 as plugin_pb2 data = sys.stdin.read() request = plugin_pb2.CodeGeneratorRequest.FromString(data) @@ -1030,10 +1078,7 @@ def main_plugin(): args = shlex.split(request.parameter) options, dummy = optparser.parse_args(args) - # We can't go printing stuff to stdout - Globals.verbose_options = False - options.verbose = False - options.quiet = True + Globals.verbose_options = options.verbose response = plugin_pb2.CodeGeneratorResponse() @@ -1054,7 +1099,7 @@ def main_plugin(): if __name__ == '__main__': # Check if we are running as a plugin under protoc - if 'protoc-gen-' in sys.argv[0]: + if 'protoc-gen-' in sys.argv[0] or '--protoc-plugin' in sys.argv: main_plugin() else: main_cli()