Commit add74427b9

Elaine Gibson <ypsvlq@gmail.com>
2024-03-23 09:03:41
mingw: support -municode
1 parent 71d878b
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);
+}
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"
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 => "",
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=",
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.
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 {
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",
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{};