Commit 54f2a7c833

Carl Åstholm <carl@astholm.se>
2025-09-05 17:50:46
Move `std.Target.SubSystem` to `std.zig.Subsystem`
Also updates the field names to conform with the rest of std.
1 parent 075d300
Changed files (9)
lib
src
test
standalone
issue_5825
windows_entry_points
lib/std/Build/Step/Compile.zig
@@ -171,7 +171,7 @@ lto: ?std.zig.LtoMode = null,
 
 dll_export_fns: ?bool = null,
 
-subsystem: ?std.Target.SubSystem = null,
+subsystem: ?std.zig.Subsystem = null,
 
 /// (Windows) When targeting the MinGW ABI, use the unicode entry point (wmain/wWinMain)
 mingw_unicode_entry_point: bool = false,
@@ -1764,16 +1764,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
 
     if (compile.subsystem) |subsystem| {
         try zig_args.append("--subsystem");
-        try zig_args.append(switch (subsystem) {
-            .Console => "console",
-            .Windows => "windows",
-            .Posix => "posix",
-            .Native => "native",
-            .EfiApplication => "efi_application",
-            .EfiBootServiceDriver => "efi_boot_service_driver",
-            .EfiRom => "efi_rom",
-            .EfiRuntimeDriver => "efi_runtime_driver",
-        });
+        try zig_args.append(@tagName(subsystem));
     }
 
     if (compile.mingw_unicode_entry_point) {
lib/std/Target.zig
@@ -1138,16 +1138,8 @@ pub fn toCoffMachine(target: *const Target) std.coff.IMAGE.FILE.MACHINE {
     };
 }
 
-pub const SubSystem = enum {
-    Console,
-    Windows,
-    Posix,
-    Native,
-    EfiApplication,
-    EfiBootServiceDriver,
-    EfiRom,
-    EfiRuntimeDriver,
-};
+/// Deprecated; use 'std.zig.Subsystem' instead. To be removed after 0.16.0 is tagged.
+pub const SubSystem = std.zig.Subsystem;
 
 pub const Cpu = struct {
     /// Architecture
lib/std/zig.zig
@@ -349,6 +349,34 @@ pub const BuildId = union(enum) {
 
 pub const LtoMode = enum { none, full, thin };
 
+pub const Subsystem = enum {
+    console,
+    windows,
+    posix,
+    native,
+    efi_application,
+    efi_boot_service_driver,
+    efi_rom,
+    efi_runtime_driver,
+
+    /// Deprecated; use '.console' instead. To be removed after 0.16.0 is tagged.
+    pub const Console: Subsystem = .console;
+    /// Deprecated; use '.windows' instead. To be removed after 0.16.0 is tagged.
+    pub const Windows: Subsystem = .windows;
+    /// Deprecated; use '.posix' instead. To be removed after 0.16.0 is tagged.
+    pub const Posix: Subsystem = .posix;
+    /// Deprecated; use '.native' instead. To be removed after 0.16.0 is tagged.
+    pub const Native: Subsystem = .native;
+    /// Deprecated; use '.efi_application' instead. To be removed after 0.16.0 is tagged.
+    pub const EfiApplication: Subsystem = .efi_application;
+    /// Deprecated; use '.efi_boot_service_driver' instead. To be removed after 0.16.0 is tagged.
+    pub const EfiBootServiceDriver: Subsystem = .efi_boot_service_driver;
+    /// Deprecated; use '.efi_rom' instead. To be removed after 0.16.0 is tagged.
+    pub const EfiRom: Subsystem = .efi_rom;
+    /// Deprecated; use '.efi_runtime_driver' instead. To be removed after 0.16.0 is tagged.
+    pub const EfiRuntimeDriver: Subsystem = .efi_runtime_driver;
+};
+
 /// Renders a `std.Target.Cpu` value into a textual representation that can be parsed
 /// via the `-mcpu` flag passed to the Zig compiler.
 /// Appends the result to `buffer`.
src/link/Lld.zig
@@ -19,7 +19,7 @@ const Coff = struct {
     minor_subsystem_version: u16,
     lib_directories: []const Cache.Directory,
     module_definition_file: ?[]const u8,
-    subsystem: ?std.Target.SubSystem,
+    subsystem: ?std.zig.Subsystem,
     /// These flags are populated by `codegen.llvm.updateExports` to allow us to guess the subsystem.
     lld_export_flags: struct {
         c_main: bool,
@@ -554,7 +554,7 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {
             try argv.append(try allocPrint(arena, "-DEF:{s}", .{def}));
         }
 
-        const resolved_subsystem: ?std.Target.SubSystem = blk: {
+        const resolved_subsystem: ?std.zig.Subsystem = blk: {
             if (coff.subsystem) |explicit| break :blk explicit;
             switch (target.os.tag) {
                 .windows => {
@@ -565,13 +565,13 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {
                             coff.lld_export_flags.winmain_crt_startup or
                             coff.lld_export_flags.wwinmain_crt_startup)
                         {
-                            break :blk .Console;
+                            break :blk .console;
                         }
                         if (coff.lld_export_flags.winmain or coff.lld_export_flags.wwinmain)
-                            break :blk .Windows;
+                            break :blk .windows;
                     }
                 },
-                .uefi => break :blk .EfiApplication,
+                .uefi => break :blk .efi_application,
                 else => {},
             }
             break :blk null;
@@ -580,60 +580,23 @@ fn coffLink(lld: *Lld, arena: Allocator) !void {
         const Mode = enum { uefi, win32 };
         const mode: Mode = mode: {
             if (resolved_subsystem) |subsystem| {
-                const subsystem_suffix = try allocPrint(arena, ",{d}.{d}", .{
-                    coff.major_subsystem_version, coff.minor_subsystem_version,
-                });
-
-                switch (subsystem) {
-                    .Console => {
-                        try argv.append(try allocPrint(arena, "-SUBSYSTEM:console{s}", .{
-                            subsystem_suffix,
-                        }));
-                        break :mode .win32;
-                    },
-                    .EfiApplication => {
-                        try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_application{s}", .{
-                            subsystem_suffix,
-                        }));
-                        break :mode .uefi;
-                    },
-                    .EfiBootServiceDriver => {
-                        try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_boot_service_driver{s}", .{
-                            subsystem_suffix,
-                        }));
-                        break :mode .uefi;
-                    },
-                    .EfiRom => {
-                        try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_rom{s}", .{
-                            subsystem_suffix,
-                        }));
-                        break :mode .uefi;
-                    },
-                    .EfiRuntimeDriver => {
-                        try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_runtime_driver{s}", .{
-                            subsystem_suffix,
-                        }));
-                        break :mode .uefi;
-                    },
-                    .Native => {
-                        try argv.append(try allocPrint(arena, "-SUBSYSTEM:native{s}", .{
-                            subsystem_suffix,
-                        }));
-                        break :mode .win32;
-                    },
-                    .Posix => {
-                        try argv.append(try allocPrint(arena, "-SUBSYSTEM:posix{s}", .{
-                            subsystem_suffix,
-                        }));
-                        break :mode .win32;
-                    },
-                    .Windows => {
-                        try argv.append(try allocPrint(arena, "-SUBSYSTEM:windows{s}", .{
-                            subsystem_suffix,
-                        }));
-                        break :mode .win32;
-                    },
-                }
+                try argv.append(try allocPrint(arena, "-SUBSYSTEM:{s},{d}.{d}", .{
+                    @tagName(subsystem),
+                    coff.major_subsystem_version,
+                    coff.minor_subsystem_version,
+                }));
+                break :mode switch (subsystem) {
+                    .console,
+                    .windows,
+                    .posix,
+                    .native,
+                    => .win32,
+                    .efi_application,
+                    .efi_boot_service_driver,
+                    .efi_rom,
+                    .efi_runtime_driver,
+                    => .uefi,
+                };
             } else if (target.os.tag == .uefi) {
                 break :mode .uefi;
             } else {
src/Compilation.zig
@@ -1766,7 +1766,7 @@ pub const CreateOptions = struct {
     reference_trace: ?u32 = null,
     test_filters: []const []const u8 = &.{},
     test_runner_path: ?[]const u8 = null,
-    subsystem: ?std.Target.SubSystem = null,
+    subsystem: ?std.zig.Subsystem = null,
     mingw_unicode_entry_point: bool = false,
     /// (Zig compiler development) Enable dumping linker's state as JSON.
     enable_link_snapshots: bool = false,
src/link.zig
@@ -448,7 +448,7 @@ pub const File = struct {
         allow_shlib_undefined: ?bool,
         allow_undefined_version: bool,
         enable_new_dtags: ?bool,
-        subsystem: ?std.Target.SubSystem,
+        subsystem: ?std.zig.Subsystem,
         linker_script: ?[]const u8,
         version_script: ?[]const u8,
         soname: ?[]const u8,
src/main.zig
@@ -893,7 +893,7 @@ fn buildOutputType(
     var override_global_cache_dir: ?[]const u8 = try EnvVar.ZIG_GLOBAL_CACHE_DIR.get(arena);
     var override_lib_dir: ?[]const u8 = try EnvVar.ZIG_LIB_DIR.get(arena);
     var clang_preprocessor_mode: Compilation.ClangPreprocessorMode = .no;
-    var subsystem: ?std.Target.SubSystem = null;
+    var subsystem: ?std.zig.Subsystem = null;
     var major_subsystem_version: ?u16 = null;
     var minor_subsystem_version: ?u16 = null;
     var mingw_unicode_entry_point: bool = false;
@@ -1135,7 +1135,7 @@ fn buildOutputType(
                         }
                         n_jobs = num;
                     } else if (mem.eql(u8, arg, "--subsystem")) {
-                        subsystem = try parseSubSystem(args_iter.nextOrFatal());
+                        subsystem = try parseSubsystem(args_iter.nextOrFatal());
                     } else if (mem.eql(u8, arg, "-O")) {
                         mod_opts.optimize_mode = parseOptimizeMode(args_iter.nextOrFatal());
                     } else if (mem.cutPrefix(u8, arg, "-fentry=")) |rest| {
@@ -2415,7 +2415,7 @@ fn buildOutputType(
                 } else if (mem.eql(u8, arg, "-rpath") or mem.eql(u8, arg, "--rpath") or mem.eql(u8, arg, "-R")) {
                     try create_module.rpath_list.append(arena, linker_args_it.nextOrFatal());
                 } else if (mem.eql(u8, arg, "--subsystem")) {
-                    subsystem = try parseSubSystem(linker_args_it.nextOrFatal());
+                    subsystem = try parseSubsystem(linker_args_it.nextOrFatal());
                 } else if (mem.eql(u8, arg, "-I") or
                     mem.eql(u8, arg, "--dynamic-linker") or
                     mem.eql(u8, arg, "-dynamic-linker"))
@@ -2743,7 +2743,7 @@ fn buildOutputType(
                     try symbol_wrap_set.put(arena, next_arg, {});
                 } else if (mem.startsWith(u8, arg, "/subsystem:")) {
                     var split_it = mem.splitBackwardsScalar(u8, arg, ':');
-                    subsystem = try parseSubSystem(split_it.first());
+                    subsystem = try parseSubsystem(split_it.first());
                 } else if (mem.startsWith(u8, arg, "/implib:")) {
                     var split_it = mem.splitBackwardsScalar(u8, arg, ':');
                     emit_implib = .{ .yes = split_it.first() };
@@ -6657,26 +6657,10 @@ fn warnAboutForeignBinaries(
     }
 }
 
-fn parseSubSystem(next_arg: []const u8) !std.Target.SubSystem {
-    if (mem.eql(u8, next_arg, "console")) {
-        return .Console;
-    } else if (mem.eql(u8, next_arg, "windows")) {
-        return .Windows;
-    } else if (mem.eql(u8, next_arg, "posix")) {
-        return .Posix;
-    } else if (mem.eql(u8, next_arg, "native")) {
-        return .Native;
-    } else if (mem.eql(u8, next_arg, "efi_application")) {
-        return .EfiApplication;
-    } else if (mem.eql(u8, next_arg, "efi_boot_service_driver")) {
-        return .EfiBootServiceDriver;
-    } else if (mem.eql(u8, next_arg, "efi_rom")) {
-        return .EfiRom;
-    } else if (mem.eql(u8, next_arg, "efi_runtime_driver")) {
-        return .EfiRuntimeDriver;
-    } else {
+fn parseSubsystem(arg: []const u8) !std.zig.Subsystem {
+    return std.meta.stringToEnum(std.zig.Subsystem, arg) orelse
         fatal("invalid: --subsystem: '{s}'. Options are:\n{s}", .{
-            next_arg,
+            arg,
             \\  console
             \\  windows
             \\  posix
@@ -6687,7 +6671,6 @@ fn parseSubSystem(next_arg: []const u8) !std.Target.SubSystem {
             \\  efi_runtime_driver
             \\
         });
-    }
 }
 
 /// Model a header searchlist as a group.
test/standalone/issue_5825/build.zig
@@ -31,7 +31,7 @@ pub fn build(b: *std.Build) void {
             .target = target,
         }),
     });
-    exe.subsystem = .Console;
+    exe.subsystem = .console;
     exe.root_module.linkSystemLibrary("kernel32", .{});
     exe.root_module.linkSystemLibrary("ntdll", .{});
     exe.root_module.addObject(obj);
test/standalone/windows_entry_points/build.zig
@@ -53,7 +53,7 @@ pub fn build(b: *std.Build) void {
                 .link_libc = true,
             }),
         });
-        // Note: `exe.subsystem = .Windows;` is not necessary
+        // Note: `exe.subsystem = .windows;` is not necessary
         exe.root_module.addCSourceFile(.{ .file = b.path("winmain.c") });
 
         _ = exe.getEmittedBin();
@@ -71,7 +71,7 @@ pub fn build(b: *std.Build) void {
             }),
         });
         exe.mingw_unicode_entry_point = true;
-        // Note: `exe.subsystem = .Windows;` is not necessary
+        // Note: `exe.subsystem = .windows;` is not necessary
         exe.root_module.addCSourceFile(.{ .file = b.path("wwinmain.c") });
 
         _ = exe.getEmittedBin();