microsoft / windows-rs

Rust for Windows
https://kennykerr.ca/rust-getting-started/
Apache License 2.0
10.1k stars 473 forks source link

Use Semantic Versioning PATCH versions more liberally. #3127

Closed BobG1983 closed 1 week ago

BobG1983 commented 1 week ago

Suggestion

Semantic Versioning (semver.org) describes the version numbers thus:

Given a version number MAJOR.MINOR.PATCH, increment the:

MAJOR version when you make incompatible API changes
MINOR version when you add functionality in a backward compatible manner
PATCH version when you make backward compatible bug fixes

Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.

A large number of crates depending on the Windows crates. In many instances they are using older versions of the crate. In many cases no compatibility break has happened as far as I can tell (say 0.52 to 0.57), but Cargo can't pick up the update automatically because non-breaking changes are added as MINOR not PATCH versions (I think?).

The windows crate is also quite slow to build. Combine these two things and I find myself spending high percentages of time building the Windows crate over and over.

I might be wrong, but if I'm not, I would really really appreciate it. My games build time would drop in half if I only had to build the Windows crate once.

BobG1983 commented 1 week ago

Again, please ignore me if this is unreasonable/against strategy or what have you, I'm just a little at my wits end.

kennykerr commented 1 week ago

Semantic versioning is used but the windows crate is generated from metadata that is not yet stable and thus any update to the metadata will in practice result in a breaking change necessitating a "major" semver bump.

Compare this... https://github.com/microsoft/windows-rs/tree/0.52.0/crates/libs/bindgen/default

With this... https://github.com/microsoft/windows-rs/tree/0.57.0/crates/libs/bindgen/default

A long term goal is to stabilize metadata and avoid the churn but for now this is where we are.

The windows crate is also quite slow to build. Combine these two things and I find myself spending high percentages of time building the Windows crate over and over.

Note that Cargo should cache the build so your dev inner loop should not be impacted too much.

riverar commented 1 week ago

It would be great to see some examples of what broke you, just so we better understand which changes are burning folks more than others. (If you don't have that readily available, don't worry about it.)

BobG1983 commented 1 week ago

I'm using Bevy (https://www.bevyengine.org) on Windows.

Right now Bevy relies on four different versions of the Windows crate:

windows@0.48 -> accesskit_windows 0.15 -> accesskit_winit 0.17 -> bevy_winit 0.13.2  -> bevy 0.13.2
windows@0.52 -> gpu_allocator 0.25     -> wgpu 0.19            -> bevy_render 0.13.2 -> bevy_0.13.2
             -> sysinfo 0.30.12        -> bevy_diagnostic 0.13.2                     -> bevy 0.13.2
windows@0.54 -> cpal 0.15.3            -> rodio 0.17.3         -> bevy_audio 0.13.2  -> bevy 0.13.2
windows@0.57 -> gilrs-core 0.5.12      -> gilrs 0.5.12         -> bevy_gilrs 0.13.2  -> bevy 0.13.2

My Windows builds of my game take 2x as long to build and 14x as long to link (on incremental) on a 9700k with 64Gb of RAM on an NVME SSD that's mostly empty as they do on my M1 Macbook Pro. That's using LLD on Mac and Windows, and not using cranelift. The only other difference is share-generic is on for MacOS and off for Windows (cos Bevy hits the limit of symbols under MSVC).

When I run cargo timings it shows that nearly 50% of my build time is spent building Windows crates.

If non-breaking changes were 0.n then all these crates would share the same windows version. They currently can't. Which then means having to chase down all the ecosystem trying to get them to update windows crate versions.

So...I recursively vendored all my deps, swapped Windows versions to a single version (which in all cases required zero code changes, I believe), and my build time halved to be more akin to MacOS.

riverar commented 1 week ago

That's super helpful, thanks!

kennykerr commented 1 week ago

There is a tension between the size of the Windows API, the productivity value of the windows crate, and the difficulty in getting dependent crates to update on a regular basis. Even the windows-sys crate, which hasn't been updated in over 7 months, has at least three major versions in wide use today.

The alternative for library crates like Bevy would be to use standalone code generation. That's what the Rust Standard Library does for Windows support. https://kennykerr.ca/rust-getting-started/standalone-code-generation.html

BobG1983 commented 1 week ago

Unfortunately, that's not really possible because Windows is deep in the deps of deps.

Thank you though.

ChrisDenton commented 1 week ago

If non-breaking changes were 0.n then all these crates would share the same windows version.

This assumes there are no breaking changes in those releases. I wouldn't assume that. Maybe it is something that could possibly be checked mechanically in the future. Note though that "no breaking changes for bevy" and "no breaking changes at all" are two very different statements.

As for mitigations, you can try using a [patch] section in Cargo.toml. Also crate authors can set a range of versions they're compatible with. Though each major version needs to be continually tested.

ChrisDenton commented 1 week ago

Maybe it is something that could possibly be checked mechanically in the future.

Just to expand on that a bit, I don't think we're able to do this fully today. E.g. cargo-semver-check has limitations. These are however potentially solvable (btw, the author is looking for sponsorship so they can tackle these issues).

BobG1983 commented 1 week ago

Because I thought it might be useful. Here is the timings for my project. cargo-timings.zip

FYI, this is running on a 2TB NVME running at 7800 MB/s formatted as a dev drive (and rustc et al are all on the same drive). I have 64GB of RAM and a 9700k running at 4.6GHz running the latest Windows 11. This is compiled using Nightly from 6/27/2024 and rust-lld with share-generics off and the parallel frontend.