mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-08-04 16:52:29 +00:00
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>
107 lines
3.4 KiB
Python
107 lines
3.4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Convenience script: runs the codegen pipeline.
|
|
|
|
1. Compile .proto -> binary descriptor set (protoc)
|
|
2. Generate C++ from descriptors (config_codegen.py)
|
|
3. Validate output against original
|
|
|
|
The toolchain (protoc, protobuf, pyyaml) is resolved by codegen_toolchain.py, so
|
|
this script is the single entry point every build script and CI job calls -- no
|
|
`pip install` lines needed around it.
|
|
|
|
Usage:
|
|
python tools/run_codegen.py # full pipeline
|
|
python tools/run_codegen.py --validate-only # just validate
|
|
"""
|
|
|
|
import argparse
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
import codegen_toolchain # noqa: E402
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
PROTO_DIR = ROOT / "src" / "PrintConfigs"
|
|
CODEGEN_OUT = ROOT / "src" / "slic3r" / "GUI" / "generated"
|
|
DESC_FILE = ROOT / "config.desc"
|
|
LAYOUT_YAML = PROTO_DIR / "layout.yaml"
|
|
|
|
|
|
def run(cmd, **kwargs):
|
|
print(f" $ {' '.join(str(c) for c in cmd)}")
|
|
result = subprocess.run(cmd, **kwargs)
|
|
if result.returncode != 0:
|
|
print(f" FAILED (exit code {result.returncode})")
|
|
return False
|
|
return True
|
|
|
|
|
|
def step_compile():
|
|
print("\n=== Step 1: Compile .proto -> descriptor set ===")
|
|
proto_files = [f for f in PROTO_DIR.glob("*.proto") if not f.name.endswith("_gen.proto") and f.name != "config_metadata.proto"]
|
|
if not proto_files:
|
|
print(" ERROR: No .proto files found")
|
|
return False
|
|
|
|
protoc = codegen_toolchain.find_protoc()
|
|
if protoc is None:
|
|
return False
|
|
|
|
return run(protoc + [
|
|
f"--proto_path={PROTO_DIR}",
|
|
f"--descriptor_set_out={DESC_FILE}",
|
|
"--include_imports",
|
|
] + [str(f) for f in proto_files])
|
|
|
|
|
|
def step_generate():
|
|
print("\n=== Step 2: Generate C++ from descriptors + layout.yaml ===")
|
|
return run([sys.executable, str(ROOT / "tools" / "config_codegen.py"),
|
|
str(DESC_FILE), str(CODEGEN_OUT)])
|
|
|
|
|
|
def step_lint():
|
|
print("\n=== Lint: proto sanity checks ===")
|
|
return run([sys.executable, str(ROOT / "tools" / "config_codegen.py"),
|
|
str(DESC_FILE), str(CODEGEN_OUT), "--lint-only"])
|
|
|
|
|
|
def step_validate():
|
|
print("\n=== Step 3: Validate ===")
|
|
return run([sys.executable, str(ROOT / "tools" / "validate_codegen.py")])
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Run OrcaSlicer config codegen pipeline")
|
|
parser.add_argument("--validate-only", action="store_true",
|
|
help="Only run validation")
|
|
parser.add_argument("--no-validate", action="store_true",
|
|
help="Skip validation step (used by cmake build)")
|
|
args = parser.parse_args()
|
|
|
|
# Re-execs into a virtualenv with protobuf/pyyaml if this interpreter lacks them.
|
|
codegen_toolchain.ensure_python_runtime()
|
|
|
|
if args.validate_only:
|
|
# Compile + lint the protos, then check the generated files against PrintConfig.cpp.
|
|
sys.exit(0 if (step_compile() and step_lint() and step_validate()) else 1)
|
|
|
|
for name, fn in [("Compile", step_compile), ("Generate", step_generate)]:
|
|
if not fn():
|
|
print(f"\n*** Pipeline FAILED at: {name} ***")
|
|
sys.exit(1)
|
|
|
|
if not args.no_validate:
|
|
if not step_validate():
|
|
print("\n*** Validate FAILED (run with --no-validate to skip) ***")
|
|
sys.exit(1)
|
|
|
|
print("\n=== Pipeline completed successfully ===")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|