-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
ports/windows: Add sockets support on Windows. #14162
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
ports/windows: Add sockets support on Windows. #14162
Conversation
bf71201
to
410163f
Compare
Not quite sure why, when I build from Visual Studio, I'm not getting any of the errors that the buildbots are reporting. I clearly need to investigate the MicroPython build system some more, and figure this out, before this can be merged. |
4e4ffac
to
57df13b
Compare
Add a new header file to define what version of Windows we are targetting, and include that everywhere we include windows.h. Signed-off-by: Jon Foster <jon@jon-foster.co.uk>
Signed-off-by: Jon Foster <jon@jon-foster.co.uk>
ports/windows/modsocket.c: New file, based on ports/unix/modsocket.c. ports/windows/mpconfigport.h: Enable sockets option. ports/windows/variants/manifest.py: Include networking bundle. ports/windows/variants/dev/mpconfigvariant.h: Disable select module. ports/windows/Makefile: Include new modsocket.c file. This is based on the UNIX socket module, with changes to make it compile. This has had almost no testing. It's submitted because it's better than what was there before, which was no network support at all, and the Windows port is experimental. The ntptime module does work, so basic DNS query and UDP connection works. Since it's based on the UNIX socket module, and Windows sockets are mostly compatible, it probably mostly works. But there are probably a few edge-case bugs waiting to be discovered by the unlucky experimenter, or by a keen tester. The "select" module is disabled as it does not work with sockets on Windows. That particular problem is surprisingly hard on Windows, and is not something I care about right now, so is left for a future volunteer. Signed-off-by: Jon Foster <jon@jon-foster.co.uk>
57df13b
to
bcea6c6
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #14162 +/- ##
=======================================
Coverage 98.39% 98.39%
=======================================
Files 161 161
Lines 21200 21200
=======================================
Hits 20860 20860
Misses 340 340 ☔ View full report in Codecov by Sentry. |
OK, it seems to compile now, but there are test failures. The Linux cross compile build seems to be using a very old version of the MS SDK. Some of the identifiers that were introduced in Windows Vista were not being defined by default by the headers there. I fixed that by defining the target Windows version macros before including windows.h. I've included that as a separate commit, since it's a separable thing. I've also broken out the initialisation of WinSock2 into a separate commit. The initialisation is hopefully uncontroversial, and hopefully right. |
Code size report:
|
Did you see #12810 ? Test failures are partly due to tests assuming unix/posix socket error codes. |
@stinos : No, I hadn't seen #12810, thanks for pointing that out! It looks like you've gotten far further than me in getting sockets to work, so I'll stop working on this PR. I would suggest you pull in my first two commits. Consistent definition of target Windows version., and Initialise WinSock2 library at startup.. Good luck getting sockets support landed! |
I don't seem to be needing Yeah I had the initialization in modcocket.c itself but indeed it's probably better to have it it in init.c so I changed that in my PR (plus guarded by MICROPY_PY_SOCKET and added the WSACleanup counterpart as well) |
Thanks for taking the init changes. Regarding the other change... OK, here's the long and complicated explanation of the problems, followed by the simple solution. I may or may not end up making a PR for this - I'm waiting until the sockets PR and my open ntptime PRs get accepted, before I make any more MicroPython PRs. But hopefully this helps explain why you need it. WIN32_LEAN_AND_MEANRegarding
In other words, this file doesn't compile:
But this does compile:
And this does compile, too:
Since programmers routinely add new headers to code they're working on, this problem can pop up with a small change that leads to adding either The thing is, this is all very weird and subtle and complicated. And it fails with weird compile errors, making it awkward to debug unless you know about this problem already. It creates a barrier to entry for people wanting to contribute. So we should do what we can to simplify it. The only sane approach is to make sure _WIN32_WINNTThe MicroPython Windows port has a minimum version of Windows that it supports. For example, it could be that MicroPython supports Windows 8 and later, or Windows 10 and later. Note that even if MicroPython doesn't make a formal decision, there will still be a minimum version of Windows that it supports, it's just that you might not know what that version is, and it might not be documented anywhere, and it might change when someone adds a new MicroPython feature using newer Windows features. So it's better to make a formal decision. Even if you're not sure, I suggest you pick something. You can always change that decision later. I recommend supporting Windows 8 as the minimum, for now. Windows 10 would also be a reasonable choice, but I don't think there are any Windows-10-only APIs that you want to use right now. Older versions of Windows are ancient, no longer supported, and not in common use among the group of developers who might want to run MicroPython on Windows. Once you've made a decision, the Windows headers are designed to help you enforce it. By defining If you don't define Basically, relying on the default for Defining The first problem is that certain Windows structures, e.g. The second problem is it messes up IDEs and debuggers. There's no sane way for the debugger to show that a bit of memory containing a struct is interpreted one way in some files, and a different way in other files. Because no-one deliberately defines structures with different definitions in different files, this is something that debugger and IDE vendors haven't spent any effort on solving. The third problem is it makes refactoring harder, and copying existing code harder. You can't just move or copy code between files, you have to check the The fourth problem is that if you define The fifth problem is that there's really no point defining Again, having different versions of Again, this is all very weird and subtle and complicated. And at best it fails with weird compile errors, making it awkward to debug unless you know about this problem already. At worst it causes incredibly hard-to-find bugs. Either way it creates a barrier to entry for people wanting to contribute. So we should do what we can to simplify it. The only sane approach is to make sure A simple solutionThe problems described above are all very weird and subtle and complicated and hard to debug. They create a barrier to entry for people wanting to contribute. So: I suggest a simple coding style rule that contributors to the Windows port would have to know and follow:
Then As a sanity check,
Note that contributors don't have to understand why that coding style rule exists. We should certainly make documentation - which could be based on this comment - available for those interested in the gory details. But so long as people follow that simple rule, none of the problems described here will occur. |
Ok thanks for the elaborate explanation - all clear. Just a couple of the relevant paragraphs are imo sufficient to understand why things are needed and could make it into the windows_version.h file, like this bit
and also
The only annoying thing left is that mingw might treat things in a different way, but then there's probably a good explanation for that as well. Then wrt
that could als be "If you are need #include <windows.h> instead use #include "ports/windows/windows.h", likewise include that file first before any other windows-specific headers" and ports/windows/windows.h would be like
Advantage being there's only one go-to include which is going to cover the majority of cases in the micropython codebase.
We'll just need to doublecheck none of the external code also defines it then. |
ports/windows/modsocket.c: New file, based on ports/unix/modsocket.c.
ports/windows/init.c: Initialise Windows sockets.
ports/windows/mpconfigport.h: Enable networking and sockets options.
ports/windows/variants/manifest.py: Include networking bundle.
This is based on the UNIX socket module, with changes to make it compile.
This has had almost no testing. It's submitted because it's better than what was there before, which was no network support at all, and the Windows port is experimental. The ntptime module does work, so basic DNS query and UDP connection works. Since it's based on the UNIX socket module, and Windows sockets are mostly compatible, it probably mostly works. But there are probably a few edge-case bugs waiting to be discovered by the unlucky experimenter, or by a keen tester.