Skip to content

test: enable rust bindings tests on Windows#5969

Merged
boquan-fang merged 6 commits into
aws:mainfrom
boquan-fang:boquan-fang/windows-rust-bindings-tests
Jul 9, 2026
Merged

test: enable rust bindings tests on Windows#5969
boquan-fang merged 6 commits into
aws:mainfrom
boquan-fang:boquan-fang/windows-rust-bindings-tests

Conversation

@boquan-fang

@boquan-fang boquan-fang commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Goal

Enable s2n-tls rust bindings tests on Windows.

Why

In the previous PR, we made the s2n-tls' rust bindings compiled and built on Windows. To make them truly available to our customers, we need to add rust bindings tests to our CI to verify that they work properly on Windows.

How

The idea in general is to run ./bindings/rust/extended/generate.sh on Windows' CI. However, there are some configurations that we need to do for Windows Github actions in order for it to work. The UCRT64 and MINGW64 works mostly natively with little configurations needed. However, as a older environment, Clang64 which uses a LLVM-based flavor of MinGW toolchain, gnullvm, needs some set up specified in .github/workflows/ci_windows.yml. My comments explain why they are needed.

At a high level, the CI work breaks down into:

  • Toolchain / host selection. We force the MinGW gnu host with rustup set default-host, otherwise rustup picks the runner's MSVC host, which can't build the GCC/Clang flags in build.rs.
  • gnullvm cross-compile (clang64 only). Pinned Rust 1.89 has no gnullvm host toolchain, so we install the gnu host and cross-compile to x86_64-pc-windows-gnullvm. This requires adding the gnullvm std to both the 1.89 workspaces and the repo-root stable default, and linking winpthreads explicitly (-Clink-arg=-lpthread via RUSTFLAGS/RUSTDOCFLAGS) since gnullvm doesn't auto-link it for s2n's pthread/clock_gettime/nanosleep symbols.
  • bindgen for gnullvm. aws-lc-sys has no prebuilt bindings for gnullvm, so it runs bindgen at build time; we install bindgen-cli (built for gnullvm) into the msys2 prefix so it's on PATH.
  • Test steps. The generate script runs the sys-crate sanity checks, and CI then runs the extended workspace tests, the feature-gated tests, and the integration crate.

Callouts

There are two things which we can not do on Windows and they are worth to be called out:

FIPS feature can't be enabled right now

According to aws-lc-fips-sys build instruction, the crate is not available yet for MinGW toolchain. Specific in https://aws.github.io/aws-lc-rs/platform_support.html. Hence, we can't run fips tests on Windows. However, as a rust feature, we can't really just gate them on Linux and MacOS only. The workaround that I choose is to manually remove fips feature by jq commands. There is a feature request to Rust: https://internals.rust-lang.org/t/pre-rfc-cargo-test-default-features-except-and-co/20850 which can help with this scenario if it is made available. If my reviewer knows other alternatives, I am happy to discuss.

If a user tried to build s2n-tls rust bindings with the fips feature with MinGW toolchain, the build will fail automatically.

The good news is: the aws-lc team is working on getting aws-lc-fips-sys build and available on MinGW as specified by this issue and PR: aws/aws-lc#3207, aws/aws-lc#3263. Their estimate is to land this feature by early 2027, so we can enable fips for Rust bindings at that time.

errno is a different channel on Windows

s2n's C IO layer (s2n_io.c) reads the C runtime errno to tell a retriable "would block" from a fatal IO error. On non-Windows the errno crate writes exactly that CRT errno, but on Windows it writes the Win32 last-error instead, which s2n never reads. So the test/callback IO helpers now set the CRT errno directly on Windows (via _set_errno, which shares the same statically linked CRT as s2n). This lives in set_io_would_block in three places (s2n-tls testing, s2n-tls-tokio, and tls-harness); they're in separate crates/domains so the small helper is duplicated rather than shared.

Note this only applies to the errno that s2n's C code reads. Error::io_error is intentionally left on the errno crate: its value is written and read back entirely on the Rust side (capture() reads it via the same errno crate), so it's self-consistent on every platform.

Some tests are gated out on Windows due to platform/tooling limitations

  • Allocator-sanity tests: these custom global allocators record into a thread-local, and on Windows the first thread-local access from inside an allocation recurses back into the allocator and overflows the stack during process startup. The allocator and the tests that depend on it are gated to non-Windows.

BoringSSL integration test will be skipped

The generate script has a integration tests that runs with Boring SSL. Unfortunately, building boringssl on MinGW seems not possible. This behavior is also documents in another issue: cloudflare/boring#71. I decided to skip this integration tests on Windows. The test will still be ran on Linux CI.

Platform-dependent enum representation

bindgen generates some C enums with a different Rust repr per platform: u32 on Linux, i32 on Windows. This shows up in async_verify_and_offload.rs, where s2n_async_offload_op_type needs an explicit as u32 cast on Windows to match the always-u32 allow-list. It's also part of why the metrics subscriber above doesn't compile on Windows.

Tests Runtime Considerations

#5969 (comment)

Testing

Windows CI should pass: https://github.com/aws/s2n-tls/actions/runs/28900040189/job/85734269755?pr=5969.

We run default + feature tests in the extended directory and also test with the integration package.

Related

related to #4018.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@github-actions github-actions Bot added the s2n-core team label Jun 30, 2026
@boquan-fang
boquan-fang marked this pull request as ready for review June 30, 2026 18:11
Comment thread bindings/rust/extended/generate.sh Outdated
Comment thread bindings/rust/extended/generate.sh Outdated
@boquan-fang
boquan-fang force-pushed the boquan-fang/windows-rust-bindings-tests branch from 7f0308a to a1ad59e Compare July 7, 2026 21:30
@boquan-fang
boquan-fang requested a review from maddeleine July 7, 2026 21:58
@boquan-fang
boquan-fang force-pushed the boquan-fang/windows-rust-bindings-tests branch from a1ad59e to 8c404eb Compare July 7, 2026 22:58
@maddeleine

maddeleine commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Currently, the Windows CI will run for about 27 minutes for the rust tests.

Yeah it looks like the Windows jobs are now taking 30 minutes. Can you investigate a bit into this? To me it looks like the "generate rust bindings" github action that is taking the longest. The thing is, if we merge this then I think this would be our slowest CI job, which isn't good. I'm not sure of that, but I think most of our CI jobs complete in ~20min.
Edit: Actually I'm pretty certain what is causing the slowness. It's this line. Release compilations can take a while, and I'm not sure if it's worth us testing the release version here.

Edit: Well actually I guess if I'm being fair it looks like cpp check is the slowest:
Linters / cppcheck (pull_request)Successful in 32m

Comment thread .github/workflows/ci_windows.yml
@boquan-fang

boquan-fang commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

Currently, the Windows CI will run for about 27 minutes for the rust tests.

Yeah it looks like the Windows jobs are now taking 30 minutes. Can you investigate a bit into this? To me it looks like the "generate rust bindings" github action that is taking the longest. The thing is, if we merge this then I think this would be our slowest CI job, which isn't good. I'm not sure of that, but I think most of our CI jobs complete in ~20min. Edit: Actually I'm pretty certain what is causing the slowness. It's this line. Release compilations can take a while, and I'm not sure if it's worth us testing the release version here.

Edit: Well actually I guess if I'm being fair it looks like cpp check is the slowest: Linters / cppcheck (pull_request)Successful in 32m

From my observation, the cargo run in the integration crate takes the most time:

pushd ../standard/integration
rustc --version || rustup toolchain install
cargo run
popd

To be more specific, compiling openssl-sys v0.9.116 is the most time consuming step.

@boquan-fang
boquan-fang requested a review from mhelkey July 8, 2026 20:37
@boquan-fang

boquan-fang commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

I investigated the potential slowdown of the tests of s2n-tls Windows CI. I ran cargo run with timing flag and found out that compiling openssl-sys takes the most time on Windows.

To speedup the process, decided to use all cores available on the machine to compile openssl, and that significantly speedup the process. At this moment, the CI will take around 23 minutes to finish all the tests, and the generate script will take only about 3 minutes to finish running the generate script.

I have attached the timing report to this comment to show the difference.
cargo-timing-multi-core-report.html
cargo-timing-single-thread-reporthtml.html

The current runtime is acceptable. We might also skip cargo test --release and cargo publish --dry-run to speed up the tests.

@boquan-fang
boquan-fang requested a review from maddeleine July 8, 2026 22:59
Comment thread bindings/rust/extended/s2n-tls/src/lib.rs Outdated
Comment thread bindings/rust/standard/integration/src/mtls/async_verify_and_offload.rs Outdated
Comment thread .github/workflows/ci_windows.yml
@boquan-fang
boquan-fang force-pushed the boquan-fang/windows-rust-bindings-tests branch from 9446f97 to d40e46e Compare July 9, 2026 21:24
* make comments of allocator clealer
* always cast offload pkey verify to u32
@boquan-fang
boquan-fang force-pushed the boquan-fang/windows-rust-bindings-tests branch 2 times, most recently from 29ff6de to ac9dab7 Compare July 9, 2026 21:55
@boquan-fang
boquan-fang force-pushed the boquan-fang/windows-rust-bindings-tests branch from ac9dab7 to 6385451 Compare July 9, 2026 21:55
@boquan-fang
boquan-fang requested a review from maddeleine July 9, 2026 22:03
Comment thread bindings/rust/extended/s2n-tls/src/testing.rs
* move all cfg into one function of set_io_would_block
@boquan-fang
boquan-fang enabled auto-merge July 9, 2026 22:46
@boquan-fang
boquan-fang added this pull request to the merge queue Jul 9, 2026
Merged via the queue into aws:main with commit 86483fd Jul 9, 2026
59 checks passed
@boquan-fang
boquan-fang deleted the boquan-fang/windows-rust-bindings-tests branch July 9, 2026 23:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants