+optparser = OptionParser(
+ usage = "Usage: nanopb_generator.py [options] file.pb ...",
+ epilog = "Compile file.pb from file.proto by: 'protoc -ofile.pb file.proto'. " +
+ "Output will be written to file.pb.h and file.pb.c.")
+optparser.add_option("-x", dest="exclude", metavar="FILE", action="append", default=[],
+ help="Exclude file from generated #include list.")
+optparser.add_option("-e", "--extension", dest="extension", metavar="EXTENSION", default="pb",
+ help="Set extension to use instead of 'pb' for generated files. [default: %default]")
+optparser.add_option("-f", "--options-file", dest="options_file", metavar="FILE", default="%s.options",
+ help="Set name of a separate generator options file.")
+optparser.add_option("-Q", "--generated-include-format", dest="genformat",
+ metavar="FORMAT", default='#include "%s"\n',
+ help="Set format string to use for including other .pb.h files. [default: %default]")
+optparser.add_option("-L", "--library-include-format", dest="libformat",
+ metavar="FORMAT", default='#include <%s>\n',
+ help="Set format string to use for including the nanopb pb.h header. [default: %default]")
+optparser.add_option("-q", "--quiet", dest="quiet", action="store_true", default=False,
+ help="Don't print anything except errors.")
+optparser.add_option("-v", "--verbose", dest="verbose", action="store_true", default=False,
+ help="Print more information.")
+optparser.add_option("-s", dest="settings", metavar="OPTION:VALUE", action="append", default=[],
+ help="Set generator option (max_size, max_count etc.).")
+
+def process(filenames, options):
+ '''Process the files given on the command line.'''
+
+ if not filenames:
+ optparser.print_help()
+ return False
+
+ if options.quiet:
+ options.verbose = False
+
+ Globals.verbose_options = options.verbose
+
+ toplevel_options = nanopb_pb2.NanoPBOptions()
+ for s in options.settings:
+ text_format.Merge(s, toplevel_options)
+
+ for filename in filenames:
+ data = open(filename, 'rb').read()
+ fdesc = descriptor.FileDescriptorSet.FromString(data)
+
+ # Check if any separate options are specified
+ optfilename = options.options_file % os.path.splitext(filename)[0]
+
+ if options.verbose:
+ print 'Reading options from ' + optfilename
+
+ if os.path.isfile(optfilename):
+ Globals.separate_options = read_options_file(open(optfilename, "rU"))
+ else:
+ Globals.separate_options = []
+
+ # Parse the file
+ file_options = get_nanopb_suboptions(fdesc.file[0], toplevel_options, Names([filename]))
+ enums, messages = parse_file(fdesc.file[0], file_options)
+
+ noext = os.path.splitext(filename)[0]
+ headername = noext + '.' + options.extension + '.h'
+ sourcename = noext + '.' + options.extension + '.c'
+ headerbasename = os.path.basename(headername)
+
+ if not options.quiet:
+ 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'] + options.exclude
+ dependencies = [d for d in fdesc.file[0].dependency if d not in excludes]
+
+ header = open(headername, 'w')
+ for part in generate_header(dependencies, headerbasename, enums, messages, options):
+ header.write(part)
+
+ source = open(sourcename, 'w')
+ for part in generate_source(headerbasename, enums, messages):
+ source.write(part)
+
+ return True
+
+if __name__ == '__main__':
+ options, filenames = optparser.parse_args()
+ status = process(filenames, options)
+
+ if not status:
+ sys.exit(1)
+