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>
This commit is contained in:
ExPikaPaka
2026-07-28 12:53:05 +02:00
parent fae4b1241b
commit 2f67e46047
16 changed files with 446 additions and 188 deletions

View File

@@ -10,11 +10,10 @@ Usage:
protoc --proto_path=src/PrintConfigs --descriptor_set_out=config.desc \
--include_imports src/PrintConfigs/*.proto
# Step 2: Generate Python bindings (one-time, or when config_metadata.proto changes)
protoc --proto_path=src/PrintConfigs --python_out=tools/ config_metadata.proto
# Step 2: Run codegen
python tools/config_codegen.py config.desc src/slic3r/GUI/generated/
# Step 3: Run codegen
python tools/config_codegen.py config.desc codegen/generated/
(tools/run_codegen.py does both, and resolves protoc for you)
Outputs:
- PrintConfigDef_generated.cpp (init_fff_params body)
@@ -29,20 +28,22 @@ import re
import argparse
from pathlib import Path
# Add tools/ to path so we can import generated config_metadata_pb2
# Add tools/ to path so we can import the sibling helper modules
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
try:
from google.protobuf import descriptor_pb2
# Import the generated bindings - this registers extensions globally
import config_metadata_pb2 as meta_pb2
from config_metadata import load_descriptor_set
except ImportError as e:
print(f"ERROR: {e}")
print("Ensure google-protobuf is installed: pip install protobuf")
print("And that config_metadata_pb2.py exists in tools/")
print("Generate it with: protoc --proto_path=src/PrintConfigs --python_out=tools/ config_metadata.proto")
print("Ensure protobuf is installed: pip install protobuf")
print("Or just run the pipeline, which bootstraps it: python tools/run_codegen.py")
sys.exit(1)
# The orca.* option extensions and enum constants, bound by main() from the
# descriptor set (see config_metadata.py for why they aren't imported).
meta_pb2 = None
# Proto FieldDescriptorProto.Type enum values
TYPE_DOUBLE = 1
@@ -179,9 +180,8 @@ def parse_field_options(field_desc_proto):
Re-parse FieldOptions from a FieldDescriptorProto with extensions registered.
This is needed because the FileDescriptorSet parser doesn't know about our
custom extensions, so they end up as unknown fields. Re-parsing with the
extensions registered (via config_metadata_pb2 import) resolves them.
extensions registered (see config_metadata.load_descriptor_set) resolves them.
"""
from google.protobuf import descriptor_pb2
opts = field_desc_proto.options
if not opts.ByteSize():
return descriptor_pb2.FieldOptions()
@@ -981,11 +981,8 @@ def main():
print(f"ERROR: Descriptor file not found: {desc_path}")
sys.exit(1)
with open(desc_path, 'rb') as f:
raw = f.read()
file_descriptor_set = descriptor_pb2.FileDescriptorSet()
file_descriptor_set.ParseFromString(raw)
global meta_pb2
file_descriptor_set, meta_pb2 = load_descriptor_set(desc_path)
print(f"Loaded {len(file_descriptor_set.file)} proto files")
for fd in file_descriptor_set.file: