Add support for Windows - #567
Conversation
Fix compilation of NIOSSL on Windows Note: This code adds some things we might not want to keep around. - OPENSSL_NO_ASM flag which I neededto get it to work - Windows directory listing using FindFirstFileA (not properly tested) - mlock -> VirtualLock on Windows (doesn't yet check if locking was successful)
|
Still needs to set up Windows CI, but if possible I'd like to ensure the tests still succeed on existing platforms |
| // Force a reference to _tls_used to make the linker create the TLS directory | ||
| // if it's not already there. (E.g. if __declspec(thread) is not used). Force | ||
| // a reference to p_thread_callback_boringssl to prevent whole program | ||
| // a reference to CNIOBoringSSL_p_thread_callback_boringssl to prevent whole program |
There was a problem hiding this comment.
We aren't taking any changes to BoringSSL itself. They shouldn't be necessary.
| FindNextFileA(dir, &fileData) | ||
| return self.path + name | ||
| } | ||
| #else |
There was a problem hiding this comment.
Why does this need an #if around the whole block? It'd be nicer to factor the calls out to helpers that can have a small #if.
Motivation:
NIOSSL is the last missing piece for building projects such as SwiftMail
on Windows: swift-nio itself already builds there, but every NIOSSL file
with a platform import ladder ends in #error("unsupported os").
Modifications:
- Define OPENSSL_NO_ASM for CNIOBoringSSL on Windows: the vendored
assembly is only generated for ELF/Mach-O targets, and SwiftPM cannot
build the NASM sources BoringSSL uses for Windows. No vendored
BoringSSL sources are modified.
- Extend the platform import ladders with ucrt/WinSDK branches.
- PosixPort: read errno through _errno() (the errno macro is not
importable on Windows), keep readlink/lstat POSIX-only, and implement
Posix.mlock/munlock on Windows via VirtualLock/VirtualUnlock with
proper error propagation.
- DirectoryContents: factor the platform-specific directory iteration
into a small nextEntryName() helper; implement Windows iteration with
FindFirstFileW/FindNextFileW (wide-char APIs, correct wildcard pattern
and exhaustion handling).
- Skip the c_rehash symlink check on Windows, where openssl rehash
creates plain copies instead of symlinks.
- Convert BIO_get_mem_data lengths (C long, 32-bit on Windows) to Int
explicitly.
- Handle st_mode being CUnsignedShort on Windows.
- Pass inet_ntop's buffer size as size_t on Windows via a small helper.
- Replace raw SOL_SOCKET/TCP_NODELAY channel options in the example
executables with the cross-platform typed options from NIOCore.
- Enable a Windows 6.3 build job in CI, mirroring apple/swift-nio.
Result:
swift build succeeds on Windows (Swift 6.3.1); no functional change on
any other platform.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Use the typed .socketOption(.so_reuseaddr) channel option instead of raw SOL_SOCKET/SO_REUSEADDR. - Map O_CLOEXEC to O_NOINHERIT on Windows. - makeTemporaryFile: mkstemps does not exist on Windows; use a random file name there. - randomSerialNumber: read from BoringSSL's CSPRNG instead of /dev/urandom, which is portable to all platforms. - Replace usleep with Thread.sleep(forTimeInterval:). - Import WinSDK for in_addr/inet_pton in the SAN test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Define _CRT_SECURE_NO_WARNINGS for the vendored BoringSSL sources. - Use fopen_s/strerror_s in PosixPort (and print the actual strerror message in the asserts rather than the pointer). - Give the tests non-deprecated unlink/fdopen wrappers and an errnoDescription helper. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…support Uses the ours strategy deliberately: this branch already carries all of jo/windows-support's changes, reimplemented on current main (and drops the vendored-BoringSSL edits per review). Merging it makes the PR into jo/windows-support fast-forward-clean without reintroducing any of the old branch's content. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Windows support rebased on main, review feedback addressed
…t ucrt Real Windows CI run (DataDock AI, run 30087599273) failed compiling this file with: cannot find 'in6_addr'/'inet_ntop'/'AF_INET'/'AF_INET6'/'socklen_t' in scope Root cause: this file's `#elseif os(Windows) / import ucrt` branch (added by upstream PR apple#567, "Add support for Windows") only imports the C runtime. in_addr/in6_addr/inet_ntop/AF_INET/AF_INET6 are Winsock2 symbols that live in WinSDK, not ucrt -- PR apple#567 covered other files needing Windows support but missed this one (confirmed: no `canImport(WinSDK)`/`os(Windows)` symbol handling existed anywhere else in this file before this commit). Fix mirrors swift-nio's own already-Windows-portable equivalent code (NIOCore/BSDSocketAPI.swift, NIOCore/SocketAddresses.swift): import the specific WinSDK symbols needed via Swift's per-symbol import syntax, and alias them locally to the POSIX names (`in_addr`, `in6_addr`) this file already uses, so the rest of the file needs no changes. `socklen_t` in the error was a red herring from the same missing-import family, not a separate gap -- ipv4ToString/ipv6ToString already special-case Windows to pass `pointer.count` (an Int, matching Winsock's `size_t` StringBufSize parameter) instead of casting to `socklen_t`, so no `socklen_t` typealias is needed here.
|
@Lukasa Maybe give it another look now? We’ve worked in your review comments. |
|
Independent Windows CI datapoints for this PR, from a clean windows-2022 GitHub runner (Swift 6.3.3), two runs. Run 1, this branch as-is: builds with zero errors (main scores 1,633 errors on the same runner, so this PR takes Windows from unbuildable to clean). The test suite is green across the unit suites (ByteBufferBIO, CertificateVerification, ClientSNI, CustomPrivateKey, IdentityVerification, ALPN, and the rest). Five failures, all in NIOSSLIntegrationTest and all in the close/shutdown family: Run 2, same branch with swift-nio overridden to apple/swift-nio#3704's head (the Windows data-path backpressure fix): identical result, same five failures. So these are not downstream of the known WSAEWOULDBLOCK data-path bug; they look like Windows half-close/shutdown semantics in their own right. Happy to share the workflow or raw logs, and to re-run against any revision if that helps get this landed. Even as-is, this PR takes swift-nio-ssl from 1,633 errors to a clean build with a green core suite on Windows. |
|
Follow-up on the five failures: root-caused, and none of them is this PR's fault. Four are a swift-nio defect. The fifth ( With both applied, this PR's suite is fully green on windows-2022 / Swift 6.3.3. One structural note: Windows half-closure currently has no upstream CI guard because |
|
One more independent Windows datapoint from assembling a real server on top of this branch: a duplicate-symbol collision between CNIOBoringSSL and swift-crypto's CCryptoBoringSSL that will hit anyone linking both into one Windows binary (which any TLS server using swift-crypto for application crypto will do). Symptom (lld, windows-2022, Swift 6.3.3): Root cause: both projects vendor BoringSSL behind a symbol prefix, but Fix that worked for us: rename the symbol in one copy. We renamed CNIOBoringSSL's to A more principled home for the fix might be BoringSSL's prefixing mechanism itself (adding the symbol to the prefix list), which would fix it for every downstream vendored copy at once. Happy to turn either form into a PR if useful. |
Fix compilation of NIOSSL on Windows
Note: This code adds some things we might not want to keep around.