Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 28 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -40,11 +48,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

Expand Down Expand Up @@ -450,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
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@

<!-- Package metadata. -->
<PropertyGroup>
<VersionPrefix>0.3.0</VersionPrefix>
<VersionPrefix>0.4.0</VersionPrefix>
<Authors>Box3D.NET contributors</Authors>
<Company>Box3D.NET</Company>
<Product>Box3D.NET</Product>
Expand Down
7 changes: 5 additions & 2 deletions Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -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.
-->
<EnablePackageValidation>true</EnablePackageValidation>
<PackageValidationBaselineVersion>0.2.0</PackageValidationBaselineVersion>
<PackageValidationBaselineVersion>0.3.0</PackageValidationBaselineVersion>
</PropertyGroup>

<ItemGroup Condition="'$(IsPackable)' == 'true'">
Expand Down
32 changes: 21 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Loading