commit b757d6e8d683d70ff680596447e8497f7ea46975 Author: stroblme Date: Mon Aug 10 11:58:34 2026 +0200 Scaffold the n3xd-ocp binding repo Placeholder for the hand-written nanobind bindings over OCCT (roadmap Phase 10 in the app repo). Carries the gitignore for a scikit-build-core/CMake extension plus the OCCT build trees, and keeps .secrets — the Gitea publish PAT — out of history. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9f4ee1c --- /dev/null +++ b/.gitignore @@ -0,0 +1,36 @@ +# Credentials (the Gitea publish PAT lives here) +.secrets + +# Python +__pycache__/ +*.py[cod] +.venv/ +venv/ +*.egg-info/ +.pytest_cache/ +.ruff_cache/ + +# Build output — scikit-build-core drives CMake into these +build/ +_skbuild/ +dist/ +wheelhouse/ +CMakeUserPresets.json + +# Compiled extension / generated stubs land in the package tree +*.so +*.dylib +*.pyd +python/OCP/*.pyi + +# Vendored or locally built OCCT (never committed; it comes from the +# builder image, and a kernel tree would dwarf this repo) +occt/build/ +occt/install/ +third_party/ + +# Editor / OS +.vscode/* +!.vscode/extensions.json +.idea/ +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..70276d2 --- /dev/null +++ b/README.md @@ -0,0 +1,47 @@ +# n3xd-ocp + +Hand-written [nanobind](https://github.com/wjakob/nanobind) bindings for the +OpenCASCADE (OCCT) geometry kernel, covering exactly the surface the N3XD CAD +backend uses — roughly 140 symbols across 48 `OCP.*` modules, not all of OCCT. + +The package installs as a top-level `OCP`, so it is a drop-in replacement for +`cadquery-ocp-novtk` and the app's 437 import sites stay untouched. + +Status: **not started.** The plan lives in the app repo at +`docs-private/reference/roadmap.md` (Phase 10), with the binding-layer +background in `docs-private/architecture/geometry-kernel.md`. + +## Why + +`cadquery-ocp` lags OCCT (it wraps 7.9.3; OCCT 8.0 shipped 2026-05), builds +Windows and macOS wheels we never use, and until recently forced a 638 MB VTK +dependency into the image. Binding *call* overhead is not a bottleneck — the +CAD hotspots live inside the C++ kernel — so this exists for version velocity, +footprint, and two defects that a binding we control prevents by construction: + +- OCCT sub-shapes are returned **by value**, so a wrapper can never alias a + `TShape` whose owner has died (this segfaulted a process-global face memo). +- Executing constructors (the two-argument `BRepAlgoAPI_*` forms) are **not + bound**, so the double-execution footgun is unrepresentable. + +It also releases the GIL around kernel calls and ships type stubs, neither of +which upstream does. + +## Build + +OCCT is compiled once into a builder image and reused; it is never built on the +production host (4 cores, and a kernel build is multi-hour). Wheels are built +here on a dev box and published to the Gitea package registry: + +```bash +uv publish --publish-url https://git.stroblme.de/api/packages/N3XD/pypi dist/*.whl +``` + +Credentials go in `.secrets` (gitignored) as `UV_PUBLISH_USERNAME` / +`UV_PUBLISH_PASSWORD`. Consumers read anonymously — the package is public — via +`https://git.stroblme.de/api/packages/N3XD/pypi/simple/`. + +Versions are `.N`, so the kernel a wheel wraps is readable from +its version alone. The registry refuses to republish a version; iteration +builds therefore carry a `.devN` suffix and are the only ones the registry's +cleanup rule collects.