Pārlūkot izejas kodu

Combine nanopb scripts into a single location (#10439)

Sam Edson 3 gadi atpakaļ
vecāks
revīzija
ba0f4f2693
25 mainītis faili ar 104 papildinājumiem un 2324 dzēšanām
  1. 2 29
      Crashlytics/ProtoSupport/generate_crashlytics_protos.sh
  2. 0 221
      Crashlytics/ProtoSupport/nanopb_objc_generator.py
  3. 0 323
      Crashlytics/ProtoSupport/proto_generator.py
  4. 2 2
      Crashlytics/Protogen/nanopb/crashlytics.nanopb.c
  5. 2 2
      Crashlytics/Protogen/nanopb/crashlytics.nanopb.h
  6. 3 29
      FirebaseInAppMessaging/ProtoSupport/generate_nanopb_protos.sh
  7. 0 323
      FirebaseInAppMessaging/ProtoSupport/nanopb_build_protos.py
  8. 0 221
      FirebaseInAppMessaging/ProtoSupport/nanopb_proto_generator.py
  9. 6 6
      FirebaseInAppMessaging/Sources/Analytics/Protogen/nanopb/fiam.nanopb.c
  10. 2 2
      FirebaseInAppMessaging/Sources/Analytics/Protogen/nanopb/fiam.nanopb.h
  11. 2 28
      FirebaseMessaging/ProtoSupport/generate_protos.sh
  12. 0 221
      FirebaseMessaging/ProtoSupport/nanopb_objc_generator.py
  13. 0 324
      FirebaseMessaging/ProtoSupport/proto_generator.py
  14. 1 1
      FirebaseMessaging/Sources/Protogen/nanopb/me.nanopb.c
  15. 1 1
      FirebaseMessaging/Sources/Protogen/nanopb/me.nanopb.h
  16. 2 28
      FirebasePerformance/ProtoSupport/generate_protos.sh
  17. 0 221
      FirebasePerformance/ProtoSupport/nanopb_objc_generator.py
  18. 0 324
      FirebasePerformance/ProtoSupport/proto_generator.py
  19. 1 1
      FirebasePerformance/Sources/Protogen/nanopb/perf_metric.nanopb.c
  20. 1 1
      FirebasePerformance/Sources/Protogen/nanopb/perf_metric.nanopb.h
  21. 1 1
      FirebaseSessions/Protogen/nanopb/clientanalytics.nanopb.c
  22. 25 0
      FirebaseSessions/generate_protos.sh
  23. 18 11
      scripts/nanopb/generate_protos.sh
  24. 0 0
      scripts/nanopb/nanopb_objc_generator.py
  25. 35 4
      scripts/nanopb/proto_generator.py

+ 2 - 29
Crashlytics/ProtoSupport/generate_crashlytics_protos.sh

@@ -22,35 +22,8 @@
 
 readonly DIR="$( git rev-parse --show-toplevel )"
 
-# Current release of nanopb being used  to build the CCT protos
-readonly NANOPB_VERSION="0.3.9.8"
-readonly NANOPB_TEMPDIR="${DIR}/Crashlytics/nanopb_temp"
-
-readonly LIBRARY_DIR="${DIR}/Crashlytics/Crashlytics/"
 readonly PROTO_DIR="${DIR}/Crashlytics/ProtoSupport/Protos/"
 readonly PROTOGEN_DIR="${DIR}/Crashlytics/Protogen/"
+readonly INCLUDE_PREFIX="Crashlytics/Protogen/nanopb/"
 
-rm -rf "${NANOPB_TEMPDIR}"
-
-echo "Downloading nanopb..."
-git clone --branch "${NANOPB_VERSION}" https://github.com/nanopb/nanopb.git "${NANOPB_TEMPDIR}"
-
-echo "Building nanopb..."
-pushd "${NANOPB_TEMPDIR}"
-./tools/make_mac_package.sh
-GIT_DESCRIPTION=`git describe --always`-macosx-x86
-NANOPB_BIN_DIR="dist/${GIT_DESCRIPTION}"
-popd
-
-echo "Removing existing CCT protos..."
-rm -rf "${PROTOGEN_DIR}/*"
-
-echo "Generating CCT protos..."
-python "${DIR}/Crashlytics/ProtoSupport/proto_generator.py" \
-  --nanopb \
-  --protos_dir="${PROTO_DIR}" \
-  --pythonpath="${NANOPB_TEMPDIR}/${NANOPB_BIN_DIR}/generator" \
-  --output_dir="${PROTOGEN_DIR}" \
-  --include="${PROTO_DIR}"
-
-rm -rf "${NANOPB_TEMPDIR}"
+./scripts/nanopb/generate_protos.sh "$PROTO_DIR" "$PROTOGEN_DIR" "$INCLUDE_PREFIX"

+ 0 - 221
Crashlytics/ProtoSupport/nanopb_objc_generator.py

@@ -1,221 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright 2020 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Generates and massages protocol buffer outputs.
-"""
-
-from __future__ import print_function
-
-import sys
-
-import io
-import nanopb_generator as nanopb
-import os
-import os.path
-import shlex
-
-from google.protobuf.descriptor_pb2 import FieldDescriptorProto
-
-# The plugin_pb2 package loads descriptors on import, but doesn't defend
-# against multiple imports. Reuse the plugin package as loaded by the
-# nanopb_generator.
-plugin_pb2 = nanopb.plugin_pb2
-nanopb_pb2 = nanopb.nanopb_pb2
-
-
-def main():
-  # Parse request
-  data = io.open(sys.stdin.fileno(), 'rb').read()
-  request = plugin_pb2.CodeGeneratorRequest.FromString(data)
-
-  # Preprocess inputs, changing types and nanopb defaults
-  options = nanopb_parse_options(request)
-  use_anonymous_oneof(request)
-  use_bytes_for_strings(request)
-
-  # Generate code
-  parsed_files = nanopb_parse_files(request, options)
-  results = nanopb_generate(request, options, parsed_files)
-  response = nanopb_write(results)
-
-  # Write to stdout
-  io.open(sys.stdout.fileno(), 'wb').write(response.SerializeToString())
-
-
-def use_anonymous_oneof(request):
-  """Use anonymous unions for oneofs if they're the only one in a message.
-
-  Equivalent to setting this option on messages where it applies:
-
-    option (nanopb).anonymous_oneof = true;
-
-  Args:
-    request: A CodeGeneratorRequest from protoc. The descriptors are modified
-      in place.
-  """
-  for _, message_type in iterate_messages(request):
-    if len(message_type.oneof_decl) == 1:
-      ext = message_type.options.Extensions[nanopb_pb2.nanopb_msgopt]
-      ext.anonymous_oneof = True
-
-
-def use_bytes_for_strings(request):
-  """Always use the bytes type instead of string.
-
-  By default, nanopb renders proto strings as having the C type char* and does
-  not include a separate size field, getting the length of the string via
-  strlen(). Unfortunately this prevents using strings with embedded nulls,
-  which is something the wire format supports.
-
-  Fortunately, string and bytes proto fields are identical on the wire and
-  nanopb's bytes representation does have an explicit length, so this function
-  changes the types of all string fields to bytes. The generated code will now
-  contain pb_bytes_array_t.
-
-  There's no nanopb or proto option to control this behavior. The equivalent
-  would be to hand edit all the .proto files :-(.
-
-  Args:
-    request: A CodeGeneratorRequest from protoc. The descriptors are modified
-      in place.
-  """
-  for names, message_type in iterate_messages(request):
-    for field in message_type.field:
-      if field.type == FieldDescriptorProto.TYPE_STRING:
-        field.type = FieldDescriptorProto.TYPE_BYTES
-
-
-def iterate_messages(request):
-  """Iterates over all messages in all files in the request.
-
-  Args:
-    request: A CodeGeneratorRequest passed by protoc.
-
-  Yields:
-    names: a nanopb.Names object giving a qualified name for the message
-    message_type: a DescriptorProto for the message.
-  """
-  for fdesc in request.proto_file:
-    for names, message_type in nanopb.iterate_messages(fdesc):
-      yield names, message_type
-
-
-def nanopb_parse_options(request):
-  """Parses nanopb_generator command-line options from the given request.
-
-  Args:
-    request: A CodeGeneratorRequest passed by protoc.
-
-  Returns:
-    Nanopb's options object, obtained via optparser.
-  """
-  # Parse options the same as nanopb_generator.main_plugin() does.
-  args = shlex.split(request.parameter)
-  options, _ = nanopb.optparser.parse_args(args)
-
-  # Force certain options
-  options.extension = '.nanopb'
-  options.verbose = True
-  
-  # Replicate options setup from nanopb_generator.main_plugin.
-  nanopb.Globals.verbose_options = options.verbose
-
-  # Google's protoc does not currently indicate the full path of proto files.
-  # Instead always add the main file path to the search dirs, that works for
-  # the common case.
-  options.options_path.append(os.path.dirname(request.file_to_generate[0]))
-  return options
-
-
-def nanopb_parse_files(request, options):
-  """Parses the files in the given request into nanopb ProtoFile objects.
-
-  Args:
-    request: A CodeGeneratorRequest, as passed by protoc.
-    options: The command-line options from nanopb_parse_options.
-
-  Returns:
-    A dictionary of filename to nanopb.ProtoFile objects, each one representing
-    the parsed form of a FileDescriptor in the request.
-  """
-  # Process any include files first, in order to have them
-  # available as dependencies
-  parsed_files = {}
-  for fdesc in request.proto_file:
-    parsed_files[fdesc.name] = nanopb.parse_file(fdesc.name, fdesc, options)
-
-  return parsed_files
-
-
-def nanopb_generate(request, options, parsed_files):
-  """Generates C sources from the given parsed files.
-
-  Args:
-    request: A CodeGeneratorRequest, as passed by protoc.
-    options: The command-line options from nanopb_parse_options.
-    parsed_files: A dictionary of filename to nanopb.ProtoFile, as returned by
-      nanopb_parse_files().
-
-  Returns:
-    A list of nanopb output dictionaries, each one representing the code
-    generation result for each file to generate. The output dictionaries have
-    the following form:
-
-        {
-          'headername': Name of header file, ending in .h,
-          'headerdata': Contents of the header file,
-          'sourcename': Name of the source code file, ending in .c,
-          'sourcedata': Contents of the source code file
-        }
-  """
-  output = []
-
-  for filename in request.file_to_generate:
-    for fdesc in request.proto_file:
-      if fdesc.name == filename:
-        results = nanopb.process_file(filename, fdesc, options, parsed_files)
-        output.append(results)
-
-  return output
-
-
-def nanopb_write(results):
-  """Translates nanopb output dictionaries to a CodeGeneratorResponse.
-
-  Args:
-    results: A list of generated source dictionaries, as returned by
-      nanopb_generate().
-
-  Returns:
-    A CodeGeneratorResponse describing the result of the code generation
-    process to protoc.
-  """
-  response = plugin_pb2.CodeGeneratorResponse()
-
-  for result in results:
-    f = response.file.add()
-    f.name = result['headername']
-    f.content = result['headerdata']
-
-    f = response.file.add()
-    f.name = result['sourcename']
-    f.content = result['sourcedata']
-
-  return response
-
-
-if __name__ == '__main__':
-  main()

+ 0 - 323
Crashlytics/ProtoSupport/proto_generator.py

@@ -1,323 +0,0 @@
-#! /usr/bin/env python
-
-# Copyright 2020 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Generates and massages protocol buffer outputs.
-
-Example usage:
-
-python Crashlytics/ProtoSupport/build_protos.py \
-  --nanopb \
-  --protos_dir=Crashlytics/Classes/Protos/ \
-  --pythonpath=~/Downloads/nanopb-0.3.9.2-macosx-x86/generator/ \
-  --output_dir=Crashlytics/Protogen/
-"""
-
-from __future__ import print_function
-
-import sys
-
-import argparse
-import os
-import os.path
-import re
-import subprocess
-
-OBJC_GENERATOR='nanopb_objc_generator.py'
-
-COPYRIGHT_NOTICE = '''
-/*
- * Copyright 2019 Google
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-'''.lstrip()
-
-
-def main():
-  parser = argparse.ArgumentParser(
-      description='Generates proto messages.')
-  parser.add_argument(
-      '--nanopb', action='store_true',
-      help='Generates nanopb messages.')
-  parser.add_argument(
-      '--objc', action='store_true',
-      help='Generates Objective-C messages.')
-  parser.add_argument(
-      '--protos_dir',
-      help='Source directory containing .proto files.')
-  parser.add_argument(
-      '--output_dir', '-d',
-      help='Directory to write files; subdirectories will be created.')
-  parser.add_argument(
-      '--protoc', default='protoc',
-      help='Location of the protoc executable')
-  parser.add_argument(
-      '--pythonpath',
-      help='Location of the protoc python library.')
-  parser.add_argument(
-      '--include', '-I', action='append', default=[],
-      help='Adds INCLUDE to the proto path.')
-
-
-  args = parser.parse_args()
-  if args.nanopb is None and args.objc is None:
-    parser.print_help()
-    sys.exit(1)
-
-  if args.protos_dir is None:
-    root_dir = os.path.abspath(os.path.dirname(__file__))
-    args.protos_dir = os.path.join(root_dir, 'protos')
-
-  if args.output_dir is None:
-    root_dir = os.path.abspath(os.path.dirname(__file__))
-    args.output_dir = os.path.join(root_dir, 'protogen-please-supply-an-outputdir')
-
-  all_proto_files = collect_files(args.protos_dir, '.proto')
-  if args.nanopb:
-    NanopbGenerator(args, all_proto_files).run()
-
-  proto_files = remove_well_known_protos(all_proto_files)
-
-  if args.objc:
-    ObjcProtobufGenerator(args, proto_files).run()
-
-
-class NanopbGenerator(object):
-  """Builds and runs the nanopb plugin to protoc."""
-
-  def __init__(self, args, proto_files):
-    self.args = args
-    self.proto_files = proto_files
-
-  def run(self):
-    """Performs the action of the generator."""
-
-    nanopb_out = os.path.join(self.args.output_dir, 'nanopb')
-    mkdir(nanopb_out)
-
-    self.__run_generator(nanopb_out)
-
-    sources = collect_files(nanopb_out, '.nanopb.h', '.nanopb.c')
-    post_process_files(
-        sources,
-        add_copyright,
-        nanopb_remove_extern_c,
-        nanopb_rename_delete,
-        nanopb_use_module_import
-    )
-
-  def __run_generator(self, out_dir):
-    """Invokes protoc using the nanopb plugin."""
-    cmd = protoc_command(self.args)
-
-    gen = os.path.join(os.path.dirname(__file__), OBJC_GENERATOR)
-    cmd.append('--plugin=protoc-gen-nanopb=%s' % gen)
-
-    nanopb_flags = [
-        '--extension=.nanopb',
-        '--source-extension=.c',
-        '--no-timestamp'
-    ]
-    nanopb_flags.extend(['-I%s' % path for path in self.args.include])
-    cmd.append('--nanopb_out=%s:%s' % (' '.join(nanopb_flags), out_dir))
-
-    cmd.extend(self.proto_files)
-    run_protoc(self.args, cmd)
-
-
-def protoc_command(args):
-  """Composes the initial protoc command-line including its include path."""
-  cmd = [args.protoc]
-  if args.include is not None:
-    cmd.extend(['-I=%s' % path for path in args.include])
-  return cmd
-
-
-def run_protoc(args, cmd):
-  """Actually runs the given protoc command.
-
-  Args:
-    args: The command-line args (including pythonpath)
-    cmd: The command to run expressed as a list of strings
-  """
-
-  kwargs = {}
-  if args.pythonpath:
-    env = os.environ.copy()
-    old_path = env.get('PYTHONPATH')
-    env['PYTHONPATH'] = os.path.expanduser(args.pythonpath)
-    if old_path is not None:
-      env['PYTHONPATH'] += os.pathsep + old_path
-    kwargs['env'] = env
-
-  try:
-    print(subprocess.check_output(cmd, stderr=subprocess.STDOUT, **kwargs))
-  except subprocess.CalledProcessError as error:
-    print('command failed: ', ' '.join(cmd), '\nerror: ', error.output)
-
-
-def remove_well_known_protos(filenames):
-  """Remove "well-known" protos for objc.
-
-  On those platforms we get these for free as a part of the protobuf runtime.
-  We only need them for nanopb.
-
-  Args:
-    filenames: A list of filenames, each naming a .proto file.
-
-  Returns:
-    The filenames with members of google/protobuf removed.
-  """
-
-  return [f for f in filenames if 'protos/google/protobuf/' not in f]
-
-
-def post_process_files(filenames, *processors):
-  for filename in filenames:
-    lines = []
-    with open(filename, 'r') as fd:
-      lines = fd.readlines()
-
-    for processor in processors:
-      lines = processor(lines)
-
-    write_file(filename, lines)
-
-
-def write_file(filename, lines):
-  mkdir(os.path.dirname(filename))
-  with open(filename, 'w') as fd:
-    fd.write(''.join(lines))
-
-
-def add_copyright(lines):
-  """Adds a copyright notice to the lines."""
-  result = [COPYRIGHT_NOTICE, '\n']
-  result.extend(lines)
-  return result
-
-
-def nanopb_remove_extern_c(lines):
-  """Removes extern "C" directives from nanopb code.
-
-  Args:
-    lines: A nanobp-generated source file, split into lines.
-  Returns:
-    A list of strings, similar to the input but modified to remove extern "C".
-  """
-  result = []
-  state = 'initial'
-  for line in lines:
-    if state == 'initial':
-      if '#ifdef __cplusplus' in line:
-        state = 'in-ifdef'
-        continue
-
-      result.append(line)
-
-    elif state == 'in-ifdef':
-      if '#endif' in line:
-        state = 'initial'
-
-  return result
-
-
-def nanopb_rename_delete(lines):
-  """Renames a delete symbol to delete_.
-
-  If a proto uses a field named 'delete', nanopb happily uses that in the
-  message definition. Works fine for C; not so much for C++.
-
-  Args:
-    lines: The lines to fix.
-
-  Returns:
-    The lines, fixed.
-  """
-  delete_keyword = re.compile(r'\bdelete\b')
-  return [delete_keyword.sub('delete_', line) for line in lines]
-
-
-def nanopb_use_module_import(lines):
-  """Changes #include <pb.h> to include <nanopb/pb.h>""" # Don't let Copybara alter these lines.
-  return [line.replace('#include <pb.h>', '{}include <nanopb/pb.h>'.format("#")) for line in lines]
-
-
-def strip_trailing_whitespace(lines):
-  """Removes trailing whitespace from the given lines."""
-  return [line.rstrip() + '\n' for line in lines]
-
-
-def objc_flatten_imports(lines):
-  """Flattens the import statements for compatibility with CocoaPods."""
-
-  long_import = re.compile(r'#import ".*/')
-  return [long_import.sub('#import "', line) for line in lines]
-
-
-def objc_strip_extension_registry(lines):
-  """Removes extensionRegistry methods from the classes."""
-  skip = False
-  result = []
-  for line in lines:
-    if '+ (GPBExtensionRegistry*)extensionRegistry {' in line:
-      skip = True
-    if not skip:
-      result.append(line)
-    elif line == '}\n':
-      skip = False
-
-  return result
-
-
-def collect_files(root_dir, *extensions):
-  """Finds files with the given extensions in the root_dir.
-
-  Args:
-    root_dir: The directory from which to start traversing.
-    *extensions: Filename extensions (including the leading dot) to find.
-
-  Returns:
-    A list of filenames, all starting with root_dir, that have one of the given
-    extensions.
-  """
-  result = []
-  for root, _, files in os.walk(root_dir):
-    for basename in files:
-      for ext in extensions:
-        if basename.endswith(ext):
-          filename = os.path.join(root, basename)
-          result.append(filename)
-  return result
-
-
-def mkdir(dirname):
-  if not os.path.isdir(dirname):
-    os.makedirs(dirname)
-
-
-if __name__ == '__main__':
-  main()

+ 2 - 2
Crashlytics/Protogen/nanopb/crashlytics.nanopb.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2019 Google
+ * Copyright 2022 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
  */
 
 /* Automatically generated nanopb constant definitions */
-/* Generated by nanopb-0.3.9.7 */
+/* Generated by nanopb-0.3.9.8 */
 
 #include "Crashlytics/Protogen/nanopb/crashlytics.nanopb.h"
 

+ 2 - 2
Crashlytics/Protogen/nanopb/crashlytics.nanopb.h

@@ -1,5 +1,5 @@
 /*
- * Copyright 2019 Google
+ * Copyright 2022 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
  */
 
 /* Automatically generated nanopb header */
-/* Generated by nanopb-0.3.9.7 */
+/* Generated by nanopb-0.3.9.8 */
 
 #ifndef PB_GOOGLE_CRASHLYTICS_CRASHLYTICS_NANOPB_H_INCLUDED
 #define PB_GOOGLE_CRASHLYTICS_CRASHLYTICS_NANOPB_H_INCLUDED

+ 3 - 29
FirebaseInAppMessaging/ProtoSupport/generate_nanopb_protos.sh

@@ -22,34 +22,8 @@
 
 readonly REPO_DIR="$( git rev-parse --show-toplevel )"
 
-# Current release of nanopb being used  to build the CCT protos
-readonly NANOPB_VERSION="0.3.9.8"
-readonly NANOPB_TEMPDIR="$(mktemp -d)"
-
 readonly PROTO_DIR="${REPO_DIR}/FirebaseInAppMessaging/ProtoSupport/Protos"
-readonly PROTOGEN_DIR="${REPO_DIR}/FirebaseInAppMessaging/Analytics/Protogen"
-
-rm -rf "${NANOPB_TEMPDIR}"
-
-echo "Downloading nanopb..."
-git clone --branch "${NANOPB_VERSION}" https://github.com/nanopb/nanopb.git "${NANOPB_TEMPDIR}"
-
-echo "Building nanopb..."
-pushd "${NANOPB_TEMPDIR}"
-./tools/make_mac_package.sh
-GIT_DESCRIPTION=`git describe --always`-macosx-x86
-NANOPB_BIN_DIR="dist/${GIT_DESCRIPTION}"
-popd
-
-echo "Removing existing generated protos..."
-rm -rf "${PROTOGEN_DIR}/*"
-
-echo "Generating nanopb protos..."
-python "${REPO_DIR}/FirebaseInAppMessaging/ProtoSupport/nanopb_build_protos.py" \
-  --nanopb \
-  --protos_dir="${PROTO_DIR}" \
-  --pythonpath="${NANOPB_TEMPDIR}/${NANOPB_BIN_DIR}/generator" \
-  --output_dir="${PROTOGEN_DIR}" \
-  --include="${PROTO_DIR}"
+readonly PROTOGEN_DIR="${REPO_DIR}/FirebaseInAppMessaging/Sources/Analytics/Protogen"
+readonly INCLUDE_PREFIX="FirebaseInAppMessaging/Sources/Analytics/Protogen/nanopb/"
 
-rm -rf "${NANOPB_TEMPDIR}"
+./scripts/nanopb/generate_protos.sh "$PROTO_DIR" "$PROTOGEN_DIR" "$INCLUDE_PREFIX"

+ 0 - 323
FirebaseInAppMessaging/ProtoSupport/nanopb_build_protos.py

@@ -1,323 +0,0 @@
-#! /usr/bin/env python
-
-# Copyright 2019 Google
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Builds nanopb protos by calling a proto generator wrapper.
-
-Example usage:
-
-python Firebase/Core/nanopb_build_protos.py \
-  --nanopb \
-  --protos_dir=Firebase/Core/Protos/ \
-  --pythonpath=Firebase/Core/nanopb_temp/generator/ \
-  --output_dir=Firebase/Core/Protos/
-"""
-
-from __future__ import print_function
-
-import sys
-
-import argparse
-import os
-import os.path
-import re
-import subprocess
-
-OBJC_GENERATOR='nanopb_proto_generator.py'
-
-COPYRIGHT_NOTICE = '''
-/*
- * Copyright 2019 Google
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-'''.lstrip()
-
-
-def main():
-  parser = argparse.ArgumentParser(
-      description='Generates proto messages.')
-  parser.add_argument(
-      '--nanopb', action='store_true',
-      help='Generates nanopb messages.')
-  parser.add_argument(
-      '--objc', action='store_true',
-      help='Generates Objective-C messages.')
-  parser.add_argument(
-      '--protos_dir',
-      help='Source directory containing .proto files.')
-  parser.add_argument(
-      '--output_dir', '-d',
-      help='Directory to write files; subdirectories will be created.')
-  parser.add_argument(
-      '--protoc', default='protoc',
-      help='Location of the protoc executable')
-  parser.add_argument(
-      '--pythonpath',
-      help='Location of the protoc python library.')
-  parser.add_argument(
-      '--include', '-I', action='append', default=[],
-      help='Adds INCLUDE to the proto path.')
-
-
-  args = parser.parse_args()
-  if args.nanopb is None and args.objc is None:
-    parser.print_help()
-    sys.exit(1)
-
-  if args.protos_dir is None:
-    root_dir = os.path.abspath(os.path.dirname(__file__))
-    args.protos_dir = os.path.join(root_dir, 'protos')
-
-  if args.output_dir is None:
-    root_dir = os.path.abspath(os.path.dirname(__file__))
-    args.output_dir = os.path.join(root_dir, 'protogen-please-supply-an-outputdir')
-
-  all_proto_files = collect_files(args.protos_dir, '.proto')
-  if args.nanopb:
-    NanopbGenerator(args, all_proto_files).run()
-
-  proto_files = remove_well_known_protos(all_proto_files)
-
-  if args.objc:
-    ObjcProtobufGenerator(args, proto_files).run()
-
-
-class NanopbGenerator(object):
-  """Builds and runs the nanopb plugin to protoc."""
-
-  def __init__(self, args, proto_files):
-    self.args = args
-    self.proto_files = proto_files
-
-  def run(self):
-    """Performs the action of the generator."""
-
-    nanopb_out = os.path.join(self.args.output_dir, 'nanopb')
-    mkdir(nanopb_out)
-
-    self.__run_generator(nanopb_out)
-
-    sources = collect_files(nanopb_out, '.nanopb.h', '.nanopb.c')
-    post_process_files(
-        sources,
-        add_copyright,
-        nanopb_remove_extern_c,
-        nanopb_rename_delete,
-        nanopb_use_module_import
-    )
-
-  def __run_generator(self, out_dir):
-    """Invokes protoc using the nanopb plugin."""
-    cmd = protoc_command(self.args)
-
-    gen = os.path.join(os.path.dirname(__file__), OBJC_GENERATOR)
-    cmd.append('--plugin=protoc-gen-nanopb=%s' % gen)
-
-    nanopb_flags = [
-        '--extension=.nanopb',
-        '--source-extension=.c',
-        '--no-timestamp'
-    ]
-    nanopb_flags.extend(['-I%s' % path for path in self.args.include])
-    cmd.append('--nanopb_out=%s:%s' % (' '.join(nanopb_flags), out_dir))
-
-    cmd.extend(self.proto_files)
-    run_protoc(self.args, cmd)
-
-
-def protoc_command(args):
-  """Composes the initial protoc command-line including its include path."""
-  cmd = [args.protoc]
-  if args.include is not None:
-    cmd.extend(['-I=%s' % path for path in args.include])
-  return cmd
-
-
-def run_protoc(args, cmd):
-  """Actually runs the given protoc command.
-
-  Args:
-    args: The command-line args (including pythonpath)
-    cmd: The command to run expressed as a list of strings
-  """
-
-  kwargs = {}
-  if args.pythonpath:
-    env = os.environ.copy()
-    old_path = env.get('PYTHONPATH')
-    env['PYTHONPATH'] = os.path.expanduser(args.pythonpath)
-    if old_path is not None:
-      env['PYTHONPATH'] += os.pathsep + old_path
-    kwargs['env'] = env
-
-  try:
-    print(subprocess.check_output(cmd, stderr=subprocess.STDOUT, **kwargs))
-  except subprocess.CalledProcessError as error:
-    print('command failed: ', ' '.join(cmd), '\nerror: ', error.output)
-
-
-def remove_well_known_protos(filenames):
-  """Remove "well-known" protos for objc.
-
-  On those platforms we get these for free as a part of the protobuf runtime.
-  We only need them for nanopb.
-
-  Args:
-    filenames: A list of filenames, each naming a .proto file.
-
-  Returns:
-    The filenames with members of google/protobuf removed.
-  """
-
-  return [f for f in filenames if 'protos/google/protobuf/' not in f]
-
-
-def post_process_files(filenames, *processors):
-  for filename in filenames:
-    lines = []
-    with open(filename, 'r') as fd:
-      lines = fd.readlines()
-
-    for processor in processors:
-      lines = processor(lines)
-
-    write_file(filename, lines)
-
-
-def write_file(filename, lines):
-  mkdir(os.path.dirname(filename))
-  with open(filename, 'w') as fd:
-    fd.write(''.join(lines))
-
-
-def add_copyright(lines):
-  """Adds a copyright notice to the lines."""
-  result = [COPYRIGHT_NOTICE, '\n']
-  result.extend(lines)
-  return result
-
-
-def nanopb_remove_extern_c(lines):
-  """Removes extern "C" directives from nanopb code.
-
-  Args:
-    lines: A nanobp-generated source file, split into lines.
-  Returns:
-    A list of strings, similar to the input but modified to remove extern "C".
-  """
-  result = []
-  state = 'initial'
-  for line in lines:
-    if state == 'initial':
-      if '#ifdef __cplusplus' in line:
-        state = 'in-ifdef'
-        continue
-
-      result.append(line)
-
-    elif state == 'in-ifdef':
-      if '#endif' in line:
-        state = 'initial'
-
-  return result
-
-
-def nanopb_rename_delete(lines):
-  """Renames a delete symbol to delete_.
-
-  If a proto uses a field named 'delete', nanopb happily uses that in the
-  message definition. Works fine for C; not so much for C++.
-
-  Args:
-    lines: The lines to fix.
-
-  Returns:
-    The lines, fixed.
-  """
-  delete_keyword = re.compile(r'\bdelete\b')
-  return [delete_keyword.sub('delete_', line) for line in lines]
-
-
-def nanopb_use_module_import(lines):
-  """Changes #include <pb.h> to include <nanopb/pb.h>""" # Don't let Copybara alter these lines.
-  return [line.replace('#include <pb.h>', '{}include <nanopb/pb.h>'.format("#")) for line in lines]
-
-
-def strip_trailing_whitespace(lines):
-  """Removes trailing whitespace from the given lines."""
-  return [line.rstrip() + '\n' for line in lines]
-
-
-def objc_flatten_imports(lines):
-  """Flattens the import statements for compatibility with CocoaPods."""
-
-  long_import = re.compile(r'#import ".*/')
-  return [long_import.sub('#import "', line) for line in lines]
-
-
-def objc_strip_extension_registry(lines):
-  """Removes extensionRegistry methods from the classes."""
-  skip = False
-  result = []
-  for line in lines:
-    if '+ (GPBExtensionRegistry*)extensionRegistry {' in line:
-      skip = True
-    if not skip:
-      result.append(line)
-    elif line == '}\n':
-      skip = False
-
-  return result
-
-
-def collect_files(root_dir, *extensions):
-  """Finds files with the given extensions in the root_dir.
-
-  Args:
-    root_dir: The directory from which to start traversing.
-    *extensions: Filename extensions (including the leading dot) to find.
-
-  Returns:
-    A list of filenames, all starting with root_dir, that have one of the given
-    extensions.
-  """
-  result = []
-  for root, _, files in os.walk(root_dir):
-    for basename in files:
-      for ext in extensions:
-        if basename.endswith(ext):
-          filename = os.path.join(root, basename)
-          result.append(filename)
-  return result
-
-
-def mkdir(dirname):
-  if not os.path.isdir(dirname):
-    os.makedirs(dirname)
-
-
-if __name__ == '__main__':
-  main()

+ 0 - 221
FirebaseInAppMessaging/ProtoSupport/nanopb_proto_generator.py

@@ -1,221 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright 2019 Google
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Generates and massages protocol buffer outputs.
-"""
-
-from __future__ import print_function
-
-import sys
-
-import io
-import nanopb_generator as nanopb
-import os
-import os.path
-import shlex
-
-from google.protobuf.descriptor_pb2 import FieldDescriptorProto
-
-# The plugin_pb2 package loads descriptors on import, but doesn't defend
-# against multiple imports. Reuse the plugin package as loaded by the
-# nanopb_generator.
-plugin_pb2 = nanopb.plugin_pb2
-nanopb_pb2 = nanopb.nanopb_pb2
-
-
-def main():
-  # Parse request
-  data = io.open(sys.stdin.fileno(), 'rb').read()
-  request = plugin_pb2.CodeGeneratorRequest.FromString(data)
-
-  # Preprocess inputs, changing types and nanopb defaults
-  options = nanopb_parse_options(request)
-  use_anonymous_oneof(request)
-  use_bytes_for_strings(request)
-
-  # Generate code
-  parsed_files = nanopb_parse_files(request, options)
-  results = nanopb_generate(request, options, parsed_files)
-  response = nanopb_write(results)
-
-  # Write to stdout
-  io.open(sys.stdout.fileno(), 'wb').write(response.SerializeToString())
-
-
-def use_anonymous_oneof(request):
-  """Use anonymous unions for oneofs if they're the only one in a message.
-
-  Equivalent to setting this option on messages where it applies:
-
-    option (nanopb).anonymous_oneof = true;
-
-  Args:
-    request: A CodeGeneratorRequest from protoc. The descriptors are modified
-      in place.
-  """
-  for _, message_type in iterate_messages(request):
-    if len(message_type.oneof_decl) == 1:
-      ext = message_type.options.Extensions[nanopb_pb2.nanopb_msgopt]
-      ext.anonymous_oneof = True
-
-
-def use_bytes_for_strings(request):
-  """Always use the bytes type instead of string.
-
-  By default, nanopb renders proto strings as having the C type char* and does
-  not include a separate size field, getting the length of the string via
-  strlen(). Unfortunately this prevents using strings with embedded nulls,
-  which is something the wire format supports.
-
-  Fortunately, string and bytes proto fields are identical on the wire and
-  nanopb's bytes representation does have an explicit length, so this function
-  changes the types of all string fields to bytes. The generated code will now
-  contain pb_bytes_array_t.
-
-  There's no nanopb or proto option to control this behavior. The equivalent
-  would be to hand edit all the .proto files :-(.
-
-  Args:
-    request: A CodeGeneratorRequest from protoc. The descriptors are modified
-      in place.
-  """
-  for names, message_type in iterate_messages(request):
-    for field in message_type.field:
-      if field.type == FieldDescriptorProto.TYPE_STRING:
-        field.type = FieldDescriptorProto.TYPE_BYTES
-
-
-def iterate_messages(request):
-  """Iterates over all messages in all files in the request.
-
-  Args:
-    request: A CodeGeneratorRequest passed by protoc.
-
-  Yields:
-    names: a nanopb.Names object giving a qualified name for the message
-    message_type: a DescriptorProto for the message.
-  """
-  for fdesc in request.proto_file:
-    for names, message_type in nanopb.iterate_messages(fdesc):
-      yield names, message_type
-
-
-def nanopb_parse_options(request):
-  """Parses nanopb_generator command-line options from the given request.
-
-  Args:
-    request: A CodeGeneratorRequest passed by protoc.
-
-  Returns:
-    Nanopb's options object, obtained via optparser.
-  """
-  # Parse options the same as nanopb_generator.main_plugin() does.
-  args = shlex.split(request.parameter)
-  options, _ = nanopb.optparser.parse_args(args)
-
-  # Force certain options
-  options.extension = '.nanopb'
-  options.verbose = True
-
-  # Replicate options setup from nanopb_generator.main_plugin.
-  nanopb.Globals.verbose_options = options.verbose
-
-  # Google's protoc does not currently indicate the full path of proto files.
-  # Instead always add the main file path to the search dirs, that works for
-  # the common case.
-  options.options_path.append(os.path.dirname(request.file_to_generate[0]))
-  return options
-
-
-def nanopb_parse_files(request, options):
-  """Parses the files in the given request into nanopb ProtoFile objects.
-
-  Args:
-    request: A CodeGeneratorRequest, as passed by protoc.
-    options: The command-line options from nanopb_parse_options.
-
-  Returns:
-    A dictionary of filename to nanopb.ProtoFile objects, each one representing
-    the parsed form of a FileDescriptor in the request.
-  """
-  # Process any include files first, in order to have them
-  # available as dependencies
-  parsed_files = {}
-  for fdesc in request.proto_file:
-    parsed_files[fdesc.name] = nanopb.parse_file(fdesc.name, fdesc, options)
-
-  return parsed_files
-
-
-def nanopb_generate(request, options, parsed_files):
-  """Generates C sources from the given parsed files.
-
-  Args:
-    request: A CodeGeneratorRequest, as passed by protoc.
-    options: The command-line options from nanopb_parse_options.
-    parsed_files: A dictionary of filename to nanopb.ProtoFile, as returned by
-      nanopb_parse_files().
-
-  Returns:
-    A list of nanopb output dictionaries, each one representing the code
-    generation result for each file to generate. The output dictionaries have
-    the following form:
-
-        {
-          'headername': Name of header file, ending in .h,
-          'headerdata': Contents of the header file,
-          'sourcename': Name of the source code file, ending in .c,
-          'sourcedata': Contents of the source code file
-        }
-  """
-  output = []
-
-  for filename in request.file_to_generate:
-    for fdesc in request.proto_file:
-      if fdesc.name == filename:
-        results = nanopb.process_file(filename, fdesc, options, parsed_files)
-        output.append(results)
-
-  return output
-
-
-def nanopb_write(results):
-  """Translates nanopb output dictionaries to a CodeGeneratorResponse.
-
-  Args:
-    results: A list of generated source dictionaries, as returned by
-      nanopb_generate().
-
-  Returns:
-    A CodeGeneratorResponse describing the result of the code generation
-    process to protoc.
-  """
-  response = plugin_pb2.CodeGeneratorResponse()
-
-  for result in results:
-    f = response.file.add()
-    f.name = result['headername']
-    f.content = result['headerdata']
-
-    f = response.file.add()
-    f.name = result['sourcename']
-    f.content = result['sourcedata']
-
-  return response
-
-
-if __name__ == '__main__':
-  main()

+ 6 - 6
FirebaseInAppMessaging/Sources/Analytics/Protogen/nanopb/fiam.nanopb.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2019 Google
+ * Copyright 2022 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
  */
 
 /* Automatically generated nanopb constant definitions */
-/* Generated by nanopb-0.3.9.6 */
+/* Generated by nanopb-0.3.9.8 */
 
 #include "FirebaseInAppMessaging/Sources/Analytics/Protogen/nanopb/fiam.nanopb.h"
 
@@ -31,10 +31,10 @@ const pb_field_t logs_proto_firebase_inappmessaging_CampaignAnalytics_fields[10]
     PB_FIELD(  2, BYTES   , OPTIONAL, POINTER , OTHER, logs_proto_firebase_inappmessaging_CampaignAnalytics, campaign_id, project_number, 0),
     PB_FIELD(  3, MESSAGE , OPTIONAL, STATIC  , OTHER, logs_proto_firebase_inappmessaging_CampaignAnalytics, client_app, campaign_id, &logs_proto_firebase_inappmessaging_ClientAppInfo_fields),
     PB_FIELD(  4, INT64   , OPTIONAL, STATIC  , OTHER, logs_proto_firebase_inappmessaging_CampaignAnalytics, client_timestamp_millis, client_app, 0),
-    PB_ANONYMOUS_ONEOF_FIELD(event,   5, ENUM    , ONEOF, STATIC  , OTHER, logs_proto_firebase_inappmessaging_CampaignAnalytics, event_type, client_timestamp_millis, 0),
-    PB_ANONYMOUS_ONEOF_FIELD(event,   6, ENUM    , ONEOF, STATIC  , UNION, logs_proto_firebase_inappmessaging_CampaignAnalytics, dismiss_type, client_timestamp_millis, 0),
-    PB_ANONYMOUS_ONEOF_FIELD(event,   7, ENUM    , ONEOF, STATIC  , UNION, logs_proto_firebase_inappmessaging_CampaignAnalytics, render_error_reason, client_timestamp_millis, 0),
-    PB_ANONYMOUS_ONEOF_FIELD(event,   8, ENUM    , ONEOF, STATIC  , UNION, logs_proto_firebase_inappmessaging_CampaignAnalytics, fetch_error_reason, client_timestamp_millis, 0),
+    PB_ANONYMOUS_ONEOF_FIELD(event,   5, UENUM   , ONEOF, STATIC  , OTHER, logs_proto_firebase_inappmessaging_CampaignAnalytics, event_type, client_timestamp_millis, 0),
+    PB_ANONYMOUS_ONEOF_FIELD(event,   6, UENUM   , ONEOF, STATIC  , UNION, logs_proto_firebase_inappmessaging_CampaignAnalytics, dismiss_type, client_timestamp_millis, 0),
+    PB_ANONYMOUS_ONEOF_FIELD(event,   7, UENUM   , ONEOF, STATIC  , UNION, logs_proto_firebase_inappmessaging_CampaignAnalytics, render_error_reason, client_timestamp_millis, 0),
+    PB_ANONYMOUS_ONEOF_FIELD(event,   8, UENUM   , ONEOF, STATIC  , UNION, logs_proto_firebase_inappmessaging_CampaignAnalytics, fetch_error_reason, client_timestamp_millis, 0),
     PB_FIELD(  9, BYTES   , OPTIONAL, POINTER , OTHER, logs_proto_firebase_inappmessaging_CampaignAnalytics, fiam_sdk_version, fetch_error_reason, 0),
     PB_LAST_FIELD
 };

+ 2 - 2
FirebaseInAppMessaging/Sources/Analytics/Protogen/nanopb/fiam.nanopb.h

@@ -1,5 +1,5 @@
 /*
- * Copyright 2019 Google
+ * Copyright 2022 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
  */
 
 /* Automatically generated nanopb header */
-/* Generated by nanopb-0.3.9.6 */
+/* Generated by nanopb-0.3.9.8 */
 
 #ifndef PB_LOGS_PROTO_FIREBASE_INAPPMESSAGING_FIAM_NANOPB_H_INCLUDED
 #define PB_LOGS_PROTO_FIREBASE_INAPPMESSAGING_FIAM_NANOPB_H_INCLUDED

+ 2 - 28
FirebaseMessaging/ProtoSupport/generate_protos.sh

@@ -22,35 +22,9 @@
 
 readonly DIR="$( git rev-parse --show-toplevel )"
 
-# Current release of nanopb being used  to build the CCT protos
-readonly NANOPB_VERSION="0.3.9.8"
-readonly NANOPB_TEMPDIR="${DIR}/FirebaseMessaging/nanopb_temp"
-
 readonly LIBRARY_DIR="${DIR}/FirebaseMessaging/Sources/"
 readonly PROTO_DIR="${DIR}/FirebaseMessaging/ProtoSupport/Protos/"
 readonly PROTOGEN_DIR="${LIBRARY_DIR}/Protogen/"
+readonly INCLUDE_PREFIX="FirebaseMessaging/Sources/Protogen/nanopb/"
 
-rm -rf "${NANOPB_TEMPDIR}"
-
-echo "Downloading nanopb..."
-git clone --branch "${NANOPB_VERSION}" https://github.com/nanopb/nanopb.git "${NANOPB_TEMPDIR}"
-
-echo "Building nanopb..."
-pushd "${NANOPB_TEMPDIR}"
-./tools/make_mac_package.sh
-GIT_DESCRIPTION=`git describe --always`-macosx-x86
-NANOPB_BIN_DIR="dist/${GIT_DESCRIPTION}"
-popd
-
-echo "Removing existing ME protos..."
-rm -rf "${PROTOGEN_DIR}/*"
-
-echo "Generating ME protos..."
-python "${DIR}/FirebaseMessaging/ProtoSupport/proto_generator.py" \
-  --nanopb \
-  --protos_dir="${PROTO_DIR}" \
-  --pythonpath="${NANOPB_TEMPDIR}/${NANOPB_BIN_DIR}/generator" \
-  --output_dir="${PROTOGEN_DIR}" \
-  --include="${PROTO_DIR}"
-
-rm -rf "${NANOPB_TEMPDIR}"
+./scripts/nanopb/generate_protos.sh "$PROTO_DIR" "$PROTOGEN_DIR" "$INCLUDE_PREFIX"

+ 0 - 221
FirebaseMessaging/ProtoSupport/nanopb_objc_generator.py

@@ -1,221 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright 2019 Google
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Generates and massages protocol buffer outputs.
-"""
-
-from __future__ import print_function
-
-import sys
-
-import io
-import nanopb_generator as nanopb
-import os
-import os.path
-import shlex
-
-from google.protobuf.descriptor_pb2 import FieldDescriptorProto
-
-# The plugin_pb2 package loads descriptors on import, but doesn't defend
-# against multiple imports. Reuse the plugin package as loaded by the
-# nanopb_generator.
-plugin_pb2 = nanopb.plugin_pb2
-nanopb_pb2 = nanopb.nanopb_pb2
-
-
-def main():
-  # Parse request
-  data = io.open(sys.stdin.fileno(), 'rb').read()
-  request = plugin_pb2.CodeGeneratorRequest.FromString(data)
-
-  # Preprocess inputs, changing types and nanopb defaults
-  options = nanopb_parse_options(request)
-  use_anonymous_oneof(request)
-  use_bytes_for_strings(request)
-
-  # Generate code
-  parsed_files = nanopb_parse_files(request, options)
-  results = nanopb_generate(request, options, parsed_files)
-  response = nanopb_write(results)
-
-  # Write to stdout
-  io.open(sys.stdout.fileno(), 'wb').write(response.SerializeToString())
-
-
-def use_anonymous_oneof(request):
-  """Use anonymous unions for oneofs if they're the only one in a message.
-
-  Equivalent to setting this option on messages where it applies:
-
-    option (nanopb).anonymous_oneof = true;
-
-  Args:
-    request: A CodeGeneratorRequest from protoc. The descriptors are modified
-      in place.
-  """
-  for _, message_type in iterate_messages(request):
-    if len(message_type.oneof_decl) == 1:
-      ext = message_type.options.Extensions[nanopb_pb2.nanopb_msgopt]
-      ext.anonymous_oneof = True
-
-
-def use_bytes_for_strings(request):
-  """Always use the bytes type instead of string.
-
-  By default, nanopb renders proto strings as having the C type char* and does
-  not include a separate size field, getting the length of the string via
-  strlen(). Unfortunately this prevents using strings with embedded nulls,
-  which is something the wire format supports.
-
-  Fortunately, string and bytes proto fields are identical on the wire and
-  nanopb's bytes representation does have an explicit length, so this function
-  changes the types of all string fields to bytes. The generated code will now
-  contain pb_bytes_array_t.
-
-  There's no nanopb or proto option to control this behavior. The equivalent
-  would be to hand edit all the .proto files :-(.
-
-  Args:
-    request: A CodeGeneratorRequest from protoc. The descriptors are modified
-      in place.
-  """
-  for names, message_type in iterate_messages(request):
-    for field in message_type.field:
-      if field.type == FieldDescriptorProto.TYPE_STRING:
-        field.type = FieldDescriptorProto.TYPE_BYTES
-
-
-def iterate_messages(request):
-  """Iterates over all messages in all files in the request.
-
-  Args:
-    request: A CodeGeneratorRequest passed by protoc.
-
-  Yields:
-    names: a nanopb.Names object giving a qualified name for the message
-    message_type: a DescriptorProto for the message.
-  """
-  for fdesc in request.proto_file:
-    for names, message_type in nanopb.iterate_messages(fdesc):
-      yield names, message_type
-
-
-def nanopb_parse_options(request):
-  """Parses nanopb_generator command-line options from the given request.
-
-  Args:
-    request: A CodeGeneratorRequest passed by protoc.
-
-  Returns:
-    Nanopb's options object, obtained via optparser.
-  """
-  # Parse options the same as nanopb_generator.main_plugin() does.
-  args = shlex.split(request.parameter)
-  options, _ = nanopb.optparser.parse_args(args)
-
-  # Force certain options
-  options.extension = '.nanopb'
-  options.verbose = True
-
-  # Replicate options setup from nanopb_generator.main_plugin.
-  nanopb.Globals.verbose_options = options.verbose
-
-  # Google's protoc does not currently indicate the full path of proto files.
-  # Instead always add the main file path to the search dirs, that works for
-  # the common case.
-  options.options_path.append(os.path.dirname(request.file_to_generate[0]))
-  return options
-
-
-def nanopb_parse_files(request, options):
-  """Parses the files in the given request into nanopb ProtoFile objects.
-
-  Args:
-    request: A CodeGeneratorRequest, as passed by protoc.
-    options: The command-line options from nanopb_parse_options.
-
-  Returns:
-    A dictionary of filename to nanopb.ProtoFile objects, each one representing
-    the parsed form of a FileDescriptor in the request.
-  """
-  # Process any include files first, in order to have them
-  # available as dependencies
-  parsed_files = {}
-  for fdesc in request.proto_file:
-    parsed_files[fdesc.name] = nanopb.parse_file(fdesc.name, fdesc, options)
-
-  return parsed_files
-
-
-def nanopb_generate(request, options, parsed_files):
-  """Generates C sources from the given parsed files.
-
-  Args:
-    request: A CodeGeneratorRequest, as passed by protoc.
-    options: The command-line options from nanopb_parse_options.
-    parsed_files: A dictionary of filename to nanopb.ProtoFile, as returned by
-      nanopb_parse_files().
-
-  Returns:
-    A list of nanopb output dictionaries, each one representing the code
-    generation result for each file to generate. The output dictionaries have
-    the following form:
-
-        {
-          'headername': Name of header file, ending in .h,
-          'headerdata': Contents of the header file,
-          'sourcename': Name of the source code file, ending in .c,
-          'sourcedata': Contents of the source code file
-        }
-  """
-  output = []
-
-  for filename in request.file_to_generate:
-    for fdesc in request.proto_file:
-      if fdesc.name == filename:
-        results = nanopb.process_file(filename, fdesc, options, parsed_files)
-        output.append(results)
-
-  return output
-
-
-def nanopb_write(results):
-  """Translates nanopb output dictionaries to a CodeGeneratorResponse.
-
-  Args:
-    results: A list of generated source dictionaries, as returned by
-      nanopb_generate().
-
-  Returns:
-    A CodeGeneratorResponse describing the result of the code generation
-    process to protoc.
-  """
-  response = plugin_pb2.CodeGeneratorResponse()
-
-  for result in results:
-    f = response.file.add()
-    f.name = result['headername']
-    f.content = result['headerdata']
-
-    f = response.file.add()
-    f.name = result['sourcename']
-    f.content = result['sourcedata']
-
-  return response
-
-
-if __name__ == '__main__':
-  main()

+ 0 - 324
FirebaseMessaging/ProtoSupport/proto_generator.py

@@ -1,324 +0,0 @@
-#! /usr/bin/env python
-
-# Copyright 2021 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Generates and massages protocol buffer outputs.
-
-Example usage:
-
-python GoogleDataTransport/GoogleDataTransportCCTSupport/ProtoSupport/build_protos.py \
-  --nanopb \
-  --protos_dir=GoogleDataTransport/GoogleDataTransportCCTSupport/Classes/Protos/ \
-  --pythonpath=~/Downloads/nanopb-0.3.9.2-macosx-x86/generator/ \
-  --output_dir=GoogleDataTransport/GoogleDataTransportCCTSupport/Classes/Protogen/
-"""
-
-from __future__ import print_function
-
-import sys
-
-import argparse
-import os
-import os.path
-import re
-import subprocess
-
-OBJC_GENERATOR='nanopb_objc_generator.py'
-
-COPYRIGHT_NOTICE = '''
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-'''.lstrip()
-
-
-def main():
-  parser = argparse.ArgumentParser(
-      description='Generates proto messages.')
-  parser.add_argument(
-      '--nanopb', action='store_true',
-      help='Generates nanopb messages.')
-  parser.add_argument(
-      '--objc', action='store_true',
-      help='Generates Objective-C messages.')
-  parser.add_argument(
-      '--protos_dir',
-      help='Source directory containing .proto files.')
-  parser.add_argument(
-      '--output_dir', '-d',
-      help='Directory to write files; subdirectories will be created.')
-  parser.add_argument(
-      '--protoc', default='protoc',
-      help='Location of the protoc executable')
-  parser.add_argument(
-      '--pythonpath',
-      help='Location of the protoc python library.')
-  parser.add_argument(
-      '--include', '-I', action='append', default=[],
-      help='Adds INCLUDE to the proto path.')
-
-
-  args = parser.parse_args()
-  if args.nanopb is None and args.objc is None:
-    parser.print_help()
-    sys.exit(1)
-
-  if args.protos_dir is None:
-    root_dir = os.path.abspath(os.path.dirname(__file__))
-    args.protos_dir = os.path.join(root_dir, 'protos')
-
-  if args.output_dir is None:
-    root_dir = os.path.abspath(os.path.dirname(__file__))
-    args.output_dir = os.path.join(root_dir, 'protogen-please-supply-an-outputdir')
-
-  all_proto_files = collect_files(args.protos_dir, '.proto')
-  if args.nanopb:
-    NanopbGenerator(args, all_proto_files).run()
-
-  proto_files = remove_well_known_protos(all_proto_files)
-
-  if args.objc:
-    ObjcProtobufGenerator(args, proto_files).run()
-
-
-class NanopbGenerator(object):
-  """Builds and runs the nanopb plugin to protoc."""
-
-  def __init__(self, args, proto_files):
-    self.args = args
-    self.proto_files = proto_files
-
-  def run(self):
-    """Performs the action of the generator."""
-
-    nanopb_out = os.path.join(self.args.output_dir, 'nanopb')
-    mkdir(nanopb_out)
-
-    self.__run_generator(nanopb_out)
-
-    sources = collect_files(nanopb_out, '.nanopb.h', '.nanopb.c')
-    post_process_files(
-        sources,
-        add_copyright,
-        nanopb_remove_extern_c,
-        nanopb_rename_delete,
-        nanopb_use_module_import
-    )
-
-  def __run_generator(self, out_dir):
-    """Invokes protoc using the nanopb plugin."""
-    cmd = protoc_command(self.args)
-
-    gen = os.path.join(os.path.dirname(__file__), OBJC_GENERATOR)
-    cmd.append('--plugin=protoc-gen-nanopb=%s' % gen)
-
-    nanopb_flags = [
-        '--extension=.nanopb',
-        '--source-extension=.c',
-        '--no-timestamp'
-    ]
-    nanopb_flags.extend(['-I%s' % path for path in self.args.include])
-    cmd.append('--nanopb_out=%s:%s' % (' '.join(nanopb_flags), out_dir))
-
-    cmd.extend(self.proto_files)
-    run_protoc(self.args, cmd)
-
-
-def protoc_command(args):
-  """Composes the initial protoc command-line including its include path."""
-  cmd = [args.protoc]
-  if args.include is not None:
-    cmd.extend(['-I=%s' % path for path in args.include])
-  return cmd
-
-
-def run_protoc(args, cmd):
-  """Actually runs the given protoc command.
-
-  Args:
-    args: The command-line args (including pythonpath)
-    cmd: The command to run expressed as a list of strings
-  """
-
-  kwargs = {}
-  if args.pythonpath:
-    env = os.environ.copy()
-    old_path = env.get('PYTHONPATH')
-    env['PYTHONPATH'] = os.path.expanduser(args.pythonpath)
-    if old_path is not None:
-      env['PYTHONPATH'] += os.pathsep + old_path
-    kwargs['env'] = env
-
-  try:
-    print(subprocess.check_output(cmd, stderr=subprocess.STDOUT, **kwargs))
-  except subprocess.CalledProcessError as error:
-    print('command failed: ', ' '.join(cmd), '\nerror: ', error.output)
-
-
-def remove_well_known_protos(filenames):
-  """Remove "well-known" protos for objc.
-
-  On those platforms we get these for free as a part of the protobuf runtime.
-  We only need them for nanopb.
-
-  Args:
-    filenames: A list of filenames, each naming a .proto file.
-
-  Returns:
-    The filenames with members of google/protobuf removed.
-  """
-
-  return [f for f in filenames if 'protos/google/protobuf/' not in f]
-
-
-def post_process_files(filenames, *processors):
-  for filename in filenames:
-    lines = []
-    with open(filename, 'r') as fd:
-      lines = fd.readlines()
-
-    for processor in processors:
-      lines = processor(lines)
-
-    write_file(filename, lines)
-
-
-def write_file(filename, lines):
-  mkdir(os.path.dirname(filename))
-  with open(filename, 'w') as fd:
-    fd.write(''.join(lines))
-
-
-def add_copyright(lines):
-  """Adds a copyright notice to the lines."""
-  result = [COPYRIGHT_NOTICE, '\n']
-  result.extend(lines)
-  return result
-
-
-def nanopb_remove_extern_c(lines):
-  """Removes extern "C" directives from nanopb code.
-
-  Args:
-    lines: A nanobp-generated source file, split into lines.
-  Returns:
-    A list of strings, similar to the input but modified to remove extern "C".
-  """
-  result = []
-  state = 'initial'
-  for line in lines:
-    if state == 'initial':
-      if '#ifdef __cplusplus' in line:
-        state = 'in-ifdef'
-        continue
-
-      result.append(line)
-
-    elif state == 'in-ifdef':
-      if '#endif' in line:
-        state = 'initial'
-
-  return result
-
-
-def nanopb_rename_delete(lines):
-  """Renames a delete symbol to delete_.
-
-  If a proto uses a field named 'delete', nanopb happily uses that in the
-  message definition. Works fine for C; not so much for C++.
-
-  Args:
-    lines: The lines to fix.
-
-  Returns:
-    The lines, fixed.
-  """
-  delete_keyword = re.compile(r'\bdelete\b')
-  return [delete_keyword.sub('delete_', line) for line in lines]
-
-
-def nanopb_use_module_import(lines):
-  """Changes #include <pb.h> to include <nanopb/pb.h>""" # Don't let Copybara alter these lines.
-  return [line.replace('#include <pb.h>', '{}include <nanopb/pb.h>'.format("#")) for line in lines]
-
-
-def strip_trailing_whitespace(lines):
-  """Removes trailing whitespace from the given lines."""
-  return [line.rstrip() + '\n' for line in lines]
-
-
-def objc_flatten_imports(lines):
-  """Flattens the import statements for compatibility with CocoaPods."""
-
-  long_import = re.compile(r'#import ".*/')
-  return [long_import.sub('#import "', line) for line in lines]
-
-
-def objc_strip_extension_registry(lines):
-  """Removes extensionRegistry methods from the classes."""
-  skip = False
-  result = []
-  for line in lines:
-    if '+ (GPBExtensionRegistry*)extensionRegistry {' in line:
-      skip = True
-    if not skip:
-      result.append(line)
-    elif line == '}\n':
-      skip = False
-
-  return result
-
-
-def collect_files(root_dir, *extensions):
-  """Finds files with the given extensions in the root_dir.
-
-  Args:
-    root_dir: The directory from which to start traversing.
-    *extensions: Filename extensions (including the leading dot) to find.
-
-  Returns:
-    A list of filenames, all starting with root_dir, that have one of the given
-    extensions.
-  """
-  result = []
-  for root, _, files in os.walk(root_dir):
-    for basename in files:
-      for ext in extensions:
-        if basename.endswith(ext):
-          filename = os.path.join(root, basename)
-          result.append(filename)
-  return result
-
-
-def mkdir(dirname):
-  if not os.path.isdir(dirname):
-    os.makedirs(dirname)
-
-
-if __name__ == '__main__':
-  main()
-

+ 1 - 1
FirebaseMessaging/Sources/Protogen/nanopb/me.nanopb.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 Google LLC
+ * Copyright 2022 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.

+ 1 - 1
FirebaseMessaging/Sources/Protogen/nanopb/me.nanopb.h

@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 Google LLC
+ * Copyright 2022 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.

+ 2 - 28
FirebasePerformance/ProtoSupport/generate_protos.sh

@@ -22,35 +22,9 @@
 
 readonly DIR="$( git rev-parse --show-toplevel )"
 
-# Current release of nanopb being used  to build the CCT protos
-readonly NANOPB_VERSION="0.3.9.8"
-readonly NANOPB_TEMPDIR="${DIR}/FirebasePerformance/nanopb_temp"
-
 readonly LIBRARY_DIR="${DIR}/FirebasePerformance/Sources/"
 readonly PROTO_DIR="${DIR}/FirebasePerformance/ProtoSupport/Protos/"
 readonly PROTOGEN_DIR="${LIBRARY_DIR}/Protogen/"
+readonly INCLUDE_PREFIX="FirebasePerformance/Sources/Protogen/nanopb/"
 
-rm -rf "${NANOPB_TEMPDIR}"
-
-echo "Downloading nanopb..."
-git clone --branch "${NANOPB_VERSION}" https://github.com/nanopb/nanopb.git "${NANOPB_TEMPDIR}"
-
-echo "Building nanopb..."
-pushd "${NANOPB_TEMPDIR}"
-./tools/make_mac_package.sh
-GIT_DESCRIPTION=`git describe --always`-macosx-x86
-NANOPB_BIN_DIR="dist/${GIT_DESCRIPTION}"
-popd
-
-echo "Removing existing generated proto files..."
-rm -rf "${PROTOGEN_DIR}/*"
-
-echo "Generating Perf_metric protos..."
-python "${DIR}/FirebasePerformance/ProtoSupport/proto_generator.py" \
-  --nanopb \
-  --protos_dir="${PROTO_DIR}" \
-  --pythonpath="${NANOPB_TEMPDIR}/${NANOPB_BIN_DIR}/generator" \
-  --output_dir="${PROTOGEN_DIR}" \
-  --include="${PROTO_DIR}"
-
-rm -rf "${NANOPB_TEMPDIR}"
+./scripts/nanopb/generate_protos.sh "$PROTO_DIR" "$PROTOGEN_DIR" "$INCLUDE_PREFIX"

+ 0 - 221
FirebasePerformance/ProtoSupport/nanopb_objc_generator.py

@@ -1,221 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright 2021 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Generates and massages protocol buffer outputs.
-"""
-
-from __future__ import print_function
-
-import sys
-
-import io
-import nanopb_generator as nanopb
-import os
-import os.path
-import shlex
-
-from google.protobuf.descriptor_pb2 import FieldDescriptorProto
-
-# The plugin_pb2 package loads descriptors on import, but doesn't defend
-# against multiple imports. Reuse the plugin package as loaded by the
-# nanopb_generator.
-plugin_pb2 = nanopb.plugin_pb2
-nanopb_pb2 = nanopb.nanopb_pb2
-
-
-def main():
-  # Parse request
-  data = io.open(sys.stdin.fileno(), 'rb').read()
-  request = plugin_pb2.CodeGeneratorRequest.FromString(data)
-
-  # Preprocess inputs, changing types and nanopb defaults
-  options = nanopb_parse_options(request)
-  use_anonymous_oneof(request)
-  use_bytes_for_strings(request)
-
-  # Generate code
-  parsed_files = nanopb_parse_files(request, options)
-  results = nanopb_generate(request, options, parsed_files)
-  response = nanopb_write(results)
-
-  # Write to stdout
-  io.open(sys.stdout.fileno(), 'wb').write(response.SerializeToString())
-
-
-def use_anonymous_oneof(request):
-  """Use anonymous unions for oneofs if they're the only one in a message.
-
-  Equivalent to setting this option on messages where it applies:
-
-    option (nanopb).anonymous_oneof = true;
-
-  Args:
-    request: A CodeGeneratorRequest from protoc. The descriptors are modified
-      in place.
-  """
-  for _, message_type in iterate_messages(request):
-    if len(message_type.oneof_decl) == 1:
-      ext = message_type.options.Extensions[nanopb_pb2.nanopb_msgopt]
-      ext.anonymous_oneof = True
-
-
-def use_bytes_for_strings(request):
-  """Always use the bytes type instead of string.
-
-  By default, nanopb renders proto strings as having the C type char* and does
-  not include a separate size field, getting the length of the string via
-  strlen(). Unfortunately this prevents using strings with embedded nulls,
-  which is something the wire format supports.
-
-  Fortunately, string and bytes proto fields are identical on the wire and
-  nanopb's bytes representation does have an explicit length, so this function
-  changes the types of all string fields to bytes. The generated code will now
-  contain pb_bytes_array_t.
-
-  There's no nanopb or proto option to control this behavior. The equivalent
-  would be to hand edit all the .proto files :-(.
-
-  Args:
-    request: A CodeGeneratorRequest from protoc. The descriptors are modified
-      in place.
-  """
-  for names, message_type in iterate_messages(request):
-    for field in message_type.field:
-      if field.type == FieldDescriptorProto.TYPE_STRING:
-        field.type = FieldDescriptorProto.TYPE_BYTES
-
-
-def iterate_messages(request):
-  """Iterates over all messages in all files in the request.
-
-  Args:
-    request: A CodeGeneratorRequest passed by protoc.
-
-  Yields:
-    names: a nanopb.Names object giving a qualified name for the message
-    message_type: a DescriptorProto for the message.
-  """
-  for fdesc in request.proto_file:
-    for names, message_type in nanopb.iterate_messages(fdesc):
-      yield names, message_type
-
-
-def nanopb_parse_options(request):
-  """Parses nanopb_generator command-line options from the given request.
-
-  Args:
-    request: A CodeGeneratorRequest passed by protoc.
-
-  Returns:
-    Nanopb's options object, obtained via optparser.
-  """
-  # Parse options the same as nanopb_generator.main_plugin() does.
-  args = shlex.split(request.parameter)
-  options, _ = nanopb.optparser.parse_args(args)
-
-  # Force certain options
-  options.extension = '.nanopb'
-  options.verbose = True
-
-  # Replicate options setup from nanopb_generator.main_plugin.
-  nanopb.Globals.verbose_options = options.verbose
-
-  # Google's protoc does not currently indicate the full path of proto files.
-  # Instead always add the main file path to the search dirs, that works for
-  # the common case.
-  options.options_path.append(os.path.dirname(request.file_to_generate[0]))
-  return options
-
-
-def nanopb_parse_files(request, options):
-  """Parses the files in the given request into nanopb ProtoFile objects.
-
-  Args:
-    request: A CodeGeneratorRequest, as passed by protoc.
-    options: The command-line options from nanopb_parse_options.
-
-  Returns:
-    A dictionary of filename to nanopb.ProtoFile objects, each one representing
-    the parsed form of a FileDescriptor in the request.
-  """
-  # Process any include files first, in order to have them
-  # available as dependencies
-  parsed_files = {}
-  for fdesc in request.proto_file:
-    parsed_files[fdesc.name] = nanopb.parse_file(fdesc.name, fdesc, options)
-
-  return parsed_files
-
-
-def nanopb_generate(request, options, parsed_files):
-  """Generates C sources from the given parsed files.
-
-  Args:
-    request: A CodeGeneratorRequest, as passed by protoc.
-    options: The command-line options from nanopb_parse_options.
-    parsed_files: A dictionary of filename to nanopb.ProtoFile, as returned by
-      nanopb_parse_files().
-
-  Returns:
-    A list of nanopb output dictionaries, each one representing the code
-    generation result for each file to generate. The output dictionaries have
-    the following form:
-
-        {
-          'headername': Name of header file, ending in .h,
-          'headerdata': Contents of the header file,
-          'sourcename': Name of the source code file, ending in .c,
-          'sourcedata': Contents of the source code file
-        }
-  """
-  output = []
-
-  for filename in request.file_to_generate:
-    for fdesc in request.proto_file:
-      if fdesc.name == filename:
-        results = nanopb.process_file(filename, fdesc, options, parsed_files)
-        output.append(results)
-
-  return output
-
-
-def nanopb_write(results):
-  """Translates nanopb output dictionaries to a CodeGeneratorResponse.
-
-  Args:
-    results: A list of generated source dictionaries, as returned by
-      nanopb_generate().
-
-  Returns:
-    A CodeGeneratorResponse describing the result of the code generation
-    process to protoc.
-  """
-  response = plugin_pb2.CodeGeneratorResponse()
-
-  for result in results:
-    f = response.file.add()
-    f.name = result['headername']
-    f.content = result['headerdata']
-
-    f = response.file.add()
-    f.name = result['sourcename']
-    f.content = result['sourcedata']
-
-  return response
-
-
-if __name__ == '__main__':
-  main()

+ 0 - 324
FirebasePerformance/ProtoSupport/proto_generator.py

@@ -1,324 +0,0 @@
-#! /usr/bin/env python
-
-# Copyright 2021 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Generates and massages protocol buffer outputs.
-
-Example usage:
-
-python FirebasePerformance/ProtoSupport/proto_generator.py \
-  --nanopb \
-  --protos_dir=FirebasePerformance/ProtoSupport/Protos/ \
-  --pythonpath=~/Downloads/nanopb-0.3.9.8-macosx-x86/generator/ \
-  --output_dir=FirebasePerformance/Sources//Protogen/ \
-  --include=FirebasePerformance/ProtoSupport/Protos/
-"""
-
-from __future__ import print_function
-
-import sys
-
-import argparse
-import os
-import os.path
-import re
-import subprocess
-
-OBJC_GENERATOR='nanopb_objc_generator.py'
-
-COPYRIGHT_NOTICE = '''
-/*
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-'''.lstrip()
-
-
-def main():
-  parser = argparse.ArgumentParser(
-      description='Generates proto messages.')
-  parser.add_argument(
-      '--nanopb', action='store_true',
-      help='Generates nanopb messages.')
-  parser.add_argument(
-      '--objc', action='store_true',
-      help='Generates Objective-C messages.')
-  parser.add_argument(
-      '--protos_dir',
-      help='Source directory containing .proto files.')
-  parser.add_argument(
-      '--output_dir', '-d',
-      help='Directory to write files; subdirectories will be created.')
-  parser.add_argument(
-      '--protoc', default='protoc',
-      help='Location of the protoc executable')
-  parser.add_argument(
-      '--pythonpath',
-      help='Location of the protoc python library.')
-  parser.add_argument(
-      '--include', '-I', action='append', default=[],
-      help='Adds INCLUDE to the proto path.')
-
-
-  args = parser.parse_args()
-  if args.nanopb is None and args.objc is None:
-    parser.print_help()
-    sys.exit(1)
-
-  if args.protos_dir is None:
-    root_dir = os.path.abspath(os.path.dirname(__file__))
-    args.protos_dir = os.path.join(root_dir, 'protos')
-
-  if args.output_dir is None:
-    root_dir = os.path.abspath(os.path.dirname(__file__))
-    args.output_dir = os.path.join(root_dir, 'protogen-please-supply-an-outputdir')
-
-  all_proto_files = collect_files(args.protos_dir, '.proto')
-  if args.nanopb:
-    NanopbGenerator(args, all_proto_files).run()
-
-  proto_files = remove_well_known_protos(all_proto_files)
-
-  if args.objc:
-    ObjcProtobufGenerator(args, proto_files).run()
-
-
-class NanopbGenerator(object):
-  """Builds and runs the nanopb plugin to protoc."""
-
-  def __init__(self, args, proto_files):
-    self.args = args
-    self.proto_files = proto_files
-
-  def run(self):
-    """Performs the action of the generator."""
-
-    nanopb_out = os.path.join(self.args.output_dir, 'nanopb')
-    mkdir(nanopb_out)
-
-    self.__run_generator(nanopb_out)
-
-    sources = collect_files(nanopb_out, '.nanopb.h', '.nanopb.c')
-    post_process_files(
-        sources,
-        add_copyright,
-        nanopb_remove_extern_c,
-        nanopb_rename_delete,
-        nanopb_use_module_import
-    )
-
-  def __run_generator(self, out_dir):
-    """Invokes protoc using the nanopb plugin."""
-    cmd = protoc_command(self.args)
-
-    gen = os.path.join(os.path.dirname(__file__), OBJC_GENERATOR)
-    cmd.append('--plugin=protoc-gen-nanopb=%s' % gen)
-
-    nanopb_flags = [
-        '--extension=.nanopb',
-        '--source-extension=.c',
-        '--no-timestamp'
-    ]
-    nanopb_flags.extend(['-I%s' % path for path in self.args.include])
-    cmd.append('--nanopb_out=%s:%s' % (' '.join(nanopb_flags), out_dir))
-
-    cmd.extend(self.proto_files)
-    run_protoc(self.args, cmd)
-
-
-def protoc_command(args):
-  """Composes the initial protoc command-line including its include path."""
-  cmd = [args.protoc]
-  if args.include is not None:
-    cmd.extend(['-I=%s' % path for path in args.include])
-  return cmd
-
-
-def run_protoc(args, cmd):
-  """Actually runs the given protoc command.
-
-  Args:
-    args: The command-line args (including pythonpath)
-    cmd: The command to run expressed as a list of strings
-  """
-
-  kwargs = {}
-  if args.pythonpath:
-    env = os.environ.copy()
-    old_path = env.get('PYTHONPATH')
-    env['PYTHONPATH'] = os.path.expanduser(args.pythonpath)
-    if old_path is not None:
-      env['PYTHONPATH'] += os.pathsep + old_path
-    kwargs['env'] = env
-
-  try:
-    print(subprocess.check_output(cmd, stderr=subprocess.STDOUT, **kwargs))
-  except subprocess.CalledProcessError as error:
-    print('command failed: ', ' '.join(cmd), '\nerror: ', error.output)
-
-
-def remove_well_known_protos(filenames):
-  """Remove "well-known" protos for objc.
-
-  On those platforms we get these for free as a part of the protobuf runtime.
-  We only need them for nanopb.
-
-  Args:
-    filenames: A list of filenames, each naming a .proto file.
-
-  Returns:
-    The filenames with members of google/protobuf removed.
-  """
-
-  return [f for f in filenames if 'protos/google/protobuf/' not in f]
-
-
-def post_process_files(filenames, *processors):
-  for filename in filenames:
-    lines = []
-    with open(filename, 'r') as fd:
-      lines = fd.readlines()
-
-    for processor in processors:
-      lines = processor(lines)
-
-    write_file(filename, lines)
-
-
-def write_file(filename, lines):
-  mkdir(os.path.dirname(filename))
-  with open(filename, 'w') as fd:
-    fd.write(''.join(lines))
-
-
-def add_copyright(lines):
-  """Adds a copyright notice to the lines."""
-  result = [COPYRIGHT_NOTICE, '\n']
-  result.extend(lines)
-  return result
-
-
-def nanopb_remove_extern_c(lines):
-  """Removes extern "C" directives from nanopb code.
-
-  Args:
-    lines: A nanobp-generated source file, split into lines.
-  Returns:
-    A list of strings, similar to the input but modified to remove extern "C".
-  """
-  result = []
-  state = 'initial'
-  for line in lines:
-    if state == 'initial':
-      if '#ifdef __cplusplus' in line:
-        state = 'in-ifdef'
-        continue
-
-      result.append(line)
-
-    elif state == 'in-ifdef':
-      if '#endif' in line:
-        state = 'initial'
-
-  return result
-
-
-def nanopb_rename_delete(lines):
-  """Renames a delete symbol to delete_.
-
-  If a proto uses a field named 'delete', nanopb happily uses that in the
-  message definition. Works fine for C; not so much for C++.
-
-  Args:
-    lines: The lines to fix.
-
-  Returns:
-    The lines, fixed.
-  """
-  delete_keyword = re.compile(r'\bdelete\b')
-  return [delete_keyword.sub('delete_', line) for line in lines]
-
-
-def nanopb_use_module_import(lines):
-  """Changes #include <pb.h> to include <nanopb/pb.h>""" # Don't let Copybara alter these lines.
-  return [line.replace('#include <pb.h>', '{}include <nanopb/pb.h>'.format("#")) for line in lines]
-
-
-def strip_trailing_whitespace(lines):
-  """Removes trailing whitespace from the given lines."""
-  return [line.rstrip() + '\n' for line in lines]
-
-
-def objc_flatten_imports(lines):
-  """Flattens the import statements for compatibility with CocoaPods."""
-
-  long_import = re.compile(r'#import ".*/')
-  return [long_import.sub('#import "', line) for line in lines]
-
-
-def objc_strip_extension_registry(lines):
-  """Removes extensionRegistry methods from the classes."""
-  skip = False
-  result = []
-  for line in lines:
-    if '+ (GPBExtensionRegistry*)extensionRegistry {' in line:
-      skip = True
-    if not skip:
-      result.append(line)
-    elif line == '}\n':
-      skip = False
-
-  return result
-
-
-def collect_files(root_dir, *extensions):
-  """Finds files with the given extensions in the root_dir.
-
-  Args:
-    root_dir: The directory from which to start traversing.
-    *extensions: Filename extensions (including the leading dot) to find.
-
-  Returns:
-    A list of filenames, all starting with root_dir, that have one of the given
-    extensions.
-  """
-  result = []
-  for root, _, files in os.walk(root_dir):
-    for basename in files:
-      for ext in extensions:
-        if basename.endswith(ext):
-          filename = os.path.join(root, basename)
-          result.append(filename)
-  return result
-
-
-def mkdir(dirname):
-  if not os.path.isdir(dirname):
-    os.makedirs(dirname)
-
-
-if __name__ == '__main__':
-  main()

+ 1 - 1
FirebasePerformance/Sources/Protogen/nanopb/perf_metric.nanopb.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 Google LLC
+ * Copyright 2022 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.

+ 1 - 1
FirebasePerformance/Sources/Protogen/nanopb/perf_metric.nanopb.h

@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 Google LLC
+ * Copyright 2022 Google LLC
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.

+ 1 - 1
FirebaseSessions/Protogen/nanopb/clientanalytics.nanopb.c

@@ -17,7 +17,7 @@
 /* Automatically generated nanopb constant definitions */
 /* Generated by nanopb-0.3.9.8 */
 
-#include "clientanalytics.nanopb.h"
+#include "FirebaseSessions/Protogen/nanopb/clientanalytics.nanopb.h"
 
 /* @@protoc_insertion_point(includes) */
 #if PB_PROTO_HEADER_VERSION != 30

+ 25 - 0
FirebaseSessions/generate_protos.sh

@@ -0,0 +1,25 @@
+#!/bin/bash
+
+# Copyright 2022 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+readonly DIR="$( git rev-parse --show-toplevel )"
+
+readonly LIBRARY_DIR="${DIR}/FirebaseSessions/Sources/"
+readonly PROTO_DIR="${DIR}/FirebaseSessions/ProtoSupport/Protos/"
+readonly PROTOGEN_DIR="${DIR}/FirebaseSessions/Protogen/"
+readonly INCLUDE_PREFIX="FirebaseSessions/Protogen/nanopb/"
+
+./scripts/nanopb/generate_protos.sh "$PROTO_DIR" "$PROTOGEN_DIR" "$INCLUDE_PREFIX"

+ 18 - 11
FirebaseSessions/ProtoSupport/generate_protos.sh → scripts/nanopb/generate_protos.sh

@@ -24,34 +24,41 @@ readonly DIR="$( git rev-parse --show-toplevel )"
 
 # Current release of nanopb being used  to build the CCT protos
 readonly NANOPB_VERSION="0.3.9.8"
-readonly NANOPB_TEMPDIR="${DIR}/FirebaseSessions/nanopb_temp"
+readonly NANOPB_TEMPDIR="${DIR}/scripts/nanopb/nanopb_temp"
 
-readonly LIBRARY_DIR="${DIR}/FirebaseSessions/Sources/"
-readonly PROTO_DIR="${DIR}/FirebaseSessions/ProtoSupport/Protos/"
-readonly PROTOGEN_DIR="${DIR}/FirebaseSessions/Protogen/"
+readonly PROTO_DIR="$1"
+readonly PROTOGEN_DIR="$2"
+readonly INCLUDE_PREFIX="$3"
+
+echoColor() {
+  COLOR='\033[0;35m'
+  NC='\033[0m'
+  printf "${COLOR}$1${NC}\n"
+}
 
 rm -rf "${NANOPB_TEMPDIR}"
 
-echo "Downloading nanopb..."
+echoColor "Downloading nanopb..."
 git clone --branch "${NANOPB_VERSION}" https://github.com/nanopb/nanopb.git "${NANOPB_TEMPDIR}"
 
-echo "Building nanopb..."
+echoColor "Building nanopb..."
 pushd "${NANOPB_TEMPDIR}"
 ./tools/make_mac_package.sh
 GIT_DESCRIPTION=`git describe --always`-macosx-x86
 NANOPB_BIN_DIR="dist/${GIT_DESCRIPTION}"
 popd
 
-echo "Removing existing protos..."
+echoColor "Removing existing protos..."
 rm -rf "${PROTOGEN_DIR}/*"
 
-echo "Generating protos..."
-python "${DIR}/FirebaseSessions/ProtoSupport/proto_generator.py" \
+echoColor "Generating protos..."
+python "${DIR}/scripts/nanopb/proto_generator.py" \
   --nanopb \
   --protos_dir="${PROTO_DIR}" \
   --pythonpath="${NANOPB_TEMPDIR}/${NANOPB_BIN_DIR}/generator" \
   --output_dir="${PROTOGEN_DIR}" \
-  --include="${PROTO_DIR}"
+  --include="${PROTO_DIR}" \
+  --include_prefix="${INCLUDE_PREFIX}"
 
 rm -rf "${NANOPB_TEMPDIR}"
 
@@ -59,6 +66,6 @@ RED='\033[0;31m'
 NC='\033[0m'
 echo ""
 echo ""
-echo -e "${RED}Important: Any new proto fields of type string, repeated, or bytes must be specified in the sessions.options file${NC}"
+echo -e "${RED}Important: Any new proto fields of type string, repeated, or bytes must be specified in the proto's .options file with type:FT_POINTER${NC}"
 echo ""
 echo ""

+ 0 - 0
FirebaseSessions/ProtoSupport/nanopb_objc_generator.py → scripts/nanopb/nanopb_objc_generator.py


+ 35 - 4
FirebaseSessions/ProtoSupport/proto_generator.py → scripts/nanopb/proto_generator.py

@@ -26,6 +26,7 @@ python Crashlytics/ProtoSupport/build_protos.py \
 """
 
 from __future__ import print_function
+from inspect import signature
 
 import sys
 
@@ -35,6 +36,7 @@ import os.path
 import re
 import subprocess
 
+
 OBJC_GENERATOR='nanopb_objc_generator.py'
 
 COPYRIGHT_NOTICE = '''
@@ -80,6 +82,9 @@ def main():
   parser.add_argument(
       '--include', '-I', action='append', default=[],
       help='Adds INCLUDE to the proto path.')
+  parser.add_argument(
+      '--include_prefix', '-p', action='append', default=[],
+      help='Adds include_prefix to the <product>.nanopb.h include in .nanopb.c')
 
 
   args = parser.parse_args()
@@ -126,7 +131,8 @@ class NanopbGenerator(object):
         add_copyright,
         nanopb_remove_extern_c,
         nanopb_rename_delete,
-        nanopb_use_module_import
+        nanopb_use_module_import,
+        make_use_absolute_import(nanopb_out, self.args)
     )
 
   def __run_generator(self, out_dir):
@@ -163,7 +169,6 @@ def run_protoc(args, cmd):
     args: The command-line args (including pythonpath)
     cmd: The command to run expressed as a list of strings
   """
-
   kwargs = {}
   if args.pythonpath:
     env = os.environ.copy()
@@ -174,7 +179,8 @@ def run_protoc(args, cmd):
     kwargs['env'] = env
 
   try:
-    print(subprocess.check_output(cmd, stderr=subprocess.STDOUT, **kwargs))
+    outputString = subprocess.check_output(cmd, stderr=subprocess.STDOUT, **kwargs)
+    print(outputString.decode("utf-8"))
   except subprocess.CalledProcessError as error:
     print('command failed: ', ' '.join(cmd), '\nerror: ', error.output)
 
@@ -202,7 +208,11 @@ def post_process_files(filenames, *processors):
       lines = fd.readlines()
 
     for processor in processors:
-      lines = processor(lines)
+      sig = signature(processor)
+      if len(sig.parameters) == 1:
+        lines = processor(lines)
+      else:
+        lines = processor(lines, filename)
 
     write_file(filename, lines)
 
@@ -215,6 +225,8 @@ def write_file(filename, lines):
 
 def add_copyright(lines):
   """Adds a copyright notice to the lines."""
+  if COPYRIGHT_NOTICE in lines:
+    return lines
   result = [COPYRIGHT_NOTICE, '\n']
   result.extend(lines)
   return result
@@ -265,6 +277,25 @@ def nanopb_use_module_import(lines):
   """Changes #include <pb.h> to include <nanopb/pb.h>""" # Don't let Copybara alter these lines.
   return [line.replace('#include <pb.h>', '{}include <nanopb/pb.h>'.format("#")) for line in lines]
 
+def make_use_absolute_import(nanopb_out, args):
+  import_file = collect_files(nanopb_out, '.nanopb.h')[0]
+
+  def nanopb_use_absolute_import(lines, filename):
+    """Makes repo-relative imports
+
+       #include "crashlytics.nanopb.h" =>
+       #include "Crashlytics/Protogen/nanopb/crashlytics.nanopb.h"
+
+       This only applies to .nanopb.c files because it causes errors if
+       .nanopb.h files import other .nanopb.h files with full relative paths.
+    """
+    if ".h" in filename:
+      return lines
+    include_prefix = args.include_prefix[0]
+    header = os.path.basename(import_file)
+    return [line.replace('#include "{0}"'.format(header), '#include "{0}{1}"'.format(include_prefix, header)) for line in lines]
+
+  return nanopb_use_absolute_import
 
 def strip_trailing_whitespace(lines):
   """Removes trailing whitespace from the given lines."""