From 76672637e23291d7789c93aa8afc77cac6014141 Mon Sep 17 00:00:00 2001 From: Miguel249 Date: Mon, 10 Aug 2026 06:52:41 -0500 Subject: [PATCH 1/2] Say what the iOS check proves now, not what it proved before The description of the mobile verification was written when the linker's own evidence was the ceiling: the executable was expected to be stripped, and the symbol half of the check was documented as attempted and normally unable to run. That stopped being true two commits later. The release simulator build keeps its symbol table - 65267 defined symbols - and the check now reads Box3D's own native ones out of it, 415 of them in the run on main. The CHANGELOG matters more than the README here, because [Unreleased] is what becomes the release notes, and shipping it unchanged would have published a claim weaker than what CI actually does. Both now also record why only _b3 names count. An AOT method carries its parameter types in its mangled name, so a plain search for b3 matches managed symbols that are in the binary whether or not the archive survived the link. Co-Authored-By: Claude Opus 5 (1M context) --- CHANGELOG.md | 22 +++++++++++++++++----- README.md | 32 +++++++++++++++++++++----------- 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4982794..ab14853 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,11 +40,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 Both are verified in CI against the packed `.nupkg` rather than the repository: a real Android application is built and its `.apk` opened to confirm `libbox3d.so` is inside it, and a real iOS application is built and - checked for evidence that the package handed Box3D's archive to the linker. - A clean build proves nothing on iOS by itself — a P/Invoke to `__Internal` is - resolved at run time, so an application the archive never reached builds and - launches like a correct one. Neither runs a simulation on a device, and the - platform table in the README says so rather than implying otherwise. + its executable read with `nm` to confirm Box3D's own native symbols are + defined in it — 415 of them, in the run this release was cut from. A clean + build proves nothing on iOS by itself: a P/Invoke to `__Internal` is resolved + at run time, so an application the archive never reached builds and launches + like a correct one. + + Only symbols named `_b3…` are counted as evidence of the link. An AOT-compiled + method carries its parameter types in its mangled name, so `b3BodyId` and + `b3ShapeDef` occur inside managed symbols such as + `_Box3D_NET_Box3D_Body__ctor_Box3D_Native_b3BodyId`, which are in the binary + whether or not the archive survived; counting those would have counted the + wrong thing. They are counted separately instead, because they answer the + other question — whether the trimmer kept Box3D's C# at all — and that + distinction is what tells the two failures apart. + + Neither platform runs a simulation on a device, and the platform table in the + README says so rather than implying otherwise. ### Changed diff --git a/README.md b/README.md index 3a26f54..e69453c 100644 --- a/README.md +++ b/README.md @@ -734,17 +734,27 @@ start an application on a phone, so those two words are the honest ceiling: it for `arm64-v8a`. That covers the failure mode specific to Android: an unresolved runtime asset produces a perfectly valid application that dies on its first physics call. -- **linked** — CI builds a real iOS application against the packed `.nupkg` and - confirms the package handed Box3D's archive to the linker. That is the failure - mode specific to iOS: the library is linked into the application rather than - loaded, and a P/Invoke to `__Internal` is resolved by Mono at run time, so an - application the archive never reached builds and launches exactly like a - correct one and fails on its first physics call. - - The stronger check — Box3D's symbols in the finished executable — is attempted - and normally cannot run, because a release build for iOS is stripped and - defines no symbols at all. Where the binary does keep a symbol table and Box3D - is missing from it, that is a failure rather than a shrug. +- **linked** — CI builds a real iOS application against the packed `.nupkg`, + then reads the executable it produced with `nm` and requires Box3D's own + native symbols to be defined in it. That is the failure mode specific to iOS: + the library is linked into the application rather than loaded, and a P/Invoke + to `__Internal` is resolved by Mono at run time, so an application the archive + never reached builds and launches exactly like a correct one and fails on its + first physics call. + + Only symbols named `_b3…` count, since those can only have come out of + `libbox3d.a`. An AOT-compiled method carries its parameter types in its + mangled name, so `b3BodyId` and `b3ShapeDef` turn up inside managed symbols + like `_Box3D_NET_Box3D_Body__ctor_Box3D_Native_b3BodyId`, which are in the + binary whether or not the archive survived the link. Those are counted too, + separately, because they answer the other question — whether the trimmer kept + Box3D's C# at all — and between them they say which half to go and look at + when the check fails. + + A stripped executable would leave nothing to read, and the check falls back to + the build log's evidence that the linker was handed the archive, reporting + that it did so rather than claiming the stronger result. That has not happened + yet: the release simulator build keeps its symbol table. Neither runs a simulation on a device. If you ship Box3D.NET on a phone, test on a phone. From 915692ae47e4db885819fc459cee7c9b38b3471a Mon Sep 17 00:00:00 2001 From: Miguel249 Date: Mon, 10 Aug 2026 06:53:08 -0500 Subject: [PATCH 2/2] Release 0.4.0 Minor rather than patch: the packages reach Android and iOS, and a platform is a capability. Nothing in the library changed - package validation against 0.3.0 reports no difference in any target framework - so there is no fix to record and no break to warn about. The baseline moves to 0.3.0 in the same commit. It was left at 0.2.0 while 0.3.0 shipped, which is the gap Directory.Build.targets already describes having made once with 0.1.0, so the comment now says when to move it rather than only that it should be moved. The CHANGELOG's link references were two releases behind: [Unreleased] still compared against v0.2.0 and 0.3.0 had no reference at all, so its heading rendered as plain text. Co-Authored-By: Claude Opus 5 (1M context) --- CHANGELOG.md | 12 +++++++++++- Directory.Build.props | 2 +- Directory.Build.targets | 7 +++++-- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab14853..0ff98db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.4.0] - 2026-08-10 + +A reach release. The library itself is unchanged — no type, member or behaviour +differs from 0.3.0, and package validation against it reports no difference — +and what is new is where it runs: the packages now carry Android and iOS +alongside the six desktop runtimes. That is a minor version rather than a patch +because a platform is a capability, and nothing here is a fix. + ### Added - **Android and iOS.** The packages now carry native binaries for @@ -462,6 +470,8 @@ rather than left standing: follow Box3D and are documented rather than corrected. - Single precision only. Box3D's large-world mode changes the ABI and would need a separate package. -[Unreleased]: https://github.com/Miguel249/Box3D.NET/compare/v0.2.0...HEAD +[Unreleased]: https://github.com/Miguel249/Box3D.NET/compare/v0.4.0...HEAD +[0.4.0]: https://github.com/Miguel249/Box3D.NET/compare/v0.3.0...v0.4.0 +[0.3.0]: https://github.com/Miguel249/Box3D.NET/compare/v0.2.0...v0.3.0 [0.2.0]: https://github.com/Miguel249/Box3D.NET/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/Miguel249/Box3D.NET/releases/tag/v0.1.0 diff --git a/Directory.Build.props b/Directory.Build.props index fe02413..3a22a93 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -71,7 +71,7 @@ - 0.3.0 + 0.4.0 Box3D.NET contributors Box3D.NET Box3D.NET diff --git a/Directory.Build.targets b/Directory.Build.targets index 87b0955..42ed680 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -56,10 +56,13 @@ This was still 0.1.0 while 0.3.0 was being prepared, which is a gap rather than extra strictness: comparing against 0.1.0 says nothing about whether a member 0.2.0 added has survived, so anything introduced and then removed - inside the 0.2.x line would have passed unremarked. + inside the 0.2.x line would have passed unremarked. It was then left at + 0.2.0 while 0.3.0 shipped, which is the same gap again, so the instruction + above is worth taking literally: this line moves in the commit that moves + VersionPrefix, not in the one after it. --> true - 0.2.0 + 0.3.0