Import of the watch repository from Pebble

This commit is contained in:
Matthieu Jeanson 2024-12-12 16:43:03 -08:00 committed by Katharine Berry
commit 3b92768480
10334 changed files with 2564465 additions and 0 deletions

2384
third_party/nanopb/generator/nanopb_generator.py vendored Executable file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,13 @@
#!/usr/bin/env python2
# This file is a wrapper around nanopb_generator.py in case you want to run
# it with Python 2 instead of default Python 3. This only exists for backwards
# compatibility, do not use for new projects.
from nanopb_generator import *
if __name__ == '__main__':
# Check if we are running as a plugin under protoc
if 'protoc-gen-' in sys.argv[0] or '--protoc-plugin' in sys.argv:
main_plugin()
else:
main_cli()

View file

@ -0,0 +1,154 @@
import os
import hashlib
import pathlib
from platformio import fs
Import("env")
try:
import protobuf
except ImportError:
env.Execute(
env.VerboseAction(
# We need to speicify protobuf version. In other case got next (on Ubuntu 20.04):
# Requirement already satisfied: protobuf in /usr/lib/python3/dist-packages (3.6.1)
'$PYTHONEXE -m pip install "protobuf>=3.19.1"',
"Installing Protocol Buffers dependencies",
)
)
try:
import grpc_tools.protoc
except ImportError:
env.Execute(
env.VerboseAction(
'$PYTHONEXE -m pip install "grpcio-tools>=1.43.0"',
"Installing GRPC dependencies",
)
)
nanopb_root = os.path.join(os.getcwd(), '..')
project_dir = env.subst("$PROJECT_DIR")
build_dir = env.subst("$BUILD_DIR")
generated_src_dir = os.path.join(build_dir, 'nanopb', 'generated-src')
generated_build_dir = os.path.join(build_dir, 'nanopb', 'generated-build')
md5_dir = os.path.join(build_dir, 'nanopb', 'md5')
nanopb_protos = env.GetProjectOption("custom_nanopb_protos", "")
nanopb_plugin_options = env.GetProjectOption("custom_nanopb_options", "")
if not nanopb_protos:
print("[nanopb] No generation needed.")
else:
if isinstance(nanopb_plugin_options, (list, tuple)):
nanopb_plugin_options = " ".join(nanopb_plugin_options)
nanopb_plugin_options = nanopb_plugin_options.split()
protos_files = fs.match_src_files(project_dir, nanopb_protos)
if not len(protos_files):
print("[nanopb] ERROR: No files matched pattern:")
print(f"custom_nanopb_protos: {nanopb_protos}")
exit(1)
protoc_generator = os.path.join(nanopb_root, 'generator', 'protoc')
nanopb_options = ""
nanopb_options += f" --nanopb_out={generated_src_dir}"
for opt in nanopb_plugin_options:
nanopb_options += (" --nanopb_opt=" + opt)
try:
os.makedirs(generated_src_dir)
except FileExistsError:
pass
try:
os.makedirs(md5_dir)
except FileExistsError:
pass
# Collect include dirs based on
proto_include_dirs = set()
for proto_file in protos_files:
proto_file_abs = os.path.join(project_dir, proto_file)
proto_dir = os.path.dirname(proto_file_abs)
proto_include_dirs.add(proto_dir)
for proto_include_dir in proto_include_dirs:
nanopb_options += (" --proto_path=" + proto_include_dir)
nanopb_options += (" --nanopb_opt=-I" + proto_include_dir)
for proto_file in protos_files:
proto_file_abs = os.path.join(project_dir, proto_file)
proto_file_path_abs = os.path.dirname(proto_file_abs)
proto_file_basename = os.path.basename(proto_file_abs)
proto_file_without_ext = os.path.splitext(proto_file_basename)[0]
proto_file_md5_abs = os.path.join(md5_dir, proto_file_basename + '.md5')
proto_file_current_md5 = hashlib.md5(pathlib.Path(proto_file_abs).read_bytes()).hexdigest()
options_file = proto_file_without_ext + ".options"
options_file_abs = os.path.join(proto_file_path_abs, options_file)
options_file_md5_abs = None
options_file_current_md5 = None
if pathlib.Path(options_file_abs).exists():
options_file_md5_abs = os.path.join(md5_dir, options_file + '.md5')
options_file_current_md5 = hashlib.md5(pathlib.Path(options_file_abs).read_bytes()).hexdigest()
else:
options_file = None
header_file = proto_file_without_ext + ".pb.h"
source_file = proto_file_without_ext + ".pb.c"
header_file_abs = os.path.join(generated_src_dir, source_file)
source_file_abs = os.path.join(generated_src_dir, header_file)
need_generate = False
# Check proto file md5
try:
last_md5 = pathlib.Path(proto_file_md5_abs).read_text()
if last_md5 != proto_file_current_md5:
need_generate = True
except FileNotFoundError:
need_generate = True
if options_file:
# Check options file md5
try:
last_md5 = pathlib.Path(options_file_md5_abs).read_text()
if last_md5 != options_file_current_md5:
need_generate = True
except FileNotFoundError:
need_generate = True
options_info = f"{options_file}" if options_file else "no options"
if not need_generate:
print(f"[nanopb] Skipping '{proto_file}' ({options_info})")
else:
print(f"[nanopb] Processing '{proto_file}' ({options_info})")
cmd = protoc_generator + " " + nanopb_options + " " + proto_file_basename
result = env.Execute(cmd)
if result != 0:
print(f"[nanopb] ERROR: ({result}) processing cmd: '{cmd}'")
exit(1)
pathlib.Path(proto_file_md5_abs).write_text(proto_file_current_md5)
if options_file:
pathlib.Path(options_file_md5_abs).write_text(options_file_current_md5)
#
# Add generated includes and sources to build environment
#
env.Append(CPPPATH=[generated_src_dir])
# Fix for ESP32 ESP-IDF https://github.com/nanopb/nanopb/issues/734#issuecomment-1001544447
global_env = DefaultEnvironment()
already_called_env_name = "_PROTOBUF_GENERATOR_ALREADY_CALLED_" + env['PIOENV'].replace("-", "_")
if not global_env.get(already_called_env_name, False):
env.BuildSources(generated_build_dir, generated_src_dir)
global_env[already_called_env_name] = True

View file

@ -0,0 +1,10 @@
PROTOC?=../protoc
all: nanopb_pb2.py
%_pb2.py: %.proto
$(PROTOC) --python_out=. $<
.PHONY: clean
clean:
rm nanopb_pb2.py

View file

@ -0,0 +1,50 @@
'''This file automatically rebuilds the proto definitions for Python.'''
from __future__ import absolute_import
import os.path
import sys
import pkg_resources
from ._utils import has_grpcio_protoc, invoke_protoc, print_versions
dirname = os.path.dirname(__file__)
protosrc = os.path.join(dirname, "nanopb.proto")
protodst = os.path.join(dirname, "nanopb_pb2.py")
rebuild = False
if os.path.isfile(protosrc):
src_date = os.path.getmtime(protosrc)
if not os.path.isfile(protodst) or os.path.getmtime(protodst) < src_date:
rebuild = True
if not rebuild:
try:
from . import nanopb_pb2
except AttributeError as e:
rebuild = True
sys.stderr.write("Failed to import nanopb_pb2.py: " + str(e) + "\n"
"Will automatically attempt to rebuild this.\n"
"Verify that python-protobuf and protoc versions match.\n")
print_versions()
if rebuild:
cmd = [
"protoc",
"--python_out={}".format(dirname),
protosrc,
"-I={}".format(dirname),
]
if has_grpcio_protoc():
# grpcio-tools has an extra CLI argument
# from grpc.tools.protoc __main__ invocation.
_builtin_proto_include = pkg_resources.resource_filename('grpc_tools', '_proto')
cmd.append("-I={}".format(_builtin_proto_include))
try:
invoke_protoc(argv=cmd)
except:
sys.stderr.write("Failed to build nanopb_pb2.py: " + ' '.join(cmd) + "\n")
raise

View file

@ -0,0 +1,66 @@
import sys
import subprocess
import os.path
def has_grpcio_protoc():
# type: () -> bool
""" checks if grpcio-tools protoc is installed"""
try:
import grpc_tools.protoc
except ImportError:
return False
return True
def invoke_protoc(argv):
# type: (list) -> typing.Any
"""
Invoke protoc.
This routine will use grpcio-provided protoc if it exists,
using system-installed protoc as a fallback.
Args:
argv: protoc CLI invocation, first item must be 'protoc'
"""
# Add current directory to include path if nothing else is specified
if not [x for x in argv if x.startswith('-I')]:
argv.append("-I.")
# Add default protoc include paths
nanopb_include = os.path.dirname(os.path.abspath(__file__))
argv.append('-I' + nanopb_include)
if has_grpcio_protoc():
import grpc_tools.protoc as protoc
import pkg_resources
proto_include = pkg_resources.resource_filename('grpc_tools', '_proto')
argv.append('-I' + proto_include)
return protoc.main(argv)
else:
return subprocess.call(argv)
def print_versions():
try:
if has_grpcio_protoc():
import grpc_tools.protoc
sys.stderr.write("Using grpcio-tools protoc from " + grpc_tools.protoc.__file__ + "\n")
else:
sys.stderr.write("Using protoc from system path\n")
invoke_protoc(['protoc', '--version'])
except Exception as e:
sys.stderr.write("Failed to determine protoc version: " + str(e) + "\n")
try:
import google.protobuf
sys.stderr.write("Using python-protobuf from " + google.protobuf.__file__ + "\n")
sys.stderr.write("Python-protobuf version: " + google.protobuf.__version__ + "\n")
except Exception as e:
sys.stderr.write("Failed to determine python-protobuf version: " + str(e) + "\n")
if __name__ == '__main__':
print_versions()

View file

@ -0,0 +1,185 @@
// Custom options for defining:
// - Maximum size of string/bytes
// - Maximum number of elements in array
//
// These are used by nanopb to generate statically allocable structures
// for memory-limited environments.
syntax = "proto2";
import "google/protobuf/descriptor.proto";
option java_package = "fi.kapsi.koti.jpa.nanopb";
enum FieldType {
FT_DEFAULT = 0; // Automatically decide field type, generate static field if possible.
FT_CALLBACK = 1; // Always generate a callback field.
FT_POINTER = 4; // Always generate a dynamically allocated field.
FT_STATIC = 2; // Generate a static field or raise an exception if not possible.
FT_IGNORE = 3; // Ignore the field completely.
FT_INLINE = 5; // Legacy option, use the separate 'fixed_length' option instead
}
enum IntSize {
IS_DEFAULT = 0; // Default, 32/64bit based on type in .proto
IS_8 = 8;
IS_16 = 16;
IS_32 = 32;
IS_64 = 64;
}
enum TypenameMangling {
M_NONE = 0; // Default, no typename mangling
M_STRIP_PACKAGE = 1; // Strip current package name
M_FLATTEN = 2; // Only use last path component
M_PACKAGE_INITIALS = 3; // Replace the package name by the initials
}
enum DescriptorSize {
DS_AUTO = 0; // Select minimal size based on field type
DS_1 = 1; // 1 word; up to 15 byte fields, no arrays
DS_2 = 2; // 2 words; up to 4095 byte fields, 4095 entry arrays
DS_4 = 4; // 4 words; up to 2^32-1 byte fields, 2^16-1 entry arrays
DS_8 = 8; // 8 words; up to 2^32-1 entry arrays
}
// This is the inner options message, which basically defines options for
// a field. When it is used in message or file scope, it applies to all
// fields.
message NanoPBOptions {
// Allocated size for 'bytes' and 'string' fields.
// For string fields, this should include the space for null terminator.
optional int32 max_size = 1;
// Maximum length for 'string' fields. Setting this is equivalent
// to setting max_size to a value of length+1.
optional int32 max_length = 14;
// Allocated number of entries in arrays ('repeated' fields)
optional int32 max_count = 2;
// Size of integer fields. Can save some memory if you don't need
// full 32 bits for the value.
optional IntSize int_size = 7 [default = IS_DEFAULT];
// Force type of field (callback or static allocation)
optional FieldType type = 3 [default = FT_DEFAULT];
// Use long names for enums, i.e. EnumName_EnumValue.
optional bool long_names = 4 [default = true];
// Add 'packed' attribute to generated structs.
// Note: this cannot be used on CPUs that break on unaligned
// accesses to variables.
optional bool packed_struct = 5 [default = false];
// Add 'packed' attribute to generated enums.
optional bool packed_enum = 10 [default = false];
// Skip this message
optional bool skip_message = 6 [default = false];
// Generate oneof fields as normal optional fields instead of union.
optional bool no_unions = 8 [default = false];
// integer type tag for a message
optional uint32 msgid = 9;
// decode oneof as anonymous union
optional bool anonymous_oneof = 11 [default = false];
// Proto3 singular field does not generate a "has_" flag
optional bool proto3 = 12 [default = false];
// Force proto3 messages to have no "has_" flag.
// This was default behavior until nanopb-0.4.0.
optional bool proto3_singular_msgs = 21 [default = false];
// Generate an enum->string mapping function (can take up lots of space).
optional bool enum_to_string = 13 [default = false];
// Generate bytes arrays with fixed length
optional bool fixed_length = 15 [default = false];
// Generate repeated field with fixed count
optional bool fixed_count = 16 [default = false];
// Generate message-level callback that is called before decoding submessages.
// This can be used to set callback fields for submsgs inside oneofs.
optional bool submsg_callback = 22 [default = false];
// Shorten or remove package names from type names.
// This option applies only on the file level.
optional TypenameMangling mangle_names = 17 [default = M_NONE];
// Data type for storage associated with callback fields.
optional string callback_datatype = 18 [default = "pb_callback_t"];
// Callback function used for encoding and decoding.
// Prior to nanopb-0.4.0, the callback was specified in per-field pb_callback_t
// structure. This is still supported, but does not work inside e.g. oneof or pointer
// fields. Instead, a new method allows specifying a per-message callback that
// will be called for all callback fields in a message type.
optional string callback_function = 19 [default = "pb_default_field_callback"];
// Select the size of field descriptors. This option has to be defined
// for the whole message, not per-field. Usually automatic selection is
// ok, but if it results in compilation errors you can increase the field
// size here.
optional DescriptorSize descriptorsize = 20 [default = DS_AUTO];
// Set default value for has_ fields.
optional bool default_has = 23 [default = false];
// Extra files to include in generated `.pb.h`
repeated string include = 24;
// Automatic includes to exclude from generated `.pb.h`
// Same as nanopb_generator.py command line flag -x.
repeated string exclude = 26;
// Package name that applies only for nanopb.
optional string package = 25;
// Override type of the field in generated C code. Only to be used with related field types
optional google.protobuf.FieldDescriptorProto.Type type_override = 27;
// Due to historical reasons, nanopb orders fields in structs by their tag number
// instead of the order in .proto. Set this to false to keep the .proto order.
// The default value will probably change to false in nanopb-0.5.0.
optional bool sort_by_tag = 28 [default = true];
// Set the FT_DEFAULT field conversion strategy.
// A field that can become a static member of a c struct (e.g. int, bool, etc)
// will be a a static field.
// Fields with dynamic length are converted to either a pointer or a callback.
optional FieldType fallback_type = 29 [default = FT_CALLBACK];
}
// Extensions to protoc 'Descriptor' type in order to define options
// inside a .proto file.
//
// Protocol Buffers extension number registry
// --------------------------------
// Project: Nanopb
// Contact: Petteri Aimonen <jpa@kapsi.fi>
// Web site: http://kapsi.fi/~jpa/nanopb
// Extensions: 1010 (all types)
// --------------------------------
extend google.protobuf.FileOptions {
optional NanoPBOptions nanopb_fileopt = 1010;
}
extend google.protobuf.MessageOptions {
optional NanoPBOptions nanopb_msgopt = 1010;
}
extend google.protobuf.EnumOptions {
optional NanoPBOptions nanopb_enumopt = 1010;
}
extend google.protobuf.FieldOptions {
optional NanoPBOptions nanopb = 1010;
}

39
third_party/nanopb/generator/protoc vendored Executable file
View file

@ -0,0 +1,39 @@
#!/usr/bin/env python3
# This file acts as a drop-in replacement of binary protoc.exe.
# It will use either Python-based protoc from grpcio-tools package,
# or if it is not available, protoc.exe from path if found.
import sys
import os
import os.path
from nanopb_generator import invoke_protoc
if __name__ == '__main__':
# Get path of the directory where this script is stored.
if getattr(sys, 'frozen', False):
mypath = os.path.dirname(sys.executable) # For pyInstaller
else:
mypath = os.path.dirname(__file__)
# Avoid recursive calls to self
env_paths = os.environ["PATH"].split(os.pathsep)
if mypath in env_paths:
env_paths.remove(mypath)
os.environ["PATH"] = os.pathsep.join(env_paths)
# Add argument for finding the nanopb generator when using --nanopb_out=
# argument to protoc.
if os.path.isfile(os.path.join(mypath, "protoc-gen-nanopb.exe")):
protoc_gen_nanopb = os.path.join(mypath, "protoc-gen-nanopb.exe")
elif os.name == 'nt':
protoc_gen_nanopb = os.path.join(mypath, "protoc-gen-nanopb.bat")
else:
protoc_gen_nanopb = os.path.join(mypath, "protoc-gen-nanopb")
args = sys.argv[1:]
if os.path.isfile(protoc_gen_nanopb):
args = ['--plugin=protoc-gen-nanopb=%s' % protoc_gen_nanopb] + args
status = invoke_protoc(['protoc'] + args)
sys.exit(status)

View file

@ -0,0 +1,13 @@
#!/bin/sh
# This file is used to invoke nanopb_generator.py as a plugin
# to protoc on Linux and other *nix-style systems.
# Use it like this:
# protoc --plugin=protoc-gen-nanopb=..../protoc-gen-nanopb --nanopb_out=dir foo.proto
#
# Note that if you use the binary package of nanopb, the protoc
# path is already set up properly and there is no need to give
# --plugin= on the command line.
MYPATH=$(dirname "$0")
exec "$MYPATH/nanopb_generator.py" --protoc-plugin

View file

@ -0,0 +1,16 @@
#!/bin/sh
# This file is used to invoke nanopb_generator.py2 as a plugin
# to protoc on Linux and other *nix-style systems.
#
# The difference from protoc-gen-nanopb is that this executes with Python 2.
#
# Use it like this:
# protoc --plugin=protoc-gen-nanopb=..../protoc-gen-nanopb-py2 --nanopb_out=dir foo.proto
#
# Note that if you use the binary package of nanopb, the protoc
# path is already set up properly and there is no need to give
# --plugin= on the command line.
MYPATH=$(dirname "$0")
exec "$MYPATH/nanopb_generator.py2" --protoc-plugin

View file

@ -0,0 +1,12 @@
@echo off
:: This file is used to invoke nanopb_generator.py as a plugin
:: to protoc on Windows.
:: Use it like this:
:: protoc --plugin=protoc-gen-nanopb=..../protoc-gen-nanopb.bat --nanopb_out=dir foo.proto
::
:: Note that if you use the binary package of nanopb, the protoc
:: path is already set up properly and there is no need to give
:: --plugin= on the command line.
set mydir=%~dp0
python "%mydir%\nanopb_generator.py" --protoc-plugin %*

View file

@ -0,0 +1,9 @@
@echo off
:: This file acts as a drop-in replacement of binary protoc.exe.
:: It will use either Python-based protoc from grpcio-tools package,
:: or if it is not available, protoc.exe from path if found.
setLocal enableDelayedExpansion
set mydir=%~dp0
python "%mydir%\protoc" %*
exit /b %ERRORLEVEL%