Skip to content
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

Start using windows sys for Windows FFI bindings in std #110152

Merged
merged 4 commits into from
May 9, 2023

Conversation

ChrisDenton
Copy link
Contributor

@ChrisDenton ChrisDenton commented Apr 10, 2023

Switch to using windows-sys for FFI. In order to avoid some currently contentious issues, this uses windows-bindgen to generate a smaller set of bindings instead of using the full crate.

Unlike the windows-sys crate, the generated bindings uses *mut c_void for handle types instead of isize. This to sidestep opsem concerns about mixing pointer types and integers between languages. Note that SOCKET remains defined as an integer but instead of being a usize, it's changed to fit the standard library definition:

#[cfg(target_pointer_width = "32")]
pub type SOCKET = u32;
#[cfg(target_pointer_width = "64")]
pub type SOCKET = u64;

The generated bindings also customizes the #[link] imports. I hope to switch to using raw-dylib but I don't want to tie that too closely with the switch to windows-sys.


Changes outside of the bindings are, for the most part, fairly minimal (e.g. some differences in *mut vs. *const or a few types differ). One issue is that our own bindings sometimes mix in higher level types, like BorrowedHandle. This is pretty adhoc though.

@rustbot
Copy link
Collaborator

rustbot commented Apr 10, 2023

r? @thomcc

(rustbot has picked a reviewer for you, use r? to override)

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Apr 10, 2023
@ChrisDenton
Copy link
Contributor Author

(rebased on master branch)

@kennykerr
Copy link
Contributor

Definitely want to avoid using a hacked windows-bindgen. 😅 Happy to discuss your needs.

@ChrisDenton
Copy link
Contributor Author

ChrisDenton commented Apr 10, 2023

It's mostly just making the following the edits, which I believe could be done by using the windows-metadata writer to produce our own metadata file which windows-bindgen could consume.

pub type HANDLE = *mut ::core::ffi::c_void;
pub type FindFileHandle = *mut ::core::ffi::c_void;
pub type BCRYPT_ALG_HANDLE = *mut ::core::ffi::c_void;
pub type HMODULE = *mut ::core::ffi::c_void;

pub const INVALID_HANDLE_VALUE: HANDLE = ::core::ptr::invalid_mut(!0);

#[cfg(target_pointer_width = "32")]
pub type SOCKET = u32;
#[cfg(target_pointer_width = "64")]
pub type SOCKET = u64;

The most hacky thing it does is change the way imports work to fit std's currently style. E.g.:

#[link(name = "kernel32")]
extern "system" {
    pub fn CloseHandle(hobject: HANDLE) -> BOOL;
    pub fn GetLastError() -> WIN32_ERROR;
    // etc,
}

But I do hope we can move to raw-dylib.

@rust-log-analyzer

This comment has been minimized.

@kennykerr
Copy link
Contributor

For the type changes, can we find some middle ground with the Win32 metadata or is there a technical reason you need these just so? I’d prefer that we don’t manage forked metadata in the short term as I’m working on some Rust-friendly metadata authoring support which will make this a lot easier in the long run.

For the imports, is that because std cannot include a crate dependency on windows-targets? Absolutely raw-dylib is the future, but you are leaving yourself susceptible to the same issues I described here:

Amanieu/parking_lot#378

We could also plausibly add a StandaloneFlags with a std mode for the standalone code generator if needed. Then at least we can manage the differences in one place and not have to resort to pre/post processing.

@kennykerr
Copy link
Contributor

For that matter, I'd be happy to discuss changes to windows-sys so you can simply use that directly.

@ChrisDenton
Copy link
Contributor Author

To take the changes one by one...

pub type HANDLE = *mut ::core::ffi::c_void;
pub type FindFileHandle = *mut ::core::ffi::c_void;
pub type BCRYPT_ALG_HANDLE = *mut ::core::ffi::c_void;
pub type HMODULE = *mut ::core::ffi::c_void;
pub const INVALID_HANDLE_VALUE: HANDLE = ::core::ptr::invalid_mut(!0);

There are still some discussion about how handle types should be... handled. By keeping the status quo within the std I was hoping to avoid trying to force that issue at this time. I suspect it may be a blocker otherwise.

#[cfg(target_pointer_width = "32")]
pub type SOCKET = u32;
#[cfg(target_pointer_width = "64")]
pub type SOCKET = u64;

This is less of an issue but Rust stably defines the SOCKET handles this way. We could have a difference between public and private types (as they are ultimately the same bit size). However, doing this is somewhat more involved due to all the places socket code is used.

#[link(name = "kernel32")]
extern "system" {
    pub fn CloseHandle(hobject: HANDLE) -> BOOL;
    pub fn GetLastError() -> WIN32_ERROR;
    // etc,
}

The linking changes again are there to keep the status quo for now. Using windows-targets means distributing windows.lib with the stdlib which is a bigger change to make, especially if it's only temporary (i.e. until we're ready to use raw-dylib in std itself). It also affects people who use custom build systems. I'd rather avoid too much churn here.

@kennykerr
Copy link
Contributor

For the handle types, I would like the metadata to actually store the true native type def rather than tip the scales in favor of C#. We'll likely get that resolved on the Rust side with the new metadata authoring support.

Anyway, sounds like adding standalone flags to windows-bindgen might be a good approach here - happy to get that started if you're happy with that approach.

@ChrisDenton
Copy link
Contributor Author

For sure! That sounds good to me.

@kennykerr
Copy link
Contributor

Take this for a spin: microsoft/windows-rs#2439

@ChrisDenton ChrisDenton force-pushed the windows-sys branch 2 times, most recently from 1fdcc6c to d84d939 Compare April 14, 2023 00:41
@rustbot rustbot added the T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) label Apr 14, 2023
@ChrisDenton
Copy link
Contributor Author

Ok, I've updated this PR and the description to reflect the current code gen. This no longer uses a hacked windows-bindgen (see above) but a few things still differ between regular windows-sys and these bindings (see OP).

@rust-log-analyzer

This comment has been minimized.

@kennykerr
Copy link
Contributor

The update looks great! Let me know when you need me to publish an update of the windows-bindgen crate.

@ChrisDenton
Copy link
Contributor Author

Sure thing. I think I'd want to wait for the next metadata update but there's no rush, I'm happy to let this sit for a little bit to give people time to comment, if anyone is inclined to do so.

@bors
Copy link
Contributor

bors commented Apr 14, 2023

☔ The latest upstream changes (presumably #110331) made this pull request unmergeable. Please resolve the merge conflicts.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@bors
Copy link
Contributor

bors commented Apr 16, 2023

☔ The latest upstream changes (presumably #109133) made this pull request unmergeable. Please resolve the merge conflicts.

@ChrisDenton
Copy link
Contributor Author

Ok, I think with the latest metadata this is looking good to go.

@kennykerr, A new release of windows-bindgen would be great whenever you're ready, then I can run tests in earnest. The only other thing that I thought might be useful is a simple switch to make it simpler when we're ready to start testing raw-dylib. But I don't think that's essential.

@ChrisDenton ChrisDenton removed the T-infra Relevant to the infrastructure team, which will review and decide on the PR/issue. label Apr 18, 2023
Copy link
Member

@thomcc thomcc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delay here, I've been occupied with family stuff.

This looks great and avoids most of the problems I'd normally complain about in something like this 😆. (In particular, windows-sys is heavyweight enough compared to what we need from it that I prefer this approach to a direct dep)

Only real nit is that IMO we should require the .lst file be sorted, (and verify that in CI). I'd accept an argument for why it's fine as-is if you feel really strongly, though.

library/std/src/sys/windows/api.rs Outdated Show resolved Hide resolved
library/std/src/sys/windows/c/windows_sys.lst Outdated Show resolved Hide resolved
@thomcc
Copy link
Member

thomcc commented May 5, 2023

@rustbot author

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 5, 2023
@ChrisDenton
Copy link
Contributor Author

I've sorted windows-sys.lst alphabetically (checked by tidy) and rebased.

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels May 5, 2023
@thomcc
Copy link
Member

thomcc commented May 6, 2023

checked by tidy

Sorry if I'm blind, but I don't see a change to tidy.

@ChrisDenton
Copy link
Contributor Author

Tidy checks everything between // tidy-alphabetical-start and // tidy-alphabetical-end. So I just added that to the lst file rather than making any bigger changes.

@thomcc
Copy link
Member

thomcc commented May 6, 2023

Oh, my bad. Yeah, thanks

@bors r+

@bors
Copy link
Contributor

bors commented May 6, 2023

📌 Commit e314a3b has been approved by thomcc

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 6, 2023
@bors
Copy link
Contributor

bors commented May 9, 2023

⌛ Testing commit e314a3b with merge 7e7483d...

@bors
Copy link
Contributor

bors commented May 9, 2023

☀️ Test successful - checks-actions
Approved by: thomcc
Pushing 7e7483d to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label May 9, 2023
@bors bors merged commit 7e7483d into rust-lang:master May 9, 2023
12 checks passed
@rustbot rustbot added this to the 1.71.0 milestone May 9, 2023
@ChrisDenton ChrisDenton deleted the windows-sys branch May 9, 2023 09:04
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (7e7483d): comparison URL.

Overall result: ✅ improvements - no action needed

@rustbot label: -perf-regression

Instruction count

This is a highly reliable metric that was used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-0.3% [-0.3%, -0.3%] 1
All ❌✅ (primary) - - 0

Max RSS (memory usage)

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-1.0% [-1.1%, -0.9%] 2
Improvements ✅
(secondary)
-1.0% [-1.0%, -1.0%] 1
All ❌✅ (primary) -1.0% [-1.1%, -0.9%] 2

Cycles

This benchmark run did not return any relevant results for this metric.

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 656.874s -> 656.5s (-0.06%)

@uweigand
Copy link
Contributor

It appears this merge has broken ./x.py test on s390x-unknown-linux-gnu. I now see this failure:

   Doc-tests std
error[E0412]: cannot find type `WSADATA` in this scope
   --> /home/uweigand/rust/library/std/src/sys/windows/c/windows_sys.rs:715:63
    |
715 |     pub fn WSAStartup(wversionrequested: u16, lpwsadata: *mut WSADATA) -> i32;
    |                                                               ^^^^^^^ not found in this scope

error[E0412]: cannot find type `CONTEXT` in this scope
    --> /home/uweigand/rust/library/std/src/sys/windows/c/windows_sys.rs:3034:29
     |
3034 |     pub ContextRecord: *mut CONTEXT,
     |                             ^^^^^^^ not found in this scope

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0412`.
error: doctest failed, to rerun pass `-p std --doc`

It's unclear to me why doctest wants to build this Windows-specific file on a non-Windows platform (and why this apparently does not cause failures on any other non-Windows platform?).

@ChrisDenton
Copy link
Contributor Author

Yes that puzzled me too so I made a PR to remove it (#111401). Hopefully that should fix the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants