-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Make entry points/inferred Windows subsystem conform better with conventions #25861
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
base: master
Are you sure you want to change the base?
Conversation
…entions Previously, start.zig would always export wWinMainCRTStartup as the entry symbol, regardless of whether `main` or `wWinMain` was used as the main. This meant that the linker was unable to differentiate between main/wWinMain and so anything with wWinMainCRTStartup would get the `.console` subsystem inferred. In other words, the added test would fail for `winmain_inferred` as it would have the `.console` subsystem instead of the expected `.windows` subsystem. This commit changes the relevant logic: - Only export wWinMainCRTStartup when using wWinMain - Export wmainCRTStartup for non-wWinMain main functions when libc is not linked - When libc is linked, then the libc runtime entry point is used and `main` is exported (this part hasn't changed) - Infer `.windows` subsystem when exporting WinMainCRTStartup/wWinMainCRTStartup/WinMain/wWinMain - Infer `.console` subsystem when exporting main/mainCRTStartup/wmainCRTStartup This is a breaking change in the sense that a compiler built before this commit will be unable to compile a non-wWinMain exe using the updated `start.zig`. This is because the previous code did not look for mainCRTStartup/wmainCRTStartup at all, so it'd fall back to assuming the entry point is wWinMainCRTStartup which is no longer exported when using a normal main and therefore hit `error: lld-link: <root>: undefined symbol: wWinMainCRTStartup`
adf827e to
f9b8da3
Compare
|
I've not invested any time into investigating this and am mainly going off quickly reading the MSVC linker docs, but I'm wondering if the way Zig decides the subsystem and entry point is correct:
I also found this blog post from Raymond Chen: https://devblogs.microsoft.com/oldnewthing/20241004-00/?p=110338
This reads to me that if no subsystem is specified by the user, it should be Then, if the resolved subsystem is Also, from a quick test, the MSVC linker behavior seems to be to fail the link with |
| !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup")) | ||
| { | ||
| @export(&WinStartup, .{ .name = "wWinMainCRTStartup" }); | ||
| @export(&WinStartup, .{ .name = "wmainCRTStartup" }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if always exporting the default Zig main as wmainCRTStartup might be a problem in some instances. If the user does zig build-exe foo.zig --subsystem windows, linking would fail under the MSVC linker behavior laid out in my above comment.
Is it possible to export the same symbol under two names, wmainCRTStartup and wWinMainCRTStartup, without any negative side effects? This way it would work regardless of which subsystem is specified at the final link.
|
Yeah, the "subsystem determines the entry point" thing of the MSVC tooling is something we discussed here and that I promptly forgot about. Will have to think more about this. A framing that might be helpful is thinking about "what do we want to work?" and let the behavior be dictated by that, i.e. stuff like:
|
Previously, start.zig would always export wWinMainCRTStartup as the entry symbol, regardless of whether
mainorwWinMainwas used as the main. This meant that the linker was unable to differentiate between main/wWinMain and so anything with wWinMainCRTStartup would get the.consolesubsystem inferred. In other words, the added test would fail forwinmain_inferredas it would have the.consolesubsystem instead of the expected.windowssubsystem.This commit changes the relevant logic:
mainis exported (this part hasn't changed).windowssubsystem when exporting WinMainCRTStartup/wWinMainCRTStartup/WinMain/wWinMain.consolesubsystem when exporting main/mainCRTStartup/wmainCRTStartupThis is a breaking change in the sense that a compiler built before this commit will be unable to compile a non-wWinMain exe using the updated
start.zig. This is because the previous code did not look for mainCRTStartup/wmainCRTStartup at all, so it'd fall back to assuming the entry point is wWinMainCRTStartup which is no longer exported when using a normal main and therefore hiterror: lld-link: <root>: undefined symbol: wWinMainCRTStartupThese are some changes I had sitting around from the time of #17808 that I've updated and added a standalone test for. Ultimately this is some fairly minor convenience stuff that mostly allows users to not have to specify
subsystemexplicitly when definingwWinMain, so the breaking nature of this change may not be worth it.cc @castholm