From ae52e245eaf737527a3af50ead74ed4e2b143e24 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Wed, 17 Jan 2024 21:07:19 +0100 Subject: [PATCH 1/2] Add WINDOWS_SUBSYSTEM constant bool true when -subsystem:windows for Windows targets, false otherwise. --- src/build_settings.cpp | 19 +++++++++---------- src/checker.cpp | 2 ++ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 1f57b5625..ae16841c5 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -298,6 +298,7 @@ struct BuildContext { 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; + bool WINDOWS_SUBSYSTEM; // True only for Windows targets with -subsystem:windows ErrorPosStyle ODIN_ERROR_POS_STYLE; @@ -1282,8 +1283,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 +1299,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; diff --git a/src/checker.cpp b/src/checker.cpp index 5e46e87fe..a9c1bdde4 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -973,6 +973,8 @@ gb_internal void init_universal(void) { add_global_string_constant("ODIN_ROOT", bc->ODIN_ROOT); add_global_string_constant("ODIN_BUILD_PROJECT_NAME", bc->ODIN_BUILD_PROJECT_NAME); + add_global_bool_constant("WINDOWS_SUBSYSTEM", bc->use_subsystem_windows); + { GlobalEnumValue values[TargetOs_COUNT] = { {"Unknown", TargetOs_Invalid}, From fc047a8043493787878d064487fc1e410b334b23 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Thu, 18 Jan 2024 19:12:39 +0100 Subject: [PATCH 2/2] Expand -subsystem option on Windows W:\Odin>odin run sketch.odin -file -subsystem:foo Invalid -subsystem string, got oo. Expected one of: BOOT_APPLICATION, CONSOLE (default), EFI_APPLICATION, EFI_BOOT_SERVICE_DRIVER, EFI_ROM, EFI_RUNTIME_DRIVER, NATIVE, POSIX, WINDOWS (or WINDOW), WINDOWSCE We now also set the constant ODIN_WINDOWS_SUBSYSTEM, which is "" for non-Windows targets. --- src/build_settings.cpp | 50 +++++++++++++++++++++++++++++++++--------- src/checker.cpp | 9 ++++---- src/linker.cpp | 9 ++++---- src/main.cpp | 43 +++++++++++++++++++++++++++++------- 4 files changed, 83 insertions(+), 28 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index ae16841c5..af518bcb4 100644 --- a/src/build_settings.cpp +++ b/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,18 +313,18 @@ 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; - bool WINDOWS_SUBSYSTEM; // True only for Windows targets with -subsystem:windows ErrorPosStyle ODIN_ERROR_POS_STYLE; @@ -368,7 +394,6 @@ struct BuildContext { bool ignore_lazy; bool ignore_llvm_build; - bool use_subsystem_windows; bool ignore_microsoft_magic; bool linker_map_file; @@ -1328,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. diff --git a/src/checker.cpp b/src/checker.cpp index a9c1bdde4..917340a20 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -968,12 +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_bool_constant("WINDOWS_SUBSYSTEM", bc->use_subsystem_windows); + add_global_string_constant("ODIN_WINDOWS_SUBSYSTEM", bc->ODIN_WINDOWS_SUBSYSTEM); { GlobalEnumValue values[TargetOs_COUNT] = { diff --git a/src/linker.cpp b/src/linker.cpp index 93869633e..c0952d0e0 100644 --- a/src/linker.cpp +++ b/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 diff --git a/src/main.cpp b/src/main.cpp index fd754248b..19271d667 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1270,16 +1270,43 @@ gb_internal bool parse_build_flags(Array 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;