Files
OrcaSlicer/tools/config_metadata.py
ExPikaPaka 2f67e46047 fix(codegen): drop grpcio-tools, stop committing generated code
The codegen only ever needed a protoc binary, but every entry point installed
grpcio-tools to get one. That drags in the grpcio C extension, which has no
Windows/ARM64 wheel and falls back to building from source there, so the ARM64
job died with "Failed building wheel for grpcio" -> "protoc not found".

tools/codegen_toolchain.py resolves the toolchain instead: protoc from $PROTOC,
PATH, a cache, grpc_tools when already installed, or a pinned checksum-verified
protoc release unpacked into .codegen-tools/; protobuf and pyyaml from the
calling interpreter or a cached virtualenv it re-execs into (distro Pythons
refuse `pip install` under PEP 668). All four build scripts and all three CI
jobs are now just `python tools/run_codegen.py`, with no pip lines around it.

tools/config_metadata_pb2.py was the one generated file checked into git. The
orca.* option extensions are now read out of the descriptor set, which already
carries config_metadata.proto via --include_imports, so nothing is generated
into the tree -- and the protobuf>=6.33.5,<7 CI pin goes away with it, since it
only existed to satisfy gencode's hard ValidateProtobufRuntimeVersion check.
Generated C++ verified byte-identical under upb and the pure-Python protobuf
runtime (what win/arm64 installs), and under both grpc_tools' and standalone
protoc.

Also fixed:
- build_release_macos.sh still passed -DPython3_EXECUTABLE=<codegen venv>,
  pointing the bundled *embed* interpreter at the codegen environment -- the
  same confusion fae4b124 fixed on the CMake side.
- Tab.cpp #includes TabLayout_generated.cpp but had no dependency on
  codegen_config, so an incremental build after a .proto edit could compile it
  while the file was being rewritten. libslic3r already had this guard.
- ConfigCodegen.cmake now probes with `codegen_toolchain.py --check` (which
  never downloads or installs), prefers a host interpreter over the embed one,
  and lets a fresh clone generate at configure time instead of erroring out.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 12:53:05 +02:00

68 lines
2.5 KiB
Python

#!/usr/bin/env python3
"""
Access to the orca.* option extensions declared in config_metadata.proto.
The extensions are read straight out of the compiled descriptor set: protoc runs
with --include_imports, so config_metadata.proto travels inside the .desc file
that the codegen already consumes. Registering it in the default descriptor pool
before the descriptor set is parsed is what makes the custom options resolve
instead of landing in unknown fields.
Doing it this way keeps generated code out of git. The alternative -- a checked-in
config_metadata_pb2.py -- also pinned the protobuf runtime to whichever protoc
produced it, because gencode embeds a hard ValidateProtobufRuntimeVersion() check.
"""
from google.protobuf import descriptor_pb2, descriptor_pool
METADATA_PROTO = "config_metadata.proto"
class Metadata:
"""
Stand-in for the generated config_metadata_pb2 module.
Exposes each orca extension as an attribute holding its FieldDescriptor
(usable as `options.Extensions[meta.label]`) and each enum value as an int
constant (`meta.MODE_SIMPLE`, `meta.STEP_SLICE`, ...), matching how the
generated module was used.
"""
def __init__(self, file_descriptor):
for name, extension in file_descriptor.extensions_by_name.items():
setattr(self, name, extension)
for enum in file_descriptor.enum_types_by_name.values():
for value in enum.values:
setattr(self, value.name, value.number)
def load_descriptor_set(path):
"""
Read a protoc descriptor set and return (FileDescriptorSet, Metadata).
The file is parsed twice on purpose: the first pass only locates the embedded
config_metadata.proto so its extensions can be registered, the second one
parses with those extensions known.
"""
with open(path, 'rb') as f:
raw = f.read()
probe = descriptor_pb2.FileDescriptorSet()
probe.ParseFromString(raw)
metadata_file = next((f for f in probe.file if f.name == METADATA_PROTO), None)
if metadata_file is None:
raise RuntimeError(
f"{path} does not contain {METADATA_PROTO} -- protoc must be run with "
"--include_imports")
pool = descriptor_pool.Default()
try:
file_descriptor = pool.FindFileByName(METADATA_PROTO)
except KeyError:
pool.Add(metadata_file)
file_descriptor = pool.FindFileByName(METADATA_PROTO)
descriptor_set = descriptor_pb2.FileDescriptorSet()
descriptor_set.ParseFromString(raw)
return descriptor_set, Metadata(file_descriptor)