authorgravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2025-11-08 01:39:15-08:00
committergravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2025-11-08 17:11:12-08:00
logb31a03f134792b8fae20a625f68499c6548f8443
treead42b9f6811ab64efc449cb2fdcdb05868e3128b
parentbe4eaed7c41fb194014d862648ff586797e39e84

Let CRT take care of the entry point for wWinMain if libc is linked

Fixes #7852 Before, the modified test would fail with: ``` error: lld-link: undefined symbol: wWinMain note: referenced by C:\Users\Ryan\Programming\Zig\zig-x86_64-windows-0.15.1\lib\libc\mingw\crt\crtexewin.c:66 note: libmingw32.lib(ucrtexewin.obj):(wmain) ```

4 files changed, 90 insertions(+), 0 deletions(-)

lib/std/start.zig+8
...@@ -61,6 +61,10 @@ comptime {...@@ -61,6 +61,10 @@ comptime {
61 } else if (!@typeInfo(@TypeOf(root.main)).@"fn".calling_convention.eql(.c)) {61 } else if (!@typeInfo(@TypeOf(root.main)).@"fn".calling_convention.eql(.c)) {
62 @export(&main, .{ .name = "main" });62 @export(&main, .{ .name = "main" });
63 }63 }
64 } else if (native_os == .windows and builtin.link_libc and @hasDecl(root, "wWinMain")) {
65 if (!@typeInfo(@TypeOf(root.wWinMain)).@"fn".calling_convention.eql(.c)) {
66 @export(&wWinMain, .{ .name = "wWinMain" });
67 }
64 } else if (native_os == .windows) {68 } else if (native_os == .windows) {
65 if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and69 if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and
66 !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup"))70 !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup"))
...@@ -527,6 +531,10 @@ fn wWinMainCRTStartup() callconv(.withStackAlign(.c, 1)) noreturn {...@@ -527,6 +531,10 @@ fn wWinMainCRTStartup() callconv(.withStackAlign(.c, 1)) noreturn {
527 std.os.windows.ntdll.RtlExitUserProcess(@as(std.os.windows.UINT, @bitCast(result)));531 std.os.windows.ntdll.RtlExitUserProcess(@as(std.os.windows.UINT, @bitCast(result)));
528}532}
529533
534fn wWinMain(hInstance: *anyopaque, hPrevInstance: ?*anyopaque, pCmdLine: [*:0]u16, nCmdShow: c_int) callconv(.c) c_int {
535 return root.wWinMain(@ptrCast(hInstance), @ptrCast(hPrevInstance), pCmdLine, @intCast(nCmdShow));
536}
537
530fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn {538fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn {
531 // We're not ready to panic until thread local storage is initialized.539 // We're not ready to panic until thread local storage is initialized.
532 @setRuntimeSafety(false);540 @setRuntimeSafety(false);
test/standalone/windows_entry_points/build.zig+62
...@@ -77,4 +77,66 @@ pub fn build(b: *std.Build) void {...@@ -77,4 +77,66 @@ pub fn build(b: *std.Build) void {
77 _ = exe.getEmittedBin();77 _ = exe.getEmittedBin();
78 test_step.dependOn(&exe.step);78 test_step.dependOn(&exe.step);
79 }79 }
80
81 {
82 const exe = b.addExecutable(.{
83 .name = "zig_main",
84 .root_module = b.createModule(.{
85 .root_source_file = b.path("main.zig"),
86 .target = target,
87 .optimize = .Debug,
88 }),
89 });
90
91 _ = exe.getEmittedBin();
92 test_step.dependOn(&exe.step);
93 }
94
95 {
96 const exe = b.addExecutable(.{
97 .name = "zig_main_link_libc",
98 .root_module = b.createModule(.{
99 .root_source_file = b.path("main.zig"),
100 .target = target,
101 .optimize = .Debug,
102 .link_libc = true,
103 }),
104 });
105
106 _ = exe.getEmittedBin();
107 test_step.dependOn(&exe.step);
108 }
109
110 {
111 const exe = b.addExecutable(.{
112 .name = "zig_wwinmain",
113 .root_module = b.createModule(.{
114 .root_source_file = b.path("wwinmain.zig"),
115 .target = target,
116 .optimize = .Debug,
117 }),
118 });
119 exe.mingw_unicode_entry_point = true;
120 // Note: `exe.subsystem = .windows;` is not necessary
121
122 _ = exe.getEmittedBin();
123 test_step.dependOn(&exe.step);
124 }
125
126 {
127 const exe = b.addExecutable(.{
128 .name = "zig_wwinmain_link_libc",
129 .root_module = b.createModule(.{
130 .root_source_file = b.path("wwinmain.zig"),
131 .target = target,
132 .optimize = .Debug,
133 .link_libc = true,
134 }),
135 });
136 exe.mingw_unicode_entry_point = true;
137 // Note: `exe.subsystem = .windows;` is not necessary
138
139 _ = exe.getEmittedBin();
140 test_step.dependOn(&exe.step);
141 }
80}142}
test/standalone/windows_entry_points/main.zig created+5
...@@ -0,0 +1,5 @@
1const std = @import("std");
2
3pub fn main() void {
4 std.debug.print("hello from Zig main\n", .{});
5}
test/standalone/windows_entry_points/wwinmain.zig created+15
...@@ -0,0 +1,15 @@
1const std = @import("std");
2
3pub fn wWinMain(
4 inst: std.os.windows.HINSTANCE,
5 prev: ?std.os.windows.HINSTANCE,
6 cmd_line: std.os.windows.LPWSTR,
7 cmd_show: c_int,
8) std.os.windows.INT {
9 _ = inst;
10 _ = prev;
11 _ = cmd_line;
12 _ = cmd_show;
13 std.debug.print("hello from Zig wWinMain\n", .{});
14 return 0;
15}