Fix duplicate union definition in generated file (#637)

This is related to the fallback logic that is used for encoded
size calculations when dependent files cannot be found at generation
time.

Cache union and size definitions before writing it to file. Group
entries under same cpp_guard in dictionary. Duplicated entries will be
ignored due to set ignoring new entries. After that convert set to
list and sort it. It prevents mess when regenerating files.

Implementation by Jakub Tymejczyk in pull request #648,
slightly modified for brevity.
diff --git a/generator/nanopb_generator.py b/generator/nanopb_generator.py
index 28a36a1..0ddb41a 100755
--- a/generator/nanopb_generator.py
+++ b/generator/nanopb_generator.py
@@ -1804,15 +1804,25 @@
             # If we require a symbol from another file, put a preprocessor if statement
             # around it to prevent compilation errors if the symbol is not actually available.
             local_defines = [identifier for identifier, msize in messagesizes if msize is not None]
+            guards = {}
             for identifier, msize in messagesizes:
                 if msize is not None:
                     cpp_guard = msize.get_cpp_guard(local_defines)
-                    yield cpp_guard
-                    yield msize.get_declarations()
-                    yield '#define %-40s %s\n' % (identifier, msize)
-                    if cpp_guard: yield "#endif\n"
+                    if cpp_guard not in guards:
+                        guards[cpp_guard] = set()
+                    for decl in msize.get_declarations().splitlines():
+                        guards[cpp_guard].add(decl)
+                    guards[cpp_guard].add('#define %-40s %s' % (identifier, msize))
                 else:
                     yield '/* %s depends on runtime parameters */\n' % identifier
+            for guard, values in guards.items():
+                if guard:
+                    yield guard
+                for v in sorted(values):
+                    yield v
+                    yield '\n'
+                if guard:
+                    yield '#endif\n'
             yield '\n'
 
             if [msg for msg in self.messages if hasattr(msg,'msgid')]: