-
Notifications
You must be signed in to change notification settings - Fork 605
Combating version churn #1720
Description
First of all I just want to thank the maintainers/Microsoft for making these crates, having a set of maintained bindings that can supplant winapi and be confident will be maintained in the future has been really great.
Problem
That being said, I think the current velocity of version changes in this repo is a bit problematic for the ecosystem, especially as more crates adopt windows or windows-sys over winapi. This is because, for the past several months, the crates in this repo have have had their minor version bumped on average every couple of weeks, essentially guaranteeing that with enough transitive dependencies on one of the crates in this repo, a project's crate graph will include multiple versions of one or more windows crates. Duplicate versions can be fine for short periods of time as various crates catch up to newer releases, however the velocity of this repo is far greater than many crates in the ecosystem, especially in the windows-sys crate case of being low level system bindings.
For a simple example, let's take parking_lot.
parking_lotcurrently depends onwindows-sys:0.34, which is around 1.5 months old- Someone helpfully added a PR to bump to
windows-sys:0.35(22 days old) about a week ago windows-syswas bumped to 0.36 a few hours ago
parking_lot is now in a conundrum. It could accept the 0.35 PR, and cut a release, but there's already a newer version, so they could bump directly to 0.36 instead, skipping 0.35 entirely. However, depending on what other crates you have in your graph, either decision is (or the none option of just staying on 0.34) almost guaranteed to result in multiple versions of windows-sys as
- Some crates will have transitioned to 0.35 sometime since it was released, but might take several days/weeks/months to move to 0.36
- Some crates will be on 0.34 (or even older) versions like
parking_lot - Some crates might move to 0.36 quite quickly, which could mean you're depending on up to 3! different versions of
windows-syssimultaneously
The real kicker is that parking_lot uses a grand total of 3 function bindings and a few type/constant bindings which, beyond fundamental changes such as #1439, are...."never" going to change, thanks to Windows' backwards compatibility guarantees.
If we take a step back I see there being multiple reasons for this version churn
- All (or at least all the "user facing" ones) of crates in this repo share a single version. On the one hand this is nice since versioning is internally consistent and makes perusing version history more easy etc. However, it's also a very big hammer, particularly in the case of
windows-sys, as it means that any change in any crate in this repo, regardless of the downstream usage, results in a new version. - The Windows API surface is positively massive, and due to how the windows/-sys crates are organized via feature flags, any breaking change to one sub-API is technically a breaking change to the crate as a whole. This is despite the fact that an overwhelming majority of downstream users will use an incredibly small fraction of that massive API surface, meaning (again, other than fundamental changes such as Don't specialize
HANDLE#1439) that they're very unlikely to actually observe such a breaking change in practice. - Reiterating from above, the release cadence of this repo is just much higher than most other crates in the ecosystem, but because the bindings in windows/-sys are essentially the
libcof Windows, many crates depend (or will, once they transition from eg.winapi) on them which coupled together mean multiple versions of one or more crates in this repo become almost inevitable
Possible Solutions
Below are several options that I can see that could solve, or at least alleviate, this problem. Obviously it's up to the maintainers on what they think is best (or if it will be considered a problem at all), so these are just some thoughts.
- Stabilize and use patches. The crates in this repo are still early days so I doubt this could happen anytime soon, but having a model similar to
libc, where they've been on a0.2minor version for years and only ever bump the patch version, means semver compatibility across the ecosystem.libcobviously has a bit of a simpler problem since the API surface is orders of magnitude smaller than Windows, but it is a proven model. windows-sysin particular (maybe notwindows?) could be more lenient about breaking semver. What I mean be this is, in an overwhelming majority of use cases, a crate usingwindows-syswill use an incredibly small fraction of the API surface exposed by it. This means that (again, beyond fundamental changes like Don't specializeHANDLE#1439) that a breaking change inwindows-sys, such as a moving constants or functions to a different location, are not going to be observed by the downstream crate at all unless they were using those exact functions/constants. Speaking for myself, this kind of breakage would be entirely acceptable if it was clearly stated in the release notes, or even just as a general caveat clearly stated in the README as it is trivial to find where a function/constant was moved to in a newer version and change it to the new location/feature flag. This is unfortunately not a super viable method for transitive dependencies however, I just thought I would mention it.- Make
windows-bindgena first class citizen (relatedwindows-bindgenneeds documentation #1407). At least in my use cases, and I believe many others, using Windows bindings is a fairly "write once" operation that generally doesn't change much past the initial implementation. For this kind of use case, having a convenient way to do "generate functions x, y, and z, and these constants to this output file" would be frankly amazing. For example, here's a recent PR I made to add minidump writing. In grand total, this uses 5 functions, ~6 constants, and ~6 types. These will most likely never change again, and by generating only the bindings I need, once, and just including them as a single source file directly in the project, I could get rid of thewindows-sysdependency altogether, avoiding the problem of multiple versions now and in the future. If we go back to theparking_lotcase above, it's already manually creating its own bindings toNt*functions that are not part of Win32 metadata, and could do the same for the few functions/constants that it is using fromwindows-sys, but having that functionality exposed in a friendly way by awindows-bindgentool would mean generating the bindings once and never having to worry about version churn in the future, because again, these functions/constants/types are not going to change
Closing
I'm sure the maintainers have probably thought about this issue already, but I'm opening this issue because I couldn't find anything relevant that was already open and want to foster a discussion in the open about this, since I'm sure we're not the only ones that find the current situation problematic.
Sorry this was a bit of a braindump I've just been thinking about this the last few days and wanted to finally just write it down.