-
Notifications
You must be signed in to change notification settings - Fork 532
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Combating version churn #1720
Comments
I would also love to see a solution here. Of the options currently suggested, personally I think the third would be the nicest of those given for reasons you've already brought up. So I'll just summarize my thoughts here. I'm not sure that I would also not be keen on breaking semver as tooling does rely on it, although I do agree that any individual crate is unlikely to break on updates too often unless they happen to be one of the unlucky ones. Which leaves making |
Note this only really works for private implementation details. If anything is exposed through the public API of a crate, I don't want to have to convert between each crate that implements the same type in its own bindings all the time, I want them to use That's something the |
Great issue! We are indeed aware of it, but an obvious solution is elusive. I will re-read the comments thus far and add any of my own. Keep it coming - I'm confident that together we'll come up with a good solution in the end. |
Thanks @Jake-Shadle for the write up! We have indeed been thinking about this, but we've yet to come up with a good solution. Let me try to talk through the considerations (many of which you've already touched on) so we're sure we're on the same page. Hopefully this makes it easier to talk through possible solutions.
My personal opinion is that a multi-crate solution (if possible) would be the right way to go. This is essentially the solution that Cargo and crates.io push us towards. It also makes other issues we've run into go away (e.g., rustdoc struggles with such a massive monolithic crate). However, the Windows API surface does not make this easy, so we still have to do work to even understand how we would begin to break up |
This was also previously discussed here: #432 |
In the short term, I'll probably exclude |
Would having one crate for all type definitions and then several for function declarations work? Function declarations can't have cyclic dependencies. Or do the type definitions also regularly change? |
I'm not sure that the developer experience hit would be worth it. Normally folks tend to think of APIs as functions and types bundled under some logical namespace. For example, if you're making an app that relies on direct2d, it feels natural if all of the APIs that logically fall under the direct2d banner are in 1 dependency. Having to break up by type vs function might be confusing, and I don't think it wins us a whole lot. I'll think about this more. |
The types can be re-exported by the individual function crates. |
A huge portion of the Windows API is defined in terms of COM and WinRT types and those don't really make sense to split up in that way either. |
FYI: I have introduced an RFC mechanism in #1731. At some point, when someone feels they have a solid understanding of the problem and a solution that addresses the concerns outlined in this issue, it would be good to open an RFC proposing how to address this. I know, for example, some folks at Microsoft are investigating the feasibility of a multi-crate approach. |
Update to fd-lock 3.0.6, which updates some subdependencies to pull in a fix for compiling for powerpc64 in rustix. It also updates windows-sys to a version being adopted by [many other crates]. [many other crates]: microsoft/windows-rs#1720 (comment)
Update to fd-lock 3.0.6, which updates some subdependencies to pull in a fix for compiling for powerpc64 in rustix. It also updates windows-sys to a version being adopted by [many other crates]. [many other crates]: microsoft/windows-rs#1720 (comment)
Just a quick update on this issue. While I've been exploring a multi-crate solution, it is far from a home run. I have excluded the We are also doing a lot of work to reduce the overall size of the |
I also wanted to mention that Anyway, I'll close this issue for now as there isn't really any actionable work here. Feel free to keep the conversation going and if new information comes to light, we can always revisit this topic. |
I don't really see any reasoning here for why a multi-crate solution is not viable. All that was written is " While I've been exploring a multi-crate solution, it is far from a home run." What about it was not a homerun? It would be really great to get a breakdown of the pros and cons of each approach so others can get insight into the decision-making process here. |
I'm not necessarily saying it's not viable, although I have my doubts. I'm saying the original issue - version churn of the |
This is exactly what I mean - it would be really nice to know the issues that were run into. Perhaps others have ideas on how to overcome the limitations you've found. Writing up your findings gives others a way to check your assumptions and assist in finding solutions. |
Agreed and still plan to do that when I get a moment, probably using the RFC model. |
Here you go: #2396 Let me know if this addresses the need. |
@Jake-Shadle would you be willing to update your PRs to use #2396? |
Sure. |
Thanks all! https://crates.io/crates/windows-bindgen v0.47.0 has now been released and includes the new standalone code generation support. |
I looked at this recently-ish, and while I haven't gone as far as implementing something concrete, it seemed, at least for windows-sys (not sure about windows, I haven't dug deep enough in what its APIs look like), that splitting types and functions would solve the circular dependency problem. Is that something you considered? |
Yes, the challenge is with splitting in a way that (a) solves the toolchain problems and (b) continues to be easy to use and maintain. With over 600 namespaces defined in metadata, that turns out to be challenging technically and practically. Anyway, we now have three viable ways to consume Windows APIs namely the
I don't think even more options would be beneficial. My focus for this year remains on metadata stabilization and tooling so that we can reign in the metadata and more easily reshape and balance the definitions in a way that would be more beneficial to Rust and allow us to finally stabilize the |
@kennykerr is standalone bindings generation for the |
That is a much bigger task and something I'm working on, but I'd like to see how well the existing standalone support is received and adopted before adding support for the I've fixed all reported issues to improve the usability of this feature and I hope to see this help the Rust community improve support for Windows (#2416 #2421 #2426 #2430). |
@Jake-Shadle let me know if there's anything else you need to wrap up |
I almost invariably need only a few definitions at a time (e.g. in quinn-udp), so this is appealing. |
Just a quick update for those still following along. I'm nearly ready to publish the |
The |
@kennykerr thanks, this is looking very promising already! While in the process of converting one of my apps to use these minimal COM bindings, I ran into not getting the Also, #2475 doesn't explain what and how to use |
Thanks for kicking the tires - please create new issues for any problems you discover - that way I won't forget to address them. Yes, https://kennykerr.ca/rust-getting-started/standalone-code-generation.html |
@kennykerr thanks, I'll file a separate issue for the lack of Perhaps |
Hmm, maybe it should have a |
Yes, I'll just hide it. |
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
orwindows-sys
overwinapi
. 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 thewindows-sys
crate case of being low level system bindings.For a simple example, let's take
parking_lot
.parking_lot
currently depends onwindows-sys:0.34
, which is around 1.5 months oldwindows-sys:0.35
(22 days old) about a week agowindows-sys
was bumped to 0.36 a few hours agoparking_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 ofwindows-sys
asparking_lot
windows-sys
simultaneouslyThe 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
windows-sys
, as it means that any change in any crate in this repo, regardless of the downstream usage, results in a new version.HANDLE
#1439) that they're very unlikely to actually observe such a breaking change in practice.libc
of 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 inevitablePossible 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.
libc
, where they've been on a0.2
minor version for years and only ever bump the patch version, means semver compatibility across the ecosystem.libc
obviously 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-sys
in 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-sys
will 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.windows-bindgen
a first class citizen (relatedwindows-bindgen
needs 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-sys
dependency altogether, avoiding the problem of multiple versions now and in the future. If we go back to theparking_lot
case 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-bindgen
tool 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 changeClosing
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.
The text was updated successfully, but these errors were encountered: