diff options
Diffstat (limited to 'src/build_settings.cpp')
| -rw-r--r-- | src/build_settings.cpp | 631 |
1 files changed, 487 insertions, 144 deletions
diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 08df34c57..53953600e 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -31,6 +31,24 @@ enum TargetOsKind : u16 { TargetOs_COUNT, }; +gb_global String target_os_names[TargetOs_COUNT] = { + str_lit(""), + str_lit("windows"), + str_lit("darwin"), + str_lit("linux"), + str_lit("essence"), + str_lit("freebsd"), + str_lit("openbsd"), + str_lit("netbsd"), + str_lit("haiku"), + + str_lit("wasi"), + str_lit("js"), + str_lit("orca"), + + str_lit("freestanding"), +}; + enum TargetArchKind : u16 { TargetArch_Invalid, @@ -45,6 +63,17 @@ enum TargetArchKind : u16 { TargetArch_COUNT, }; +gb_global String target_arch_names[TargetArch_COUNT] = { + str_lit(""), + str_lit("amd64"), + str_lit("i386"), + str_lit("arm32"), + str_lit("arm64"), + str_lit("wasm32"), + str_lit("wasm64p32"), + str_lit("riscv64"), +}; + enum TargetEndianKind : u8 { TargetEndian_Little, TargetEndian_Big, @@ -52,6 +81,11 @@ enum TargetEndianKind : u8 { TargetEndian_COUNT, }; +gb_global String target_endian_names[TargetEndian_COUNT] = { + str_lit("little"), + str_lit("big"), +}; + enum TargetABIKind : u16 { TargetABI_Default, @@ -61,7 +95,14 @@ enum TargetABIKind : u16 { TargetABI_COUNT, }; +gb_global String target_abi_names[TargetABI_COUNT] = { + str_lit(""), + str_lit("win64"), + str_lit("sysv"), +}; + enum Windows_Subsystem : u8 { + Windows_Subsystem_UNKNOWN, Windows_Subsystem_BOOT_APPLICATION, Windows_Subsystem_CONSOLE, // Default, Windows_Subsystem_EFI_APPLICATION, @@ -75,53 +116,32 @@ enum Windows_Subsystem : u8 { Windows_Subsystem_COUNT, }; -struct MicroarchFeatureList { - String microarch; - String features; -}; - -gb_global String target_os_names[TargetOs_COUNT] = { +gb_global String windows_subsystem_names[Windows_Subsystem_COUNT] = { str_lit(""), - str_lit("windows"), - str_lit("darwin"), - str_lit("linux"), - str_lit("essence"), - str_lit("freebsd"), - str_lit("openbsd"), - str_lit("netbsd"), - str_lit("haiku"), - - str_lit("wasi"), - str_lit("js"), - str_lit("orca"), - - str_lit("freestanding"), + 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"), }; -gb_global String target_arch_names[TargetArch_COUNT] = { - str_lit(""), - str_lit("amd64"), - str_lit("i386"), - str_lit("arm32"), - str_lit("arm64"), - str_lit("wasm32"), - str_lit("wasm64p32"), - str_lit("riscv64"), +struct MicroarchFeatureList { + String microarch; + String features; }; +#if defined(GB_SYSTEM_WINDOWS) + #include <llvm-c/Config/llvm-config.h> +#else + #include <llvm/Config/llvm-config.h> +#endif #include "build_settings_microarch.cpp" -gb_global String target_endian_names[TargetEndian_COUNT] = { - str_lit("little"), - str_lit("big"), -}; - -gb_global String target_abi_names[TargetABI_COUNT] = { - str_lit(""), - str_lit("win64"), - str_lit("sysv"), -}; - gb_global TargetEndianKind target_endians[TargetArch_COUNT] = { TargetEndian_Little, TargetEndian_Little, @@ -132,19 +152,6 @@ 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 @@ -164,14 +171,19 @@ struct TargetMetrics { enum Subtarget : u32 { Subtarget_Default, - Subtarget_iOS, - + Subtarget_iPhone, + Subtarget_iPhoneSimulator, + Subtarget_Android, + Subtarget_COUNT, + Subtarget_Invalid, // NOTE(harold): Must appear after _COUNT as this is not a real subtarget }; gb_global String subtarget_strings[Subtarget_COUNT] = { str_lit(""), - str_lit("ios"), + str_lit("iphone"), + str_lit("iphonesimulator"), + str_lit("android"), }; @@ -198,20 +210,25 @@ enum BuildModeKind { BuildMode_COUNT, }; -enum CommandKind : u32 { +enum CommandKind : u64 { Command_run = 1<<0, Command_build = 1<<1, - Command_check = 1<<3, - Command_doc = 1<<5, - Command_version = 1<<6, - Command_test = 1<<7, + Command_check = 1<<2, + Command_doc = 1<<3, + Command_version = 1<<4, + Command_test = 1<<5, - Command_strip_semicolon = 1<<8, - Command_bug_report = 1<<9, + Command_strip_semicolon = 1<<6, + Command_bug_report = 1<<7, + + Command_bundle_android = 1<<8, + Command_bundle_macos = 1<<9, + Command_bundle_ios = 1<<10, + Command_bundle_orca = 1<<11, Command__does_check = Command_run|Command_build|Command_check|Command_doc|Command_test|Command_strip_semicolon, Command__does_build = Command_run|Command_build|Command_test, - Command_all = ~(u32)0, + Command_all = ~(CommandKind)0, }; gb_global char const *odin_command_strings[32] = { @@ -222,6 +239,11 @@ gb_global char const *odin_command_strings[32] = { "version", "test", "strip-semicolon", + "", + "bundle android", + "bundle macos", + "bundle ios", + "bundle orca", }; @@ -269,7 +291,7 @@ enum BuildPath : u8 { BuildPath_VS_LIB, // vs_library_path BuildPath_Output, // Output Path for .exe, .dll, .so, etc. Can be overridden with `-out:`. - BuildPath_PDB, // Output Path for .pdb file, can be overridden with `-pdb-name:`. + BuildPath_Symbols, // Output Path for .pdb or .dSym file, can be overridden with `-pdb-name:`. BuildPathCOUNT, }; @@ -287,6 +309,7 @@ enum VetFlags : u64 { VetFlag_Cast = 1u<<8, VetFlag_Tabs = 1u<<9, VetFlag_UnusedProcedures = 1u<<10, + VetFlag_ExplicitAllocators = 1u<<11, VetFlag_Unused = VetFlag_UnusedVariables|VetFlag_UnusedImports, @@ -320,6 +343,8 @@ u64 get_vet_flag_from_name(String const &name) { return VetFlag_Tabs; } else if (name == "unused-procedures") { return VetFlag_UnusedProcedures; + } else if (name == "explicit-allocators") { + return VetFlag_ExplicitAllocators; } return VetFlag_NONE; } @@ -327,12 +352,43 @@ u64 get_vet_flag_from_name(String const &name) { enum OptInFeatureFlags : u64 { OptInFeatureFlag_NONE = 0, OptInFeatureFlag_DynamicLiterals = 1u<<0, + + OptInFeatureFlag_GlobalContext = 1u<<1, + + OptInFeatureFlag_IntegerDivisionByZero_Trap = 1u<<2, + OptInFeatureFlag_IntegerDivisionByZero_Zero = 1u<<3, + OptInFeatureFlag_IntegerDivisionByZero_Self = 1u<<4, + OptInFeatureFlag_IntegerDivisionByZero_AllBits = 1u<<5, + + + OptInFeatureFlag_IntegerDivisionByZero_ALL = OptInFeatureFlag_IntegerDivisionByZero_Trap| + OptInFeatureFlag_IntegerDivisionByZero_Zero| + OptInFeatureFlag_IntegerDivisionByZero_Self| + OptInFeatureFlag_IntegerDivisionByZero_AllBits, + }; u64 get_feature_flag_from_name(String const &name) { if (name == "dynamic-literals") { return OptInFeatureFlag_DynamicLiterals; } + if (name == "integer-division-by-zero:trap") { + return OptInFeatureFlag_IntegerDivisionByZero_Trap; + } + if (name == "integer-division-by-zero:zero") { + return OptInFeatureFlag_IntegerDivisionByZero_Zero; + } + if (name == "integer-division-by-zero:self") { + return OptInFeatureFlag_IntegerDivisionByZero_Self; + } + if (name == "integer-division-by-zero:all-bits") { + return OptInFeatureFlag_IntegerDivisionByZero_AllBits; + } + + + if (name == "global-context") { + return OptInFeatureFlag_GlobalContext; + } return OptInFeatureFlag_NONE; } @@ -362,30 +418,46 @@ enum LinkerChoice : i32 { Linker_Default = 0, Linker_lld, Linker_radlink, + Linker_mold, Linker_COUNT, }; +enum SourceCodeLocationInfo : u8 { + SourceCodeLocationInfo_Normal = 0, + SourceCodeLocationInfo_Obfuscated = 1, + SourceCodeLocationInfo_Filename = 2, + SourceCodeLocationInfo_None = 3, +}; + String linker_choices[Linker_COUNT] = { str_lit("default"), str_lit("lld"), str_lit("radlink"), + str_lit("mold"), +}; + +enum IntegerDivisionByZeroKind : u8 { + IntegerDivisionByZero_Trap, + IntegerDivisionByZero_Zero, + IntegerDivisionByZero_Self, + IntegerDivisionByZero_AllBits, }; // 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 - 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_DEFAULT_TO_PANIC_ALLOCATOR; // Whether the default allocator is a "panic" allocator or not (i.e. panics on any call to it) + 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 + Windows_Subsystem ODIN_WINDOWS_SUBSYSTEM; // .Console, .Windows + 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_DEFAULT_TO_PANIC_ALLOCATOR; // Whether the default allocator is a "panic" allocator or not (i.e. panics on any call to it) bool ODIN_FOREIGN_ERROR_PROCEDURES; bool ODIN_VALGRIND_SUPPORT; @@ -423,6 +495,7 @@ struct BuildContext { String extra_assembler_flags; String microarch; BuildModeKind build_mode; + bool keep_executable; bool generate_docs; bool custom_optimization_level; i32 optimization_level; @@ -441,6 +514,7 @@ struct BuildContext { bool ignore_unknown_attributes; bool no_bounds_check; bool no_type_assert; + bool dynamic_literals; // Opt-in to `#+feature dynamic-literals` project-wide. bool no_output_files; bool no_crt; bool no_rpath; @@ -451,6 +525,8 @@ struct BuildContext { bool keep_object_files; bool disallow_do; + IntegerDivisionByZeroKind integer_division_by_zero_behaviour; + LinkerChoice linker_choice; StringSet custom_attributes; @@ -472,6 +548,8 @@ struct BuildContext { bool ignore_microsoft_magic; bool linker_map_file; + bool build_diagnostics; + bool use_single_module; bool use_separate_modules; bool module_per_file; @@ -480,6 +558,8 @@ struct BuildContext { bool internal_no_inline; bool internal_by_value; + bool internal_weak_monomorphization; + bool internal_ignore_llvm_verification; bool no_threaded_checker; @@ -491,7 +571,7 @@ struct BuildContext { bool dynamic_map_calls; - bool obfuscate_source_code_locations; + SourceCodeLocationInfo source_code_location_info; bool min_link_libs; @@ -521,6 +601,21 @@ struct BuildContext { String minimum_os_version_string; bool minimum_os_version_string_given; + + + int ODIN_ANDROID_API_LEVEL; + + String ODIN_ANDROID_SDK; + + String ODIN_ANDROID_NDK; + String ODIN_ANDROID_NDK_TOOLCHAIN; + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB; + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL; + String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT; + + String android_keystore; + String android_keystore_alias; + String android_keystore_password; }; gb_global BuildContext build_context = {0}; @@ -544,12 +639,6 @@ gb_internal isize MAX_ERROR_COLLECTOR_COUNT(void) { return build_context.max_error_count; } -#if defined(GB_SYSTEM_WINDOWS) - #include <llvm-c/Config/llvm-config.h> -#else - #include <llvm/Config/llvm-config.h> -#endif - // NOTE: AMD64 targets had their alignment on 128 bit ints bumped from 8 to 16 (undocumented of course). #if LLVM_VERSION_MAJOR >= 18 #define AMD64_MAX_ALIGNMENT 16 @@ -820,13 +909,47 @@ gb_global NamedTargetMetrics *selected_target_metrics; gb_global Subtarget selected_subtarget; -gb_internal TargetOsKind get_target_os_from_string(String str) { +gb_internal TargetOsKind get_target_os_from_string(String str, Subtarget *subtarget_ = nullptr, String *subtarget_str = nullptr) { + String os_name = str; + String subtarget = {}; + auto part = string_partition(str, str_lit(":")); + if (part.match.len == 1) { + os_name = part.head; + subtarget = part.tail; + } + + TargetOsKind kind = TargetOs_Invalid; + for (isize i = 0; i < TargetOs_COUNT; i++) { - if (str_eq_ignore_case(target_os_names[i], str)) { - return cast(TargetOsKind)i; + if (str_eq_ignore_case(target_os_names[i], os_name)) { + kind = cast(TargetOsKind)i; + break; + } + } + + if (subtarget_str) *subtarget_str = subtarget; + + if (subtarget_) { + if (subtarget.len != 0) { + *subtarget_ = Subtarget_Invalid; + + if (str_eq_ignore_case(subtarget, "generic") || str_eq_ignore_case(subtarget, "default")) { + *subtarget_ = Subtarget_Default; + + } else { + for (isize i = 1; i < Subtarget_COUNT; i++) { + if (str_eq_ignore_case(subtarget_strings[i], subtarget)) { + *subtarget_ = cast(Subtarget)i; + break; + } + } + } + } else { + *subtarget_ = Subtarget_Default; } } - return TargetOs_Invalid; + + return kind; } gb_internal TargetArchKind get_target_arch_from_string(String str) { @@ -847,14 +970,6 @@ gb_internal bool is_excluded_target_filename(String name) { return true; } - if (build_context.command_kind != Command_test) { - String test_suffix = str_lit("_test"); - if (string_ends_with(name, test_suffix) && name != test_suffix) { - // Ignore *_test.odin files - return true; - } - } - String str1 = {}; String str2 = {}; isize n = 0; @@ -946,6 +1061,14 @@ gb_internal bool is_arch_x86(void) { gb_global String const WIN32_SEPARATOR_STRING = {cast(u8 *)"\\", 1}; gb_global String const NIX_SEPARATOR_STRING = {cast(u8 *)"/", 1}; +gb_global String const SEPARATOR_STRING = +#if defined(GB_SYSTEM_WINDOWS) + WIN32_SEPARATOR_STRING; +#else + NIX_SEPARATOR_STRING; +#endif + + gb_global String const WASM_MODULE_NAME_SEPARATOR = str_lit(".."); gb_internal String internal_odin_root_dir(void); @@ -1001,10 +1124,10 @@ gb_internal String internal_odin_root_dir(void) { mutex_lock(&string_buffer_mutex); defer (mutex_unlock(&string_buffer_mutex)); - text = gb_alloc_array(permanent_allocator(), wchar_t, len+1); + text = permanent_alloc_array<wchar_t>(len+1); GetModuleFileNameW(nullptr, text, cast(int)len); - path = string16_to_string(heap_allocator(), make_string16(text, len)); + path = string16_to_string(heap_allocator(), make_string16(cast(u16 *)text, len)); for (i = path.len-1; i >= 0; i--) { u8 c = path[i]; @@ -1038,8 +1161,8 @@ gb_internal String internal_odin_root_dir(void) { return global_module_path; } - auto path_buf = array_make<char>(heap_allocator(), 300); - defer (array_free(&path_buf)); + TEMPORARY_ALLOCATOR_GUARD(); + auto path_buf = array_make<char>(temporary_allocator(), 300); len = 0; for (;;) { @@ -1056,7 +1179,7 @@ gb_internal String internal_odin_root_dir(void) { mutex_lock(&string_buffer_mutex); defer (mutex_unlock(&string_buffer_mutex)); - text = gb_alloc_array(permanent_allocator(), u8, len + 1); + text = permanent_alloc_array<u8>(len + 1); gb_memmove(text, &path_buf[0], len); path = path_to_fullpath(heap_allocator(), make_string(text, len), nullptr); @@ -1108,7 +1231,7 @@ gb_internal String internal_odin_root_dir(void) { mutex_lock(&string_buffer_mutex); defer (mutex_unlock(&string_buffer_mutex)); - text = gb_alloc_array(permanent_allocator(), u8, len + 1); + text = permanent_alloc_array<u8>(len + 1); gb_memmove(text, &path_buf[0], len); path = path_to_fullpath(heap_allocator(), make_string(text, len), nullptr); @@ -1269,7 +1392,7 @@ gb_internal String internal_odin_root_dir(void) { mutex_lock(&string_buffer_mutex); defer (mutex_unlock(&string_buffer_mutex)); - text = gb_alloc_array(permanent_allocator(), u8, len + 1); + text = permanent_alloc_array<u8>(len + 1); gb_memmove(text, &path_buf[0], len); @@ -1302,14 +1425,14 @@ gb_internal String path_to_fullpath(gbAllocator a, String s, bool *ok_) { mutex_lock(&fullpath_mutex); - len = GetFullPathNameW(&string16[0], 0, nullptr, nullptr); + len = GetFullPathNameW(cast(wchar_t *)&string16[0], 0, nullptr, nullptr); if (len != 0) { - wchar_t *text = gb_alloc_array(permanent_allocator(), wchar_t, len+1); - GetFullPathNameW(&string16[0], len, text, nullptr); + wchar_t *text = permanent_alloc_array<wchar_t>(len+1); + GetFullPathNameW(cast(wchar_t *)&string16[0], len, text, nullptr); mutex_unlock(&fullpath_mutex); text[len] = 0; - result = string16_to_string(a, make_string16(text, len)); + result = string16_to_string(a, make_string16(cast(u16 *)text, len)); result = string_trim_whitespace(result); // Replace Windows style separators @@ -1461,6 +1584,94 @@ gb_internal bool has_ansi_terminal_colours(void) { return build_context.has_ansi_terminal_colours && !json_errors(); } +gb_internal void init_android_values(bool with_sdk) { + auto *bc = &build_context; + { // Android SDK/API Level + String default_level = str_lit("34"); + if (!bc->minimum_os_version_string_given) { + bc->minimum_os_version_string = default_level; + } + BigInt level = {}; + bool success = false; + big_int_from_string(&level, bc->minimum_os_version_string, &success); + if (!success) { + gb_printf_err("Warning: Invalid -minimum-os-version:%.*s for -subtarget:Android, defaulting to %.*s\n", LIT(bc->minimum_os_version_string), LIT(default_level)); + bc->minimum_os_version_string = default_level; + big_int_from_string(&level, bc->minimum_os_version_string, &success); + GB_ASSERT(success); + } + + i64 new_level = big_int_to_i64(&level); + + if (new_level >= 21) { + bc->ODIN_ANDROID_API_LEVEL = cast(int)new_level; + } else { + gb_printf_err("Warning: Invalid -minimum-os-version:%.*s for -subtarget:Android, defaulting to %.*s\n", LIT(bc->minimum_os_version_string), LIT(default_level)); + bc->ODIN_ANDROID_API_LEVEL = atoi(cast(char const *)default_level.text); + } + } + bc->ODIN_ANDROID_NDK = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK", permanent_allocator())), NIX_SEPARATOR_STRING); + bc->ODIN_ANDROID_NDK_TOOLCHAIN = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK_TOOLCHAIN", permanent_allocator())), NIX_SEPARATOR_STRING); + bc->ODIN_ANDROID_SDK = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_SDK", permanent_allocator())), NIX_SEPARATOR_STRING); + + #if defined(GB_SYSTEM_WINDOWS) + if (bc->ODIN_ANDROID_SDK.len == 0) { + bc->ODIN_ANDROID_SDK = normalize_path(permanent_allocator(), + path_to_fullpath(permanent_allocator(), str_lit("%LocalAppData%/Android/Sdk"), nullptr), + NIX_SEPARATOR_STRING); + } + #endif + + if (bc->ODIN_ANDROID_NDK.len != 0 && bc->ODIN_ANDROID_NDK_TOOLCHAIN.len == 0) { + String arch = str_lit("x86_64"); + #if defined (GB_CPU_ARM) + // TODO(bill): this is a complete guess + arch = str_lit("aarch64"); + #endif + #if defined(GB_SYSTEM_WINDOWS) + bc->ODIN_ANDROID_NDK_TOOLCHAIN = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK, str_lit("toolchains/llvm/prebuilt/"), str_lit("windows-"), arch); + #elif defined(GB_SYSTEM_OSX) + // TODO(bill): is this name even correct? + bc->ODIN_ANDROID_NDK_TOOLCHAIN = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK, str_lit("toolchains/llvm/prebuilt/"), str_lit("darwin-"), arch); + #elif defined(GB_SYSTEM_LINUX) + bc->ODIN_ANDROID_NDK_TOOLCHAIN = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK, str_lit("toolchains/llvm/prebuilt/"), str_lit("linux-"), arch); + #endif + + bc->ODIN_ANDROID_NDK_TOOLCHAIN = normalize_path(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN, NIX_SEPARATOR_STRING); + } + + if (bc->ODIN_ANDROID_NDK.len == 0 && !with_sdk) { + gb_printf_err("Error: ODIN_ANDROID_NDK not set"); + gb_exit(1); + + } + + if (bc->ODIN_ANDROID_NDK_TOOLCHAIN.len == 0 && !with_sdk) { + gb_printf_err("Error: ODIN_ANDROID_NDK not set"); + gb_exit(1); + } + + bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN, str_lit("sysroot/usr/lib/aarch64-linux-android/")); + + char buf[32] = {}; + gb_snprintf(buf, gb_size_of(buf), "%d/", bc->ODIN_ANDROID_API_LEVEL); + bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB, make_string_c(buf)); + + bc->ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN, str_lit("sysroot/")); + + + if (with_sdk) { + if (bc->ODIN_ANDROID_SDK.len == 0) { + gb_printf_err("Error: ODIN_ANDROID_SDK not set, which is required for -build-mode:executable for -subtarget:android"); + gb_exit(1); + } + if (bc->android_keystore.len == 0) { + gb_printf_err("Error: -android-keystore:<string> has not been set\n"); + gb_exit(1); + } + } +} + gb_internal bool has_asm_extension(String const &path) { String ext = path_extension(path); if (ext == ".asm") { @@ -1637,20 +1848,66 @@ 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]; + if (bc->ODIN_WINDOWS_SUBSYSTEM == Windows_Subsystem_UNKNOWN && bc->metrics.os == TargetOs_windows) { + bc->ODIN_WINDOWS_SUBSYSTEM = Windows_Subsystem_CONSOLE; + } + + if (subtarget == Subtarget_Android) { + switch (build_context.build_mode) { + case BuildMode_DynamicLibrary: + case BuildMode_Object: + case BuildMode_Assembly: + case BuildMode_LLVM_IR: + break; + default: + case BuildMode_Executable: + case BuildMode_StaticLibrary: + if ((build_context.command_kind & Command__does_build) != 0) { + gb_printf_err("Unsupported -build-mode for -subtarget:android\n"); + gb_printf_err("\tCurrently only supporting: \n"); + // gb_printf_err("\t\texe\n"); + gb_printf_err("\t\tshared\n"); + gb_printf_err("\t\tobject\n"); + gb_printf_err("\t\tassembly\n"); + gb_printf_err("\t\tllvm-ir\n"); + gb_exit(1); + } + break; + } } - if (metrics->os == TargetOs_darwin && subtarget == Subtarget_iOS) { + if (metrics->os == TargetOs_darwin) { + switch (subtarget) { + case Subtarget_iPhone: + switch (metrics->arch) { + case TargetArch_arm64: + bc->metrics.target_triplet = str_lit("arm64-apple-ios"); + break; + default: + GB_PANIC("Unknown architecture for -subtarget:iphone"); + } + break; + case Subtarget_iPhoneSimulator: + switch (metrics->arch) { + case TargetArch_arm64: + bc->metrics.target_triplet = str_lit("arm64-apple-ios-simulator"); + break; + case TargetArch_amd64: + bc->metrics.target_triplet = str_lit("x86_64-apple-ios-simulator"); + break; + default: + GB_PANIC("Unknown architecture for -subtarget:iphonesimulator"); + } + break; + } + } else if (metrics->os == TargetOs_linux && subtarget == Subtarget_Android) { switch (metrics->arch) { case TargetArch_arm64: - bc->metrics.target_triplet = str_lit("arm64-apple-ios"); - break; - case TargetArch_amd64: - bc->metrics.target_triplet = str_lit("x86_64-apple-ios"); + bc->metrics.target_triplet = str_lit("aarch64-none-linux-android"); + bc->reloc_mode = RelocMode_PIC; break; default: - GB_PANIC("Unknown architecture for darwin"); + GB_PANIC("Unknown architecture for -subtarget:android"); } } @@ -1668,6 +1925,13 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta str_lit("-target "), bc->metrics.target_triplet, str_lit(" ")); } else if (is_arch_wasm()) { gbString link_flags = gb_string_make(heap_allocator(), " "); + + // NOTE(laytan): Put the stack first in the memory, + // causing a stack overflow to error immediately instead of corrupting globals. + link_flags = gb_string_appendc(link_flags, "--stack-first "); + // NOTE(laytan): default stack size is 64KiB, up to a more reasonable 1MiB. + link_flags = gb_string_appendc(link_flags, "-z stack-size=1048576 "); + // link_flags = gb_string_appendc(link_flags, "--export-all "); // link_flags = gb_string_appendc(link_flags, "--export-table "); // if (bc->metrics.arch == TargetArch_wasm64) { @@ -1700,12 +1964,27 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta // does not annoy the user with version warnings. if (metrics->os == TargetOs_darwin) { if (!bc->minimum_os_version_string_given) { - bc->minimum_os_version_string = str_lit("11.0.0"); + if (subtarget == Subtarget_Default) { + bc->minimum_os_version_string = str_lit("11.0.0"); + } else if (subtarget == Subtarget_iPhone || subtarget == Subtarget_iPhoneSimulator) { + // NOTE(harold): We default to 17.4 on iOS because that's when os_sync_wait_on_address was added and + // we'd like to avoid any potential App Store issues by using the private ulock_* there. + bc->minimum_os_version_string = str_lit("17.4"); + } } - if (subtarget == Subtarget_Default) { + if (subtarget == Subtarget_iPhoneSimulator) { + // For the iPhoneSimulator subtarget, the version must be between 'ios' and '-simulator'. + String suffix = str_lit("-simulator"); + GB_ASSERT(string_ends_with(bc->metrics.target_triplet, suffix)); + + String prefix = substring(bc->metrics.target_triplet, 0, bc->metrics.target_triplet.len - suffix.len); + bc->metrics.target_triplet = concatenate3_strings(permanent_allocator(), prefix, bc->minimum_os_version_string, suffix); + } else { bc->metrics.target_triplet = concatenate_strings(permanent_allocator(), bc->metrics.target_triplet, bc->minimum_os_version_string); } + } else if (selected_subtarget == Subtarget_Android) { + init_android_values(bc->build_mode == BuildMode_Executable && (bc->command_kind & Command__does_build) != 0); } if (!bc->custom_optimization_level) { @@ -1731,12 +2010,6 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta } - // TODO: Static map calls are bugged on `amd64sysv` abi. - if (bc->metrics.os != TargetOs_windows && bc->metrics.arch == TargetArch_amd64) { - // ENFORCE DYNAMIC MAP CALLS - bc->dynamic_map_calls = true; - } - bc->ODIN_VALGRIND_SUPPORT = false; if (build_context.metrics.os != TargetOs_windows) { switch (bc->metrics.arch) { @@ -1842,6 +2115,39 @@ gb_internal bool check_target_feature_is_superset_of(String const &superset, Str return true; } +gb_internal String infer_object_extension_from_build_context() { + String output_extension = {}; + if (is_arch_wasm()) { + output_extension = STR_LIT("wasm.o"); + } else { + switch (build_context.metrics.os) { + case TargetOs_windows: + output_extension = STR_LIT("obj"); + break; + default: + case TargetOs_darwin: + case TargetOs_linux: + case TargetOs_essence: + output_extension = STR_LIT("o"); + break; + + case TargetOs_freestanding: + switch (build_context.metrics.abi) { + default: + case TargetABI_Default: + case TargetABI_SysV: + output_extension = STR_LIT("o"); + break; + case TargetABI_Win64: + output_extension = STR_LIT("obj"); + break; + } + break; + } + } + return output_extension; +} + // NOTE(Jeroen): Set/create the output and other paths and report an error as appropriate. // We've previously called `parse_build_flags`, so `out_filepath` should be set. gb_internal bool init_build_paths(String init_filename) { @@ -1885,10 +2191,6 @@ gb_internal bool init_build_paths(String init_filename) { } } - if (bc->pdb_filepath.len > 0) { - bc->build_paths[BuildPath_PDB] = path_from_string(ha, bc->pdb_filepath); - } - if ((bc->command_kind & Command__does_build) && (!bc->ignore_microsoft_magic)) { // NOTE(ic): It would be nice to extend this so that we could specify the Visual Studio version that we want instead of defaulting to the latest. Find_Result find_result = find_visual_studio_and_windows_sdk(); @@ -1947,7 +2249,10 @@ gb_internal bool init_build_paths(String init_filename) { output_extension = make_string(nullptr, 0); String const single_file_extension = str_lit(".odin"); - if (build_context.metrics.os == TargetOs_windows) { + if (selected_subtarget == Subtarget_Android) { + // NOTE(bill): It's always shared! + output_extension = STR_LIT("so"); + } else if (build_context.metrics.os == TargetOs_windows) { output_extension = STR_LIT("exe"); } else if (build_context.cross_compiling && selected_target_metrics->metrics == &target_essence_amd64) { // Do nothing: we don't want the .bin extension @@ -1975,13 +2280,8 @@ gb_internal bool init_build_paths(String init_filename) { if (build_context.metrics.os == TargetOs_windows) { output_extension = STR_LIT("lib"); } - }else if (build_context.build_mode == BuildMode_Object) { - // By default use a .o object extension. - output_extension = STR_LIT("o"); - - if (build_context.metrics.os == TargetOs_windows) { - output_extension = STR_LIT("obj"); - } + } else if (build_context.build_mode == BuildMode_Object) { + output_extension = infer_object_extension_from_build_context(); } else if (build_context.build_mode == BuildMode_Assembly) { // By default use a .S asm extension. output_extension = STR_LIT("S"); @@ -2001,7 +2301,7 @@ gb_internal bool init_build_paths(String init_filename) { return false; } else if (bc->build_paths[BuildPath_Output].ext.len == 0) { gb_printf_err("Output path %.*s must have an appropriate extension.\n", LIT(output_file)); - return false; + return false; } } } else { @@ -2027,11 +2327,34 @@ gb_internal bool init_build_paths(String init_filename) { while (output_name.len > 0 && (output_name[output_name.len-1] == '/' || output_name[output_name.len-1] == '\\')) { output_name.len -= 1; } + // Only trim the extension if it's an Odin source file. + // This lets people build folders with extensions or files beginning with dots. + if (path_extension(output_name) == ".odin" && !path_is_directory(output_name)) { + output_name = remove_extension_from_path(output_name); + } output_name = remove_directory_from_path(output_name); - output_name = remove_extension_from_path(output_name); output_name = copy_string(ha, string_trim_whitespace(output_name)); - output_path = path_from_string(ha, output_name); - + // This is `path_from_string` without the extension trimming. + Path res = {}; + if (output_name.len > 0) { + String fullpath = path_to_full_path(ha, output_name); + defer (gb_free(ha, fullpath.text)); + + res.basename = directory_from_path(fullpath); + res.basename = copy_string(ha, res.basename); + + if (path_is_directory(fullpath)) { + if (res.basename.len > 0 && res.basename.text[res.basename.len - 1] == '/') { + res.basename.len--; + } + } else { + isize name_start = (res.basename.len > 0) ? res.basename.len + 1 : res.basename.len; + res.name = substring(fullpath, name_start, fullpath.len); + res.name = copy_string(ha, res.name); + } + } + output_path = res; + // Note(Dragos): This is a fix for empty filenames // Turn the trailing folder into the file name if (output_path.name.len == 0) { @@ -2061,6 +2384,26 @@ gb_internal bool init_build_paths(String init_filename) { bc->build_paths[BuildPath_Output] = output_path; } + if (build_context.ODIN_DEBUG) { + if (build_context.metrics.os == TargetOs_windows) { + if (bc->pdb_filepath.len > 0) { + bc->build_paths[BuildPath_Symbols] = path_from_string(ha, bc->pdb_filepath); + } else { + Path symbol_path; + symbol_path.basename = copy_string(ha, bc->build_paths[BuildPath_Output].basename); + symbol_path.name = copy_string(ha, bc->build_paths[BuildPath_Output].name); + symbol_path.ext = copy_string(ha, STR_LIT("pdb")); + bc->build_paths[BuildPath_Symbols] = symbol_path; + } + } else if (build_context.metrics.os == TargetOs_darwin) { + Path symbol_path; + symbol_path.basename = copy_string(ha, bc->build_paths[BuildPath_Output].basename); + symbol_path.name = copy_string(ha, bc->build_paths[BuildPath_Output].name); + symbol_path.ext = copy_string(ha, STR_LIT("dSYM")); + bc->build_paths[BuildPath_Symbols] = symbol_path; + } + } + // Do we have an extension? We might not if the output filename was supplied. if (bc->build_paths[BuildPath_Output].ext.len == 0) { if (build_context.metrics.os == TargetOs_windows || is_arch_wasm() || build_context.build_mode != BuildMode_Executable) { @@ -2096,9 +2439,10 @@ gb_internal bool init_build_paths(String init_filename) { case TargetOs_windows: case TargetOs_linux: case TargetOs_darwin: + case TargetOs_freebsd: break; default: - gb_printf_err("-sanitize:address is only supported on windows, linux, and darwin\n"); + gb_printf_err("-sanitize:address is only supported on Windows, Linux, Darwin, and FreeBSD\n"); return false; } } @@ -2106,12 +2450,10 @@ gb_internal bool init_build_paths(String init_filename) { if (build_context.sanitizer_flags & SanitizerFlag_Memory) { switch (build_context.metrics.os) { case TargetOs_linux: + case TargetOs_freebsd: break; default: - gb_printf_err("-sanitize:memory is only supported on linux\n"); - return false; - } - if (build_context.metrics.os != TargetOs_linux) { + gb_printf_err("-sanitize:memory is only supported on Linux and FreeBSD\n"); return false; } } @@ -2120,9 +2462,10 @@ gb_internal bool init_build_paths(String init_filename) { switch (build_context.metrics.os) { case TargetOs_linux: case TargetOs_darwin: + case TargetOs_freebsd: break; default: - gb_printf_err("-sanitize:thread is only supported on linux and darwin\n"); + gb_printf_err("-sanitize:thread is only supported on Linux, Darwin, and FreeBSD\n"); return false; } } |