aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/libc/mingw/crt/crtexewin.c68
-rw-r--r--lib/libc/mingw/crt/ucrtexewin.c14
-rw-r--r--lib/std/Build/Step/Compile.zig7
-rw-r--r--src/Compilation.zig7
-rw-r--r--src/clang_options_data.zig9
-rw-r--r--src/link/Coff/lld.zig2
-rw-r--r--src/main.zig7
-rw-r--r--src/mingw.zig40
-rw-r--r--test/standalone.zig4
-rw-r--r--test/standalone/windows_entry_points/build.zig68
-rw-r--r--test/standalone/windows_entry_points/main.c6
-rw-r--r--test/standalone/windows_entry_points/winmain.c7
-rw-r--r--test/standalone/windows_entry_points/wmain.c7
-rw-r--r--test/standalone/windows_entry_points/wwinmain.c7
-rw-r--r--tools/update_clang_options.zig4
15 files changed, 231 insertions, 26 deletions
diff --git a/lib/libc/mingw/crt/crtexewin.c b/lib/libc/mingw/crt/crtexewin.c
new file mode 100644
index 0000000000..26179fa905
--- /dev/null
+++ b/lib/libc/mingw/crt/crtexewin.c
@@ -0,0 +1,68 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+#include <windows.h>
+#include <tchar.h>
+#include <corecrt_startup.h>
+
+#ifndef _UNICODE
+#include <mbctype.h>
+#endif
+
+#define SPACECHAR _T(' ')
+#define DQUOTECHAR _T('\"')
+
+extern IMAGE_DOS_HEADER __ImageBase;
+
+int _tmain (int, _TCHAR **, _TCHAR **);
+int _tmain (int __UNUSED_PARAM(argc),
+ _TCHAR ** __UNUSED_PARAM(argv),
+ _TCHAR ** __UNUSED_PARAM(envp))
+{
+ HINSTANCE hInstance;
+ _TCHAR *lpCmdLine;
+ DWORD nShowCmd;
+
+ hInstance = (HINSTANCE) &__ImageBase;
+
+#ifdef _UNICODE
+ lpCmdLine = _wcmdln;
+#else
+ lpCmdLine = _acmdln;
+#endif
+ if (lpCmdLine)
+ {
+ BOOL inDoubleQuote = FALSE;
+ while (*lpCmdLine > SPACECHAR || (*lpCmdLine && inDoubleQuote))
+ {
+ if (*lpCmdLine == DQUOTECHAR)
+ inDoubleQuote = !inDoubleQuote;
+#ifndef _UNICODE
+ if (_ismbblead (*lpCmdLine))
+ {
+ if (lpCmdLine[1])
+ ++lpCmdLine;
+ }
+#endif
+ ++lpCmdLine;
+ }
+ while (*lpCmdLine && (*lpCmdLine <= SPACECHAR))
+ lpCmdLine++;
+ }
+ else
+ lpCmdLine = _TEXT("");
+
+ {
+ STARTUPINFO StartupInfo;
+ memset (&StartupInfo, 0, sizeof (STARTUPINFO));
+ GetStartupInfo (&StartupInfo);
+ if (StartupInfo.dwFlags & STARTF_USESHOWWINDOW)
+ nShowCmd = StartupInfo.wShowWindow;
+ else
+ nShowCmd = SW_SHOWDEFAULT;
+ }
+
+ return _tWinMain (hInstance, NULL, lpCmdLine, nShowCmd);
+}
diff --git a/lib/libc/mingw/crt/ucrtexewin.c b/lib/libc/mingw/crt/ucrtexewin.c
new file mode 100644
index 0000000000..e3b7d4ddc2
--- /dev/null
+++ b/lib/libc/mingw/crt/ucrtexewin.c
@@ -0,0 +1,14 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+
+#ifndef UNICODE
+#define UNICODE
+#endif
+#ifndef _UNICODE
+#define _UNICODE
+#endif
+
+#include "crtexewin.c"
diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig
index 75f01dbf5e..9c1354fd30 100644
--- a/lib/std/Build/Step/Compile.zig
+++ b/lib/std/Build/Step/Compile.zig
@@ -161,6 +161,9 @@ dll_export_fns: ?bool = null,
subsystem: ?std.Target.SubSystem = null,
+/// (Windows) When targeting the MinGW ABI, use the unicode entry point (wmain/wWinMain)
+mingw_unicode_entry_point: bool = false,
+
/// How the linker must handle the entry point of the executable.
entry: Entry = .default,
@@ -1583,6 +1586,10 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
});
}
+ if (self.mingw_unicode_entry_point) {
+ try zig_args.append("-municode");
+ }
+
if (self.error_limit) |err_limit| try zig_args.appendSlice(&.{
"--error-limit",
b.fmt("{}", .{err_limit}),
diff --git a/src/Compilation.zig b/src/Compilation.zig
index 460a1e5d9e..5a6e02d400 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -173,6 +173,7 @@ global_cache_directory: Directory,
libc_include_dir_list: []const []const u8,
libc_framework_dir_list: []const []const u8,
rc_includes: RcIncludes,
+mingw_unicode_entry_point: bool,
thread_pool: *ThreadPool,
/// Populated when we build the libc++ static library. A Job to build this is placed in the queue
@@ -758,7 +759,7 @@ pub const MiscTask = enum {
@"mingw-w64 crt2.o",
@"mingw-w64 dllcrt2.o",
- @"mingw-w64 mingwex.lib",
+ @"mingw-w64 mingw32.lib",
};
pub const MiscError = struct {
@@ -1101,6 +1102,7 @@ pub const CreateOptions = struct {
test_name_prefix: ?[]const u8 = null,
test_runner_path: ?[]const u8 = null,
subsystem: ?std.Target.SubSystem = null,
+ mingw_unicode_entry_point: bool = false,
/// (Zig compiler development) Enable dumping linker's state as JSON.
enable_link_snapshots: bool = false,
/// (Darwin) Install name of the dylib
@@ -1427,6 +1429,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
.libc_include_dir_list = libc_dirs.libc_include_dir_list,
.libc_framework_dir_list = libc_dirs.libc_framework_dir_list,
.rc_includes = options.rc_includes,
+ .mingw_unicode_entry_point = options.mingw_unicode_entry_point,
.thread_pool = options.thread_pool,
.clang_passthrough_mode = options.clang_passthrough_mode,
.clang_preprocessor_mode = options.clang_preprocessor_mode,
@@ -1768,7 +1771,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
const crt_job: Job = .{ .mingw_crt_file = if (is_dyn_lib) .dllcrt2_o else .crt2_o };
try comp.work_queue.ensureUnusedCapacity(2);
- comp.work_queue.writeItemAssumeCapacity(.{ .mingw_crt_file = .mingwex_lib });
+ comp.work_queue.writeItemAssumeCapacity(.{ .mingw_crt_file = .mingw32_lib });
comp.work_queue.writeItemAssumeCapacity(crt_job);
// When linking mingw-w64 there are some import libs we always need.
diff --git a/src/clang_options_data.zig b/src/clang_options_data.zig
index 0137d2cbfc..0d5bab676c 100644
--- a/src/clang_options_data.zig
+++ b/src/clang_options_data.zig
@@ -6895,7 +6895,14 @@ joinpd1("mdouble="),
joinpd1("mfpmath="),
joinpd1("mhwmult="),
joinpd1("mthreads"),
-joinpd1("municode"),
+.{
+ .name = "municode",
+ .syntax = .joined,
+ .zig_equivalent = .mingw_unicode_entry_point,
+ .pd1 = true,
+ .pd2 = false,
+ .psl = false,
+},
joinpd1("mwindows"),
.{
.name = "offload=",
diff --git a/src/link/Coff/lld.zig b/src/link/Coff/lld.zig
index 1543415d0e..cf9c06a70f 100644
--- a/src/link/Coff/lld.zig
+++ b/src/link/Coff/lld.zig
@@ -409,7 +409,7 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, prog_node: *std.Progress.Node)
try argv.append(try comp.get_libc_crt_file(arena, "crt2.obj"));
}
- try argv.append(try comp.get_libc_crt_file(arena, "mingwex.lib"));
+ try argv.append(try comp.get_libc_crt_file(arena, "mingw32.lib"));
} else {
const lib_str = switch (comp.config.link_mode) {
.dynamic => "",
diff --git a/src/main.zig b/src/main.zig
index c60cc100ab..2edc3864c6 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -450,6 +450,7 @@ const usage_build_generic =
\\ -fstructured-cfg (SPIR-V) force SPIR-V kernels to use structured control flow
\\ -fno-structured-cfg (SPIR-V) force SPIR-V kernels to not use structured control flow
\\ -mexec-model=[value] (WASI) Execution model
+ \\ -municode (Windows) Use wmain/wWinMain as entry point
\\
\\Per-Module Compile Options:
\\ -target [name] <arch><sub>-<os>-<abi> see the targets command
@@ -893,6 +894,7 @@ fn buildOutputType(
var subsystem: ?std.Target.SubSystem = null;
var major_subsystem_version: ?u16 = null;
var minor_subsystem_version: ?u16 = null;
+ var mingw_unicode_entry_point: bool = false;
var enable_link_snapshots: bool = false;
var debug_incremental: bool = false;
var install_name: ?[]const u8 = null;
@@ -1686,6 +1688,8 @@ fn buildOutputType(
}
} else if (mem.startsWith(u8, arg, "-mexec-model=")) {
create_module.opts.wasi_exec_model = parseWasiExecModel(arg["-mexec-model=".len..]);
+ } else if (mem.eql(u8, arg, "-municode")) {
+ mingw_unicode_entry_point = true;
} else {
fatal("unrecognized parameter: '{s}'", .{arg});
}
@@ -2091,6 +2095,7 @@ fn buildOutputType(
try force_undefined_symbols.put(arena, it.only_arg, {});
},
.force_load_objc => force_load_objc = true,
+ .mingw_unicode_entry_point => mingw_unicode_entry_point = true,
.weak_library => try create_module.system_libs.put(arena, it.only_arg, .{
.needed = false,
.weak = true,
@@ -3229,6 +3234,7 @@ fn buildOutputType(
.rc_source_files = create_module.rc_source_files.items,
.manifest_file = manifest_file,
.rc_includes = rc_includes,
+ .mingw_unicode_entry_point = mingw_unicode_entry_point,
.link_objects = create_module.link_objects.items,
.framework_dirs = create_module.framework_dirs.items,
.frameworks = resolved_frameworks.items,
@@ -5792,6 +5798,7 @@ pub const ClangArgIterator = struct {
install_name,
undefined,
force_load_objc,
+ mingw_unicode_entry_point,
};
const Args = struct {
diff --git a/src/mingw.zig b/src/mingw.zig
index b711ad7515..803c0f9367 100644
--- a/src/mingw.zig
+++ b/src/mingw.zig
@@ -13,7 +13,7 @@ const Cache = std.Build.Cache;
pub const CRTFile = enum {
crt2_o,
dllcrt2_o,
- mingwex_lib,
+ mingw32_lib,
};
pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progress.Node) !void {
@@ -28,14 +28,9 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr
.crt2_o => {
var args = std.ArrayList([]const u8).init(arena);
try add_cc_args(comp, arena, &args);
- try args.appendSlice(&[_][]const u8{
- // Prevents warning: 'used' attribute ignored on a non-definition declaration
- // pointing at extern _CRTALLOC
- "-Wno-ignored-attributes",
- // Uncommenting this makes mingw-w64 look for wmain instead of main.
- //"-DUNICODE",
- //"-D_UNICODE",
- });
+ if (comp.mingw_unicode_entry_point) {
+ try args.appendSlice(&.{ "-DUNICODE", "-D_UNICODE" });
+ }
var files = [_]Compilation.CSourceFile{
.{
.src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
@@ -63,12 +58,12 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr
return comp.build_crt_file("dllcrt2", .Obj, .@"mingw-w64 dllcrt2.o", prog_node, &files);
},
- .mingwex_lib => {
+ .mingw32_lib => {
var args = std.ArrayList([]const u8).init(arena);
try add_cc_args(comp, arena, &args);
var c_source_files = std.ArrayList(Compilation.CSourceFile).init(arena);
- for (mingwex_generic_src) |dep| {
+ for (mingw32_generic_src) |dep| {
try c_source_files.append(.{
.src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
"libc", "mingw", dep,
@@ -79,7 +74,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr
}
const target = comp.getTarget();
if (target.cpu.arch == .x86 or target.cpu.arch == .x86_64) {
- for (mingwex_x86_src) |dep| {
+ for (mingw32_x86_src) |dep| {
try c_source_files.append(.{
.src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
"libc", "mingw", dep,
@@ -89,7 +84,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr
});
}
if (target.cpu.arch == .x86) {
- for (mingwex_x86_32_src) |dep| {
+ for (mingw32_x86_32_src) |dep| {
try c_source_files.append(.{
.src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
"libc", "mingw", dep,
@@ -100,7 +95,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr
}
}
} else if (target.cpu.arch.isARM()) {
- for (mingwex_arm32_src) |dep| {
+ for (mingw32_arm32_src) |dep| {
try c_source_files.append(.{
.src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
"libc", "mingw", dep,
@@ -110,7 +105,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr
});
}
} else if (target.cpu.arch.isAARCH64()) {
- for (mingwex_arm64_src) |dep| {
+ for (mingw32_arm64_src) |dep| {
try c_source_files.append(.{
.src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
"libc", "mingw", dep,
@@ -122,7 +117,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr
} else {
@panic("unsupported arch");
}
- return comp.build_crt_file("mingwex", .Lib, .@"mingw-w64 mingwex.lib", prog_node, c_source_files.items);
+ return comp.build_crt_file("mingw32", .Lib, .@"mingw-w64 mingw32.lib", prog_node, c_source_files.items);
},
}
}
@@ -389,14 +384,16 @@ fn findDef(
return error.FileNotFound;
}
-const mingwex_generic_src = [_][]const u8{
+const mingw32_generic_src = [_][]const u8{
// mingw32
+ "crt" ++ path.sep_str ++ "crtexewin.c",
"crt" ++ path.sep_str ++ "dll_argv.c",
"crt" ++ path.sep_str ++ "gccmain.c",
"crt" ++ path.sep_str ++ "natstart.c",
"crt" ++ path.sep_str ++ "pseudo-reloc-list.c",
"crt" ++ path.sep_str ++ "wildcard.c",
"crt" ++ path.sep_str ++ "charmax.c",
+ "crt" ++ path.sep_str ++ "ucrtexewin.c",
"crt" ++ path.sep_str ++ "dllargv.c",
"crt" ++ path.sep_str ++ "_newmode.c",
"crt" ++ path.sep_str ++ "tlssup.c",
@@ -814,7 +811,7 @@ const mingwex_generic_src = [_][]const u8{
"libsrc" ++ path.sep_str ++ "activeds-uuid.c",
};
-const mingwex_x86_src = [_][]const u8{
+const mingw32_x86_src = [_][]const u8{
// mingwex
"math" ++ path.sep_str ++ "cbrtl.c",
"math" ++ path.sep_str ++ "erfl.c",
@@ -873,8 +870,7 @@ const mingwex_x86_src = [_][]const u8{
"math" ++ path.sep_str ++ "nexttowardf.c",
};
-const mingwex_x86_32_src = [_][]const u8{
- // ucrtbase
+const mingw32_x86_32_src = [_][]const u8{
"math" ++ path.sep_str ++ "coshf.c",
"math" ++ path.sep_str ++ "expf.c",
"math" ++ path.sep_str ++ "log10f.c",
@@ -896,7 +892,7 @@ const mingwex_x86_32_src = [_][]const u8{
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "tanf.c",
};
-const mingwex_arm32_src = [_][]const u8{
+const mingw32_arm32_src = [_][]const u8{
"math" ++ path.sep_str ++ "arm-common" ++ path.sep_str ++ "ldexpl.c",
"math" ++ path.sep_str ++ "arm" ++ path.sep_str ++ "_chgsignl.S",
"math" ++ path.sep_str ++ "arm" ++ path.sep_str ++ "s_rint.c",
@@ -905,7 +901,7 @@ const mingwex_arm32_src = [_][]const u8{
"math" ++ path.sep_str ++ "arm" ++ path.sep_str ++ "sincosf.S",
};
-const mingwex_arm64_src = [_][]const u8{
+const mingw32_arm64_src = [_][]const u8{
"math" ++ path.sep_str ++ "arm-common" ++ path.sep_str ++ "ldexpl.c",
"math" ++ path.sep_str ++ "arm64" ++ path.sep_str ++ "_chgsignl.S",
"math" ++ path.sep_str ++ "arm64" ++ path.sep_str ++ "rint.c",
diff --git a/test/standalone.zig b/test/standalone.zig
index c8158364e2..495468eb24 100644
--- a/test/standalone.zig
+++ b/test/standalone.zig
@@ -196,6 +196,10 @@ pub const build_cases = [_]BuildCase{
.import = @import("standalone/windows_resources/build.zig"),
},
.{
+ .build_root = "test/standalone/windows_entry_points",
+ .import = @import("standalone/windows_entry_points/build.zig"),
+ },
+ .{
.build_root = "test/standalone/windows_spawn",
.import = @import("standalone/windows_spawn/build.zig"),
},
diff --git a/test/standalone/windows_entry_points/build.zig b/test/standalone/windows_entry_points/build.zig
new file mode 100644
index 0000000000..25c4839147
--- /dev/null
+++ b/test/standalone/windows_entry_points/build.zig
@@ -0,0 +1,68 @@
+const std = @import("std");
+
+pub fn build(b: *std.Build) void {
+ const test_step = b.step("test", "Test it");
+ b.default_step = test_step;
+
+ const target = b.resolveTargetQuery(.{
+ .cpu_arch = .x86_64,
+ .os_tag = .windows,
+ .abi = .gnu,
+ });
+
+ {
+ const exe = b.addExecutable(.{
+ .name = "main",
+ .target = target,
+ .optimize = .Debug,
+ .link_libc = true,
+ });
+ exe.addCSourceFile(.{ .file = .{ .path = "main.c" } });
+
+ _ = exe.getEmittedBin();
+ test_step.dependOn(&exe.step);
+ }
+
+ {
+ const exe = b.addExecutable(.{
+ .name = "wmain",
+ .target = target,
+ .optimize = .Debug,
+ .link_libc = true,
+ });
+ exe.mingw_unicode_entry_point = true;
+ exe.addCSourceFile(.{ .file = .{ .path = "wmain.c" } });
+
+ _ = exe.getEmittedBin();
+ test_step.dependOn(&exe.step);
+ }
+
+ {
+ const exe = b.addExecutable(.{
+ .name = "winmain",
+ .target = target,
+ .optimize = .Debug,
+ .link_libc = true,
+ });
+ // Note: `exe.subsystem = .Windows;` is not necessary
+ exe.addCSourceFile(.{ .file = .{ .path = "winmain.c" } });
+
+ _ = exe.getEmittedBin();
+ test_step.dependOn(&exe.step);
+ }
+
+ {
+ const exe = b.addExecutable(.{
+ .name = "wwinmain",
+ .target = target,
+ .optimize = .Debug,
+ .link_libc = true,
+ });
+ exe.mingw_unicode_entry_point = true;
+ // Note: `exe.subsystem = .Windows;` is not necessary
+ exe.addCSourceFile(.{ .file = .{ .path = "wwinmain.c" } });
+
+ _ = exe.getEmittedBin();
+ test_step.dependOn(&exe.step);
+ }
+}
diff --git a/test/standalone/windows_entry_points/main.c b/test/standalone/windows_entry_points/main.c
new file mode 100644
index 0000000000..1e47eefae0
--- /dev/null
+++ b/test/standalone/windows_entry_points/main.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int main(int argc, char *argv[ ], char *envp[ ]) {
+ printf("hello from main\n");
+ return 0;
+} \ No newline at end of file
diff --git a/test/standalone/windows_entry_points/winmain.c b/test/standalone/windows_entry_points/winmain.c
new file mode 100644
index 0000000000..c5c0de2434
--- /dev/null
+++ b/test/standalone/windows_entry_points/winmain.c
@@ -0,0 +1,7 @@
+#include <windows.h>
+#include <stdio.h>
+
+int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, PSTR cmdline, int cmdshow) {
+ printf("hello from WinMain\n");
+ return 0;
+} \ No newline at end of file
diff --git a/test/standalone/windows_entry_points/wmain.c b/test/standalone/windows_entry_points/wmain.c
new file mode 100644
index 0000000000..41ec522c57
--- /dev/null
+++ b/test/standalone/windows_entry_points/wmain.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include <windows.h>
+
+int wmain(int argc, wchar_t *argv[ ], wchar_t *envp[ ]) {
+ printf("hello from wmain\n");
+ return 0;
+} \ No newline at end of file
diff --git a/test/standalone/windows_entry_points/wwinmain.c b/test/standalone/windows_entry_points/wwinmain.c
new file mode 100644
index 0000000000..7bf97bfae3
--- /dev/null
+++ b/test/standalone/windows_entry_points/wwinmain.c
@@ -0,0 +1,7 @@
+#include <windows.h>
+#include <stdio.h>
+
+int APIENTRY wWinMain(HINSTANCE hInst, HINSTANCE hInstPrev, PWSTR cmdline, int cmdshow) {
+ printf("hello from wWinMain\n");
+ return 0;
+} \ No newline at end of file
diff --git a/tools/update_clang_options.zig b/tools/update_clang_options.zig
index e632e18854..8031e6dcdb 100644
--- a/tools/update_clang_options.zig
+++ b/tools/update_clang_options.zig
@@ -532,6 +532,10 @@ const known_options = [_]KnownOpt{
.name = "ObjC",
.ident = "force_load_objc",
},
+ .{
+ .name = "municode",
+ .ident = "mingw_unicode_entry_point",
+ },
};
const blacklisted_options = [_][]const u8{};