feat: follow stable releases and parameterise the native build - #3
Conversation
The manifest moves from `ref: master` to release tracking on `stable`, recording v1.0 as what is vendored. `master` was a hazard sitting there unarmed: had the tracked CD been active it would have fetched the 1.2 header and left the 1.0 binaries in place. meshopt-cmake.yml becomes callable with a `ref`, instead of carrying v1.0 in a hardcoded line that had already drifted from the manifest and the README. Each platform now stages its library directly into the runtimes layout the package expects, so the CD can unpack every artifact over the project directory with no mapping table anywhere. It also records the exported symbols per platform. A rebuild is never byte-identical -- different compiler, different date -- so comparing bytes proves nothing; comparing the exported symbol set is what shows the toolchain still produces an equivalent library.
Scraping dumpbin's output reported the DLL's own name and fragments of decorated C++ names as exported symbols, so a comparison that was in fact clean showed two differences per Windows platform. A comparator that cries wolf is worse than none when the thing it guards is a silent runtime break.
Replaces binding-simple-cd, which published whatever was already in the tree without ever looking upstream, and had no schedule at all. Three jobs, because the halves cannot share a runner: the native libraries need a matrix across three operating systems, the generator and packaging need one machine holding the whole tree. `resolve` runs first and alone so exactly one place decides which revision the run is about -- if the header and the binaries each worked it out separately, a release published midway through would leave them on different versions, and that mismatch is the invisible kind. Monthly, in step with the rest of the fleet.
…annot Two faults that hid each other. The output path was a fixed climb of five directories, which is only correct when the generator is published without a runtime identifier. CI and CD pass linux-x64, adding a level, so every automated run wrote its bindings into MeshOptimizerGen/MeshOptimizerGen/Evergine.Bindings.MeshOptimizer/Generated -- a directory no build reads. The checked-in bindings have therefore only ever changed when a human ran the generator locally. That the published v1.0 package works is not evidence against this: it was generated by hand, on Windows, without a runtime identifier, and it was correct for v1.0. Now it searches upward for the project by name, so how deep the build output sits stops being something this file has to know. Parse failures went to Debug.WriteLine, which compiles to nothing in Release, and the process still returned 0. A header the generator could not read produced no output, no message and no error. They now go to stderr with a non-zero exit. Seven of the ten bindings pass a non-empty runtime-identifier, so this pattern is worth checking in the others -- RenderDoc.NET especially, which regenerates on a schedule.
The CppAst generator cannot read meshoptimizer.h on Linux. The libclang shipped in the NuGet package carries no system include paths and none of its own builtin headers, so <assert.h> and <stddef.h> do not resolve and the parse aborts before any binding is produced -- previously in silence, since the diagnostics went to Debug.WriteLine and the process still exited 0. RenderDoc.NET and KTX.NET already generate on Windows for the same reason. This does not constrain the package: the five native libraries are built in their own matrix job, and runtime-identifier only feeds the generator's publish, never the packing -- checked against binding-tracked-cd rather than assumed. CI moves with CD. A CI that validates on a platform the CD does not use is checking a build nobody ships.
…quest Two contracts that a diff of 6,000 generated lines hides. The API gate says which public symbols a change adds or removes; the coherence check says every P/Invoke still resolves in all five shipped libraries. auto-merge stays off. This binding rebuilds five native libraries when it bumps, and that pipeline has run a handful of times -- measure first. README follows the manifest to v1.2.
API gate: breakingThis removes or changes public symbols. Merging is left to a human — a rename is sometimes the right answer, but never an automatic one.
|
API gate: additiveEvery symbol that existed still exists, unchanged. Nothing that compiled before stops compiling.
Enum and constant values are part of the measured surface: a renumbering keeps compiling and sends the wrong number to the driver, so it counts as a removal. |
API gate: additiveEvery symbol that existed still exists, unchanged. Nothing that compiled before stops compiling.
Enum and constant values are part of the measured surface: a renumbering keeps compiling and sends the wrong number to the driver, so it counts as a removal. |
Phases 1 and 2 of moving Meshoptimizer.NET onto tracked stable releases. No version bump yet — this only makes the machinery capable and the manifest truthful.
Verification of the native toolchain (rebuilding v1.0 and comparing exported symbols against the committed binaries) runs before this merges.
🤖 Generated with Claude Code