Browse Source

Merge pull request #3108 from Kelimion/subsystem

Add WINDOWS_SUBSYSTEM constant
gingerBill 1 year ago
parent
commit
737677f1b6
4 changed files with 91 additions and 35 deletions
  1. 48 19
      src/build_settings.cpp
  2. 4 3
      src/checker.cpp
  3. 4 5
      src/linker.cpp
  4. 35 8
      src/main.cpp

+ 48 - 19
src/build_settings.cpp

@@ -56,6 +56,19 @@ enum TargetABIKind : u16 {
 	TargetABI_COUNT,
 };
 
+enum Windows_Subsystem : u8 {
+ 	Windows_Subsystem_BOOT_APPLICATION,
+	Windows_Subsystem_CONSOLE,                 // Default,
+	Windows_Subsystem_EFI_APPLICATION,
+	Windows_Subsystem_EFI_BOOT_SERVICE_DRIVER,
+	Windows_Subsystem_EFI_ROM,
+	Windows_Subsystem_EFI_RUNTIME_DRIVER,
+	Windows_Subsystem_NATIVE,
+	Windows_Subsystem_POSIX,
+	Windows_Subsystem_WINDOWS,
+	Windows_Subsystem_WINDOWSCE,
+	Windows_Subsystem_COUNT,
+};
 
 gb_global String target_os_names[TargetOs_COUNT] = {
 	str_lit(""),
@@ -120,6 +133,19 @@ gb_global TargetEndianKind target_endians[TargetArch_COUNT] = {
 	TargetEndian_Little,
 };
 
+gb_global String windows_subsystem_names[Windows_Subsystem_COUNT] = {
+	str_lit("BOOT_APPLICATION"),
+	str_lit("CONSOLE"),                 // Default
+	str_lit("EFI_APPLICATION"),
+	str_lit("EFI_BOOT_SERVICE_DRIVER"),
+	str_lit("EFI_ROM"),
+	str_lit("EFI_RUNTIME_DRIVER"),
+	str_lit("NATIVE"),
+	str_lit("POSIX"),
+	str_lit("WINDOWS"),
+	str_lit("WINDOWSCE"),
+};
+
 #ifndef ODIN_VERSION_RAW
 #define ODIN_VERSION_RAW "dev-unknown-unknown"
 #endif
@@ -287,14 +313,15 @@ enum SanitizerFlags : u32 {
 // This stores the information for the specify architecture of this build
 struct BuildContext {
 	// Constants
-	String ODIN_OS;      // target operating system
-	String ODIN_ARCH;    // target architecture
-	String ODIN_VENDOR;  // compiler vendor
-	String ODIN_VERSION; // compiler version
-	String ODIN_ROOT;    // Odin ROOT
-	String ODIN_BUILD_PROJECT_NAME; // Odin main/initial package's directory name
-	bool   ODIN_DEBUG;   // Odin in debug mode
-	bool   ODIN_DISABLE_ASSERT; // Whether the default 'assert' et al is disabled in code or not
+	String ODIN_OS;                       // Target operating system
+	String ODIN_ARCH;                     // Target architecture
+	String ODIN_VENDOR;                   // Compiler vendor
+	String ODIN_VERSION;                  // Compiler version
+	String ODIN_ROOT;                     // Odin ROOT
+	String ODIN_BUILD_PROJECT_NAME;       // Odin main/initial package's directory name
+	String ODIN_WINDOWS_SUBSYSTEM;        // Empty string for non-Windows targets
+	bool   ODIN_DEBUG;                    // Odin in debug mode
+	bool   ODIN_DISABLE_ASSERT;           // Whether the default 'assert' et al is disabled in code or not
 	bool   ODIN_DEFAULT_TO_NIL_ALLOCATOR; // Whether the default allocator is a "nil" allocator or not (i.e. it does nothing)
 	bool   ODIN_FOREIGN_ERROR_PROCEDURES;
 	bool   ODIN_VALGRIND_SUPPORT;
@@ -367,7 +394,6 @@ struct BuildContext {
 	bool   ignore_lazy;
 	bool   ignore_llvm_build;
 
-	bool   use_subsystem_windows;
 	bool   ignore_microsoft_magic;
 	bool   linker_map_file;
 
@@ -1282,8 +1308,6 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta
 		GB_ASSERT(metrics->int_size == 2*metrics->ptr_size);
 	}
 
-
-
 	bc->metrics = *metrics;
 	switch (subtarget) {
 	case Subtarget_Default:
@@ -1300,14 +1324,14 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta
 		break;
 	}
 
-	bc->ODIN_OS        = target_os_names[metrics->os];
-	bc->ODIN_ARCH      = target_arch_names[metrics->arch];
-	bc->endian_kind    = target_endians[metrics->arch];
-	bc->ptr_size       = metrics->ptr_size;
-	bc->int_size       = metrics->int_size;
-	bc->max_align      = metrics->max_align;
-	bc->max_simd_align = metrics->max_simd_align;
-	bc->link_flags  = str_lit(" ");
+	bc->ODIN_OS           = target_os_names[metrics->os];
+	bc->ODIN_ARCH         = target_arch_names[metrics->arch];
+	bc->endian_kind       = target_endians[metrics->arch];
+	bc->ptr_size          = metrics->ptr_size;
+	bc->int_size          = metrics->int_size;
+	bc->max_align         = metrics->max_align;
+	bc->max_simd_align    = metrics->max_simd_align;
+	bc->link_flags        = str_lit(" ");
 
 	#if defined(DEFAULT_TO_THREADED_CHECKER)
 	bc->threaded_checker = true;
@@ -1329,6 +1353,11 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta
 		}
 	}
 
+	// Default to subsystem:CONSOLE on Windows targets
+	if (bc->ODIN_WINDOWS_SUBSYSTEM == "" && bc->metrics.os == TargetOs_windows) {
+		bc->ODIN_WINDOWS_SUBSYSTEM = windows_subsystem_names[Windows_Subsystem_CONSOLE];
+	}
+
 	// NOTE(zangent): The linker flags to set the build architecture are different
 	// across OSs. It doesn't make sense to allocate extra data on the heap
 	// here, so I just #defined the linker flags to keep things concise.

+ 4 - 3
src/checker.cpp

@@ -968,10 +968,11 @@ gb_internal void init_universal(void) {
 	add_global_bool_constant("true",  true);
 	add_global_bool_constant("false", false);
 
-	add_global_string_constant("ODIN_VENDOR",  bc->ODIN_VENDOR);
-	add_global_string_constant("ODIN_VERSION", bc->ODIN_VERSION);
-	add_global_string_constant("ODIN_ROOT",    bc->ODIN_ROOT);
+	add_global_string_constant("ODIN_VENDOR",             bc->ODIN_VENDOR);
+	add_global_string_constant("ODIN_VERSION",            bc->ODIN_VERSION);
+	add_global_string_constant("ODIN_ROOT",               bc->ODIN_ROOT);
 	add_global_string_constant("ODIN_BUILD_PROJECT_NAME", bc->ODIN_BUILD_PROJECT_NAME);
+	add_global_string_constant("ODIN_WINDOWS_SUBSYSTEM",  bc->ODIN_WINDOWS_SUBSYSTEM);
 
 	{
 		GlobalEnumValue values[TargetOs_COUNT] = {

+ 4 - 5
src/linker.cpp

@@ -233,7 +233,6 @@ gb_internal i32 linker_stage(LinkerData *gen) {
 			String windows_sdk_bin_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Win_SDK_Bin_Path]);
 			defer (gb_free(heap_allocator(), windows_sdk_bin_path.text));
 
-			char const *subsystem_str = build_context.use_subsystem_windows ? "WINDOWS" : "CONSOLE";
 			if (!build_context.use_lld) { // msvc
 				String res_path = {};
 				defer (gb_free(heap_allocator(), res_path.text));
@@ -265,14 +264,14 @@ gb_internal i32 linker_stage(LinkerData *gen) {
 
 				result = system_exec_command_line_app("msvc-link",
 					"\"%.*slink.exe\" %s %.*s -OUT:\"%.*s\" %s "
-					"/nologo /incremental:no /opt:ref /subsystem:%s "
+					"/nologo /incremental:no /opt:ref /subsystem:%.*s "
 					"%.*s "
 					"%.*s "
 					"%s "
 					"",
 					LIT(vs_exe_path), object_files, LIT(res_path), LIT(output_filename),
 					link_settings,
-					subsystem_str,
+					LIT(build_context.ODIN_WINDOWS_SUBSYSTEM),
 					LIT(build_context.link_flags),
 					LIT(build_context.extra_linker_flags),
 					lib_str
@@ -283,14 +282,14 @@ gb_internal i32 linker_stage(LinkerData *gen) {
 			} else { // lld
 				result = system_exec_command_line_app("msvc-lld-link",
 					"\"%.*s\\bin\\lld-link\" %s -OUT:\"%.*s\" %s "
-					"/nologo /incremental:no /opt:ref /subsystem:%s "
+					"/nologo /incremental:no /opt:ref /subsystem:%.*s "
 					"%.*s "
 					"%.*s "
 					"%s "
 					"",
 					LIT(build_context.ODIN_ROOT), object_files, LIT(output_filename),
 					link_settings,
-					subsystem_str,
+					LIT(build_context.ODIN_WINDOWS_SUBSYSTEM),
 					LIT(build_context.link_flags),
 					LIT(build_context.extra_linker_flags),
 					lib_str

+ 35 - 8
src/main.cpp

@@ -1270,16 +1270,43 @@ gb_internal bool parse_build_flags(Array<String> args) {
 						}
 
 						case BuildFlag_Subsystem: {
+							// TODO(Jeroen): Parse optional "[,major[.minor]]"
+
 							GB_ASSERT(value.kind == ExactValue_String);
 							String subsystem = value.value_string;
-							if (str_eq_ignore_case(subsystem, str_lit("console"))) {
-								build_context.use_subsystem_windows = false;
-							} else if (str_eq_ignore_case(subsystem, str_lit("window"))) {
-								build_context.use_subsystem_windows = true;
-							} else if (str_eq_ignore_case(subsystem, str_lit("windows"))) {
-								build_context.use_subsystem_windows = true;
-							} else {
-								gb_printf_err("Invalid -subsystem string, got %.*s, expected either 'console' or 'windows'\n", LIT(subsystem));
+							bool subsystem_found = false;
+							for (int i = 0; i < Windows_Subsystem_COUNT; i++) {
+								if (str_eq_ignore_case(subsystem, windows_subsystem_names[i])) {
+									build_context.ODIN_WINDOWS_SUBSYSTEM = windows_subsystem_names[i];
+									subsystem_found = true;
+									break;
+								}
+							}
+
+							// WINDOW is a hidden alias for WINDOWS. Check it.
+							String subsystem_windows_alias = str_lit("WINDOW");
+							if (!subsystem_found && str_eq_ignore_case(subsystem, subsystem_windows_alias)) {
+								build_context.ODIN_WINDOWS_SUBSYSTEM = windows_subsystem_names[Windows_Subsystem_WINDOWS];
+								subsystem_found = true;
+								break;
+							}
+
+							if (!subsystem_found) {
+								gb_printf_err("Invalid -subsystem string, got %.*s. Expected one of:\n", LIT(subsystem));
+								gb_printf_err("\t");
+								for (int i = 0; i < Windows_Subsystem_COUNT; i++) {
+									if (i > 0) {
+										gb_printf_err(", ");
+									}
+									gb_printf_err("%.*s", LIT(windows_subsystem_names[i]));
+									if (i == Windows_Subsystem_CONSOLE) {
+										gb_printf_err(" (default)");
+									}
+									if (i == Windows_Subsystem_WINDOWS) {
+										gb_printf_err(" (or WINDOW)");
+									}
+								}
+								gb_printf_err("\n");
 								bad_flags = true;
 							}
 							break;