From f80e73e036706cd731dc4ea39e0d2ab84e066292 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Wed, 19 Mar 2025 21:18:31 +0100 Subject: few llvm 20 changes --- src/build_settings.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 08df34c57..6bee10674 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -109,6 +109,12 @@ gb_global String target_arch_names[TargetArch_COUNT] = { str_lit("riscv64"), }; +#if defined(GB_SYSTEM_WINDOWS) + #include +#else + #include +#endif + #include "build_settings_microarch.cpp" gb_global String target_endian_names[TargetEndian_COUNT] = { @@ -544,12 +550,6 @@ gb_internal isize MAX_ERROR_COLLECTOR_COUNT(void) { return build_context.max_error_count; } -#if defined(GB_SYSTEM_WINDOWS) - #include -#else - #include -#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 -- cgit v1.2.3 From e6718fcfcc979cedcdb01294003431519e7785f3 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Mar 2025 13:09:39 +0000 Subject: Very very rudimentary support for `-target:linux_arm64 -subtarget:android` --- src/build_settings.cpp | 39 +++++++++++- src/checker.cpp | 1 + src/linker.cpp | 167 ++++++++++++++++++++++++++++++++++++++++++++++--- src/main.cpp | 5 +- 4 files changed, 199 insertions(+), 13 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 6bee10674..30e29ab73 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -171,6 +171,7 @@ struct TargetMetrics { enum Subtarget : u32 { Subtarget_Default, Subtarget_iOS, + Subtarget_Android, Subtarget_COUNT, }; @@ -178,6 +179,7 @@ enum Subtarget : u32 { gb_global String subtarget_strings[Subtarget_COUNT] = { str_lit(""), str_lit("ios"), + str_lit("android"), }; @@ -946,6 +948,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); @@ -1652,6 +1662,15 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta default: GB_PANIC("Unknown architecture for darwin"); } + } else if (metrics->os == TargetOs_linux && subtarget == Subtarget_Android) { + switch (metrics->arch) { + case TargetArch_arm64: + bc->metrics.target_triplet = str_lit("aarch64-none-linux-android"); + bc->reloc_mode = RelocMode_PIC; + break; + default: + GB_PANIC("Unknown architecture for darwin"); + } } if (bc->metrics.os == TargetOs_windows) { @@ -1749,6 +1768,22 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta if (bc->metrics.os == TargetOs_freestanding) { bc->ODIN_DEFAULT_TO_NIL_ALLOCATOR = !bc->ODIN_DEFAULT_TO_PANIC_ALLOCATOR; } + + if (subtarget == Subtarget_Android) { + switch (build_context.build_mode) { + case BuildMode_DynamicLibrary: + break; + case BuildMode_Executable: + case BuildMode_StaticLibrary: + case BuildMode_Object: + case BuildMode_Assembly: + case BuildMode_LLVM_IR: + gb_printf_err("Unsupported -build-mode for -target:android\n"); + gb_printf_err("\tCurrently only supporting -build-mode:shared\n"); + gb_exit(1); + break; + } + } } #if defined(GB_SYSTEM_WINDOWS) @@ -1947,7 +1982,9 @@ 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) { + output_extension = STR_LIT("bin"); + } 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 diff --git a/src/checker.cpp b/src/checker.cpp index 9d822073f..c44c6ce5b 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1149,6 +1149,7 @@ gb_internal void init_universal(void) { GlobalEnumValue values[Subtarget_COUNT] = { {"Default", Subtarget_Default}, {"iOS", Subtarget_iOS}, + {"Android", Subtarget_Android}, }; auto fields = add_global_enum_type(str_lit("Odin_Platform_Subtarget_Type"), values, gb_count_of(values)); diff --git a/src/linker.cpp b/src/linker.cpp index 1568d049e..5e2720eeb 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -130,6 +130,9 @@ gb_internal i32 linker_stage(LinkerData *gen) { return result; } + bool is_cross_linking = false; + bool is_android = false; + if (build_context.cross_compiling && selected_target_metrics->metrics == &target_essence_amd64) { #if defined(GB_SYSTEM_UNIX) result = system_exec_command_line_app("linker", "x86_64-essence-gcc \"%.*s.o\" -o \"%.*s\" %.*s %.*s", @@ -141,12 +144,22 @@ gb_internal i32 linker_stage(LinkerData *gen) { ); #endif } else if (build_context.cross_compiling && build_context.different_os) { - gb_printf_err("Linking for cross compilation for this platform is not yet supported (%.*s %.*s)\n", - LIT(target_os_names[build_context.metrics.os]), - LIT(target_arch_names[build_context.metrics.arch]) - ); - build_context.keep_object_files = true; + switch (selected_subtarget) { + case Subtarget_Android: + is_cross_linking = true; + is_android = true; + goto try_cross_linking; + default: + gb_printf_err("Linking for cross compilation for this platform is not yet supported (%.*s %.*s)\n", + LIT(target_os_names[build_context.metrics.os]), + LIT(target_arch_names[build_context.metrics.arch]) + ); + build_context.keep_object_files = true; + break; + } } else { +try_cross_linking:; + #if defined(GB_SYSTEM_WINDOWS) bool is_windows = build_context.metrics.os == TargetOs_windows; #else @@ -155,6 +168,7 @@ gb_internal i32 linker_stage(LinkerData *gen) { bool is_osx = build_context.metrics.os == TargetOs_darwin; + if (is_windows) { String section_name = str_lit("msvc-link"); switch (build_context.linker_choice) { @@ -404,6 +418,44 @@ gb_internal i32 linker_stage(LinkerData *gen) { } else { timings_start_section(timings, str_lit("ld-link")); + String ODIN_ANDROID_NDK_PATH = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK_PATH", permanent_allocator())), NIX_SEPARATOR_STRING); + String ODIN_ANDROID_NDK_TOOLCHAIN_PATH = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK_TOOLCHAIN_PATH", permanent_allocator())), NIX_SEPARATOR_STRING); + + int ODIN_ANDROID_API_LEVEL = 34; + if (char const *found = gb_get_env("ODIN_ANDROID_API_LEVEL", permanent_allocator())) { + int new_level = atoi(found); + if (new_level >= 34) { + ODIN_ANDROID_API_LEVEL = new_level; + } else { + gb_printf_err("Warning: Invalid ODIN_ANDROID_API_LEVEL '%s', defaulting to %d\n", found, ODIN_ANDROID_API_LEVEL); + } + } + + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH = {}; + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH = {}; + String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH = {}; + + if (is_android) { + if (ODIN_ANDROID_NDK_PATH.len == 0) { + gb_printf_err("Error: ODIN_ANDROID_NDK_PATH not set"); + return 1; + } + + if (ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len == 0) { + gb_printf_err("Error: ODIN_ANDROID_NDK_PATH not set"); + return 1; + } + + ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH = concatenate_strings(permanent_allocator(), ODIN_ANDROID_NDK_TOOLCHAIN_PATH, str_lit("sysroot/usr/lib/aarch64-linux-android/")); + + char buf[32] = {}; + gb_snprintf(buf, gb_size_of(buf), "%d/", ODIN_ANDROID_API_LEVEL); + ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH = concatenate_strings(permanent_allocator(), ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH, make_string_c(buf)); + + ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH = concatenate_strings(permanent_allocator(), ODIN_ANDROID_NDK_TOOLCHAIN_PATH, str_lit("sysroot/")); + } + + // Link using `clang`, unless overridden by `ODIN_CLANG_PATH` environment variable. const char* clang_path = gb_get_env("ODIN_CLANG_PATH", permanent_allocator()); if (clang_path == NULL) { @@ -412,8 +464,11 @@ gb_internal i32 linker_stage(LinkerData *gen) { // NOTE(vassvik): needs to add the root to the library search paths, so that the full filenames of the library // files can be passed with -l: - gbString lib_str = gb_string_make(heap_allocator(), "-L/"); + gbString lib_str = gb_string_make(heap_allocator(), ""); defer (gb_string_free(lib_str)); + #if !defined(GB_SYSTEM_WINDOWS) + lib_str = gb_string_appendc(lib_str, "-L/ "); + #endif StringSet asm_files = {}; string_set_init(&asm_files, 64); @@ -602,6 +657,74 @@ gb_internal i32 linker_stage(LinkerData *gen) { gbString object_files = gb_string_make(heap_allocator(), ""); defer (gb_string_free(object_files)); + + + if (is_android) { // NOTE(bill): glue code needed for Android + String android_glue_object = {}; + String android_glue_static_lib = {}; + + char hash_buf[64] = {}; + gb_snprintf(hash_buf, gb_size_of(hash_buf), "%p", &hash_buf); + String hash = make_string_c(hash_buf); + + String temp_dir = normalize_path(temporary_allocator(), temporary_directory(temporary_allocator()), NIX_SEPARATOR_STRING); + android_glue_object = concatenate4_strings(temporary_allocator(), temp_dir, str_lit("android_native_app_glue-"), hash, str_lit(".o")); + android_glue_static_lib = concatenate4_strings(permanent_allocator(), temp_dir, str_lit("libandroid_native_app_glue-"), hash, str_lit(".a")); + + gbString glue = gb_string_make(heap_allocator(), clang_path); + defer (gb_string_free(glue)); + + glue = gb_string_append_fmt(glue, " --target=aarch64-linux-android%d ", ODIN_ANDROID_API_LEVEL); + glue = gb_string_appendc(glue, "-c \""); + glue = gb_string_append_length(glue, ODIN_ANDROID_NDK_PATH.text, ODIN_ANDROID_NDK_PATH.len); + glue = gb_string_appendc(glue, "sources/android/native_app_glue/android_native_app_glue.c"); + glue = gb_string_appendc(glue, "\" "); + glue = gb_string_appendc(glue, "-o \""); + glue = gb_string_append_length(glue, android_glue_object.text, android_glue_object.len); + glue = gb_string_appendc(glue, "\" "); + + glue = gb_string_appendc(glue, "\"-I"); + glue = gb_string_append_length(glue, ODIN_ANDROID_NDK_TOOLCHAIN_PATH.text, ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len); + glue = gb_string_appendc(glue, "sysroot/usr/include/"); + glue = gb_string_appendc(glue, "\" "); + + glue = gb_string_appendc(glue, "\"-I"); + glue = gb_string_append_length(glue, ODIN_ANDROID_NDK_TOOLCHAIN_PATH.text, ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len); + glue = gb_string_appendc(glue, "sysroot/usr/include/aarch64-linux-android/"); + glue = gb_string_appendc(glue, "\" "); + + + glue = gb_string_appendc(glue, "-Wno-macro-redefined "); + + result = system_exec_command_line_app("android-native-app-glue-compile", glue); + if (result) { + return result; + } + + gbString ar = gb_string_make_length(heap_allocator(), ODIN_ANDROID_NDK_TOOLCHAIN_PATH.text, ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len); + defer (gb_string_free(ar)); + + ar = gb_string_appendc(ar, "bin/llvm-ar"); + + ar = gb_string_appendc(ar, " rcs "); + + ar = gb_string_appendc(ar, "\""); + ar = gb_string_append_length(ar, android_glue_static_lib.text, android_glue_static_lib.len); + ar = gb_string_appendc(ar, "\" "); + + ar = gb_string_appendc(ar, "\""); + ar = gb_string_append_length(ar, android_glue_object.text, android_glue_object.len); + ar = gb_string_appendc(ar, "\" "); + + result = system_exec_command_line_app("android-native-app-glue-ar", ar); + if (result) { + return result; + } + + object_files = gb_string_append_fmt(object_files, "\"%.*s\" ", LIT(android_glue_static_lib)); + } + + for (String object_path : gen->output_object_paths) { object_files = gb_string_append_fmt(object_files, "\"%.*s\" ", LIT(object_path)); } @@ -654,6 +777,7 @@ gb_internal i32 linker_stage(LinkerData *gen) { if (build_context.metrics.os != TargetOs_openbsd && build_context.metrics.os != TargetOs_haiku && build_context.metrics.arch != TargetArch_riscv64 + && !is_android ) { // OpenBSD and Haiku default to PIE executable. do not pass -no-pie for it. link_settings = gb_string_appendc(link_settings, "-no-pie "); @@ -687,30 +811,53 @@ gb_internal i32 linker_stage(LinkerData *gen) { } } + if (is_android) { + GB_ASSERT(ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH.len != 0); + GB_ASSERT(ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH.len != 0); + GB_ASSERT(ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH.len != 0); + + platform_lib_str = gb_string_appendc(platform_lib_str, "\"-L"); + platform_lib_str = gb_string_append_length(platform_lib_str, ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH.text, ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH.len); + platform_lib_str = gb_string_appendc(platform_lib_str, "\" "); + + platform_lib_str = gb_string_appendc(platform_lib_str, "\"--sysroot="); + platform_lib_str = gb_string_append_length(platform_lib_str, ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH.text, ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH.len); + platform_lib_str = gb_string_appendc(platform_lib_str, "\" "); + + link_settings = gb_string_appendc(link_settings, "-u ANativeActivity_onCreate "); + } + if (!build_context.no_rpath) { // Set the rpath to the $ORIGIN/@loader_path (the path of the executable), // so that dynamic libraries are looked for at that path. if (build_context.metrics.os == TargetOs_darwin) { link_settings = gb_string_appendc(link_settings, "-Wl,-rpath,@loader_path "); } else { - link_settings = gb_string_appendc(link_settings, "-Wl,-rpath,\\$ORIGIN "); + if (is_android) { + // ignore + } else { + link_settings = gb_string_appendc(link_settings, "-Wl,-rpath,\\$ORIGIN "); + } } } if (!build_context.no_crt) { - platform_lib_str = gb_string_appendc(platform_lib_str, "-lm "); + lib_str = gb_string_appendc(lib_str, "-lm "); if (build_context.metrics.os == TargetOs_darwin) { // NOTE: adding this causes a warning about duplicate libraries, I think it is // automatically assumed/added by clang when you don't do `-nostdlib`. - // platform_lib_str = gb_string_appendc(platform_lib_str, "-lSystem "); + // lib_str = gb_string_appendc(lib_str, "-lSystem "); } else { - platform_lib_str = gb_string_appendc(platform_lib_str, "-lc "); + lib_str = gb_string_appendc(lib_str, "-lc "); } } gbString link_command_line = gb_string_make(heap_allocator(), clang_path); defer (gb_string_free(link_command_line)); + if (is_android) { + link_command_line = gb_string_append_fmt(link_command_line, " --target=aarch64-linux-android%d ", ODIN_ANDROID_API_LEVEL); + } link_command_line = gb_string_appendc(link_command_line, " -Wno-unused-command-line-argument "); link_command_line = gb_string_appendc(link_command_line, object_files); link_command_line = gb_string_append_fmt(link_command_line, " -o \"%.*s\" ", LIT(output_filename)); diff --git a/src/main.cpp b/src/main.cpp index 289a6150a..3549eb277 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1105,8 +1105,9 @@ gb_internal bool parse_build_flags(Array args) { String str = value.value_string; bool found = false; - if (selected_target_metrics->metrics->os != TargetOs_darwin) { - gb_printf_err("-subtarget can only be used with darwin based targets at the moment\n"); + if (selected_target_metrics->metrics->os != TargetOs_darwin && + selected_target_metrics->metrics->os != TargetOs_linux ) { + gb_printf_err("-subtarget can only be used with darwin and linux based targets at the moment\n"); bad_flags = true; break; } -- cgit v1.2.3 From dfd0f18f47cb1eeafe43fe341963095ef6fd0cbc Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Mar 2025 13:19:40 +0000 Subject: Allow `check` for `-subtarget:android` --- src/build_settings.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 30e29ab73..7d864c26b 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1772,15 +1772,21 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta if (subtarget == Subtarget_Android) { switch (build_context.build_mode) { case BuildMode_DynamicLibrary: - break; - case BuildMode_Executable: - case BuildMode_StaticLibrary: case BuildMode_Object: case BuildMode_Assembly: case BuildMode_LLVM_IR: - gb_printf_err("Unsupported -build-mode for -target:android\n"); - gb_printf_err("\tCurrently only supporting -build-mode:shared\n"); - gb_exit(1); + break; + case BuildMode_Executable: + case BuildMode_StaticLibrary: + if ((build_context.command_kind & Command__does_build) != 0) { + gb_printf_err("Unsupported -build-mode for -target:android\n"); + gb_printf_err("\tCurrently only supporting: \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; } } -- cgit v1.2.3 From db82a49576c8e691cf938f7a2a86446f14b73f7c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Mar 2025 13:30:18 +0000 Subject: Fix typos --- src/build_settings.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 7d864c26b..0e040a4e6 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1669,7 +1669,7 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta bc->reloc_mode = RelocMode_PIC; break; default: - GB_PANIC("Unknown architecture for darwin"); + GB_PANIC("Unknown architecture for -subtarget:android"); } } @@ -1779,7 +1779,7 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta case BuildMode_Executable: case BuildMode_StaticLibrary: if ((build_context.command_kind & Command__does_build) != 0) { - gb_printf_err("Unsupported -build-mode for -target:android\n"); + gb_printf_err("Unsupported -build-mode for -subtarget:android\n"); gb_printf_err("\tCurrently only supporting: \n"); gb_printf_err("\t\tshared\n"); gb_printf_err("\t\tobject\n"); -- cgit v1.2.3 From d48e7bb0b89d19a9b5b66b5b6f35852125bd3afe Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Mar 2025 16:05:21 +0000 Subject: Migrate `ODIN_ANDROID_*` constants to `build_settings.cpp`; `-minimum-os-version:` for `-subtarget:android` --- src/build_settings.cpp | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/linker.cpp | 42 +++++------------------------ 2 files changed, 77 insertions(+), 36 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 0e040a4e6..b61121976 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -529,6 +529,14 @@ struct BuildContext { String minimum_os_version_string; bool minimum_os_version_string_given; + + + int ODIN_ANDROID_API_LEVEL; + String ODIN_ANDROID_NDK_PATH; + String ODIN_ANDROID_NDK_TOOLCHAIN_PATH; + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH; + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH; + String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH; }; gb_global BuildContext build_context = {0}; @@ -1725,6 +1733,69 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta if (subtarget == Subtarget_Default) { bc->metrics.target_triplet = concatenate_strings(permanent_allocator(), bc->metrics.target_triplet, bc->minimum_os_version_string); } + } else if (selected_subtarget == Subtarget_Android) { + 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_PATH = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK_PATH", permanent_allocator())), NIX_SEPARATOR_STRING); + bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK_TOOLCHAIN_PATH", permanent_allocator())), NIX_SEPARATOR_STRING); + + if (bc->ODIN_ANDROID_NDK_PATH.len != 0 && bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH.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_PATH = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK_PATH, 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_PATH = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK_PATH, str_lit("toolchains/llvm/prebuilt/"), str_lit("darwin-"), arch); + #elif defined(GB_SYSTEM_LINUX) + bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK_PATH, str_lit("toolchains/llvm/prebuilt/"), str_lit("linux-"), arch); + #endif + + bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH = normalize_path(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH, NIX_SEPARATOR_STRING); + } + + if (bc->ODIN_ANDROID_NDK_PATH.len == 0) { + gb_printf_err("Error: ODIN_ANDROID_NDK_PATH not set"); + gb_exit(1); + + } + + if (bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len == 0) { + gb_printf_err("Error: ODIN_ANDROID_NDK_PATH not set"); + gb_exit(1); + } + + bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH, 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_PATH = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH, make_string_c(buf)); + + bc->ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH, str_lit("sysroot/")); } if (!bc->custom_optimization_level) { diff --git a/src/linker.cpp b/src/linker.cpp index ea0abc5f3..1e6f045b1 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -418,43 +418,13 @@ try_cross_linking:; } else { timings_start_section(timings, str_lit("ld-link")); - String ODIN_ANDROID_NDK_PATH = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK_PATH", permanent_allocator())), NIX_SEPARATOR_STRING); - String ODIN_ANDROID_NDK_TOOLCHAIN_PATH = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK_TOOLCHAIN_PATH", permanent_allocator())), NIX_SEPARATOR_STRING); - - int ODIN_ANDROID_API_LEVEL = 34; - if (char const *found = gb_get_env("ODIN_ANDROID_API_LEVEL", permanent_allocator())) { - int new_level = atoi(found); - if (new_level >= 34) { - ODIN_ANDROID_API_LEVEL = new_level; - } else { - gb_printf_err("Warning: Invalid ODIN_ANDROID_API_LEVEL '%s', defaulting to %d\n", found, ODIN_ANDROID_API_LEVEL); - } - } - - String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH = {}; - String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH = {}; - String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH = {}; - - if (is_android) { - if (ODIN_ANDROID_NDK_PATH.len == 0) { - gb_printf_err("Error: ODIN_ANDROID_NDK_PATH not set"); - return 1; - } - - if (ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len == 0) { - gb_printf_err("Error: ODIN_ANDROID_NDK_PATH not set"); - return 1; - } - - ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH = concatenate_strings(permanent_allocator(), ODIN_ANDROID_NDK_TOOLCHAIN_PATH, str_lit("sysroot/usr/lib/aarch64-linux-android/")); - - char buf[32] = {}; - gb_snprintf(buf, gb_size_of(buf), "%d/", ODIN_ANDROID_API_LEVEL); - ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH = concatenate_strings(permanent_allocator(), ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH, make_string_c(buf)); - - ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH = concatenate_strings(permanent_allocator(), ODIN_ANDROID_NDK_TOOLCHAIN_PATH, str_lit("sysroot/")); - } + int const ODIN_ANDROID_API_LEVEL = build_context.ODIN_ANDROID_API_LEVEL; + String ODIN_ANDROID_NDK_PATH = build_context.ODIN_ANDROID_NDK_PATH; + String ODIN_ANDROID_NDK_TOOLCHAIN_PATH = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_PATH; + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH; + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH; + String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH; // Link using `clang`, unless overridden by `ODIN_CLANG_PATH` environment variable. const char* clang_path = gb_get_env("ODIN_CLANG_PATH", permanent_allocator()); -- cgit v1.2.3 From 8e884c6292135f80d9f4700a522313eddfd24f5e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Mar 2025 16:50:35 +0000 Subject: Remove `_PATH` on android environment variables --- src/build_settings.cpp | 96 ++++++++++++++++++++++++++++++-------------------- src/linker.cpp | 28 +++++++-------- 2 files changed, 72 insertions(+), 52 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index b61121976..eff6cef2e 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -217,9 +217,11 @@ enum CommandKind : u32 { Command_strip_semicolon = 1<<8, Command_bug_report = 1<<9, + Command_pkg_android = 1<<16, + 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] = { @@ -532,11 +534,18 @@ struct BuildContext { int ODIN_ANDROID_API_LEVEL; - String ODIN_ANDROID_NDK_PATH; - String ODIN_ANDROID_NDK_TOOLCHAIN_PATH; - String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH; - String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH; - String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH; + + 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_JAR_SIGNER; + String android_keystore; + String android_manifest; }; gb_global BuildContext build_context = {0}; @@ -1734,68 +1743,79 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta bc->metrics.target_triplet = concatenate_strings(permanent_allocator(), bc->metrics.target_triplet, bc->minimum_os_version_string); } } else if (selected_subtarget == Subtarget_Android) { - 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; + + { // 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); - GB_ASSERT(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); + 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); + 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); - bc->ODIN_ANDROID_NDK_PATH = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK_PATH", permanent_allocator())), NIX_SEPARATOR_STRING); - bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_NDK_TOOLCHAIN_PATH", 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_PATH.len != 0 && bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len == 0) { + 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_PATH = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK_PATH, str_lit("toolchains/llvm/prebuilt/"), str_lit("windows-"), arch); + 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_PATH = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK_PATH, str_lit("toolchains/llvm/prebuilt/"), str_lit("darwin-"), arch); + 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_PATH = concatenate4_strings(temporary_allocator(), bc->ODIN_ANDROID_NDK_PATH, str_lit("toolchains/llvm/prebuilt/"), str_lit("linux-"), arch); + 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_PATH = normalize_path(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH, NIX_SEPARATOR_STRING); + bc->ODIN_ANDROID_NDK_TOOLCHAIN = normalize_path(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN, NIX_SEPARATOR_STRING); } - if (bc->ODIN_ANDROID_NDK_PATH.len == 0) { - gb_printf_err("Error: ODIN_ANDROID_NDK_PATH not set"); + if (bc->ODIN_ANDROID_NDK.len == 0) { + gb_printf_err("Error: ODIN_ANDROID_NDK not set"); gb_exit(1); } - if (bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len == 0) { - gb_printf_err("Error: ODIN_ANDROID_NDK_PATH not set"); + if (bc->ODIN_ANDROID_NDK_TOOLCHAIN.len == 0) { + gb_printf_err("Error: ODIN_ANDROID_NDK not set"); gb_exit(1); } - bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH, str_lit("sysroot/usr/lib/aarch64-linux-android/")); + 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_PATH = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH, make_string_c(buf)); + 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_PATH = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN_PATH, str_lit("sysroot/")); + bc->ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN, str_lit("sysroot/")); } if (!bc->custom_optimization_level) { diff --git a/src/linker.cpp b/src/linker.cpp index 1e6f045b1..29dc5afc6 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -420,11 +420,11 @@ try_cross_linking:; int const ODIN_ANDROID_API_LEVEL = build_context.ODIN_ANDROID_API_LEVEL; - String ODIN_ANDROID_NDK_PATH = build_context.ODIN_ANDROID_NDK_PATH; - String ODIN_ANDROID_NDK_TOOLCHAIN_PATH = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_PATH; - String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH; - String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH; - String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH; + String ODIN_ANDROID_NDK = build_context.ODIN_ANDROID_NDK; + String ODIN_ANDROID_NDK_TOOLCHAIN = build_context.ODIN_ANDROID_NDK_TOOLCHAIN; + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_LIB; + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL; + String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT; // Link using `clang`, unless overridden by `ODIN_CLANG_PATH` environment variable. const char* clang_path = gb_get_env("ODIN_CLANG_PATH", permanent_allocator()); @@ -648,7 +648,7 @@ try_cross_linking:; glue = gb_string_append_fmt(glue, " --target=aarch64-linux-android%d ", ODIN_ANDROID_API_LEVEL); glue = gb_string_appendc(glue, "-c \""); - glue = gb_string_append_length(glue, ODIN_ANDROID_NDK_PATH.text, ODIN_ANDROID_NDK_PATH.len); + glue = gb_string_append_length(glue, ODIN_ANDROID_NDK.text, ODIN_ANDROID_NDK.len); glue = gb_string_appendc(glue, "sources/android/native_app_glue/android_native_app_glue.c"); glue = gb_string_appendc(glue, "\" "); glue = gb_string_appendc(glue, "-o \""); @@ -656,12 +656,12 @@ try_cross_linking:; glue = gb_string_appendc(glue, "\" "); glue = gb_string_appendc(glue, "\"-I"); - glue = gb_string_append_length(glue, ODIN_ANDROID_NDK_TOOLCHAIN_PATH.text, ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len); + glue = gb_string_append_length(glue, ODIN_ANDROID_NDK_TOOLCHAIN.text, ODIN_ANDROID_NDK_TOOLCHAIN.len); glue = gb_string_appendc(glue, "sysroot/usr/include/"); glue = gb_string_appendc(glue, "\" "); glue = gb_string_appendc(glue, "\"-I"); - glue = gb_string_append_length(glue, ODIN_ANDROID_NDK_TOOLCHAIN_PATH.text, ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len); + glue = gb_string_append_length(glue, ODIN_ANDROID_NDK_TOOLCHAIN.text, ODIN_ANDROID_NDK_TOOLCHAIN.len); glue = gb_string_appendc(glue, "sysroot/usr/include/aarch64-linux-android/"); glue = gb_string_appendc(glue, "\" "); @@ -675,7 +675,7 @@ try_cross_linking:; TIME_SECTION("Android Native App Glue ar"); - gbString ar = gb_string_make_length(heap_allocator(), ODIN_ANDROID_NDK_TOOLCHAIN_PATH.text, ODIN_ANDROID_NDK_TOOLCHAIN_PATH.len); + gbString ar = gb_string_make_length(heap_allocator(), ODIN_ANDROID_NDK_TOOLCHAIN.text, ODIN_ANDROID_NDK_TOOLCHAIN.len); defer (gb_string_free(ar)); ar = gb_string_appendc(ar, "bin/llvm-ar"); @@ -786,16 +786,16 @@ try_cross_linking:; } if (is_android) { - GB_ASSERT(ODIN_ANDROID_NDK_TOOLCHAIN_LIB_PATH.len != 0); - GB_ASSERT(ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH.len != 0); - GB_ASSERT(ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH.len != 0); + GB_ASSERT(ODIN_ANDROID_NDK_TOOLCHAIN_LIB.len != 0); + GB_ASSERT(ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL.len != 0); + GB_ASSERT(ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT.len != 0); platform_lib_str = gb_string_appendc(platform_lib_str, "\"-L"); - platform_lib_str = gb_string_append_length(platform_lib_str, ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH.text, ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL_PATH.len); + platform_lib_str = gb_string_append_length(platform_lib_str, ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL.text, ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL.len); platform_lib_str = gb_string_appendc(platform_lib_str, "\" "); platform_lib_str = gb_string_appendc(platform_lib_str, "\"--sysroot="); - platform_lib_str = gb_string_append_length(platform_lib_str, ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH.text, ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT_PATH.len); + platform_lib_str = gb_string_append_length(platform_lib_str, ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT.text, ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT.len); platform_lib_str = gb_string_appendc(platform_lib_str, "\" "); link_settings = gb_string_appendc(link_settings, "-u ANativeActivity_onCreate "); -- cgit v1.2.3 From 45ecafd7b1e4f6fd0a5f29ccfefcb9250bb91486 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Mar 2025 17:33:10 +0000 Subject: Really bodgy android packing system for `odin build` --- src/build_settings.cpp | 36 +++++++++++- src/linker.cpp | 148 ++++++++++++++++++++++++++++++++++++++++++++++++- src/main.cpp | 22 ++++++++ 3 files changed, 202 insertions(+), 4 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index eff6cef2e..bb7cb7208 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -543,8 +543,9 @@ struct BuildContext { String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL; String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT; - String ANDROID_JAR_SIGNER; + String ODIN_ANDROID_JAR_SIGNER; String android_keystore; + String android_keystore_alias; String android_manifest; }; @@ -1816,6 +1817,32 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta 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/")); + + + bc->ODIN_ANDROID_JAR_SIGNER = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_JAR_SIGNER", permanent_allocator())), NIX_SEPARATOR_STRING); + if (bc->build_mode == BuildMode_Executable) { + 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->ODIN_ANDROID_JAR_SIGNER.len == 0) { + gb_printf_err("Error: ODIN_ANDROID_JAR_SIGNER 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: has not been set\n"); + gb_exit(1); + } + if (bc->android_keystore_alias.len == 0) { + gb_printf_err("Error: -android-keystore_alias: has not been set\n"); + gb_exit(1); + } + if (bc->android_manifest.len == 0) { + gb_printf_err("Error: -android-manifest: has not been set\n"); + gb_exit(1); + } + } + } if (!bc->custom_optimization_level) { @@ -1862,16 +1889,18 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta if (subtarget == Subtarget_Android) { switch (build_context.build_mode) { + case BuildMode_Executable: case BuildMode_DynamicLibrary: case BuildMode_Object: case BuildMode_Assembly: case BuildMode_LLVM_IR: break; - case BuildMode_Executable: + default: 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"); @@ -2080,7 +2109,8 @@ gb_internal bool init_build_paths(String init_filename) { String const single_file_extension = str_lit(".odin"); if (selected_subtarget == Subtarget_Android) { - output_extension = STR_LIT("bin"); + // 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) { diff --git a/src/linker.cpp b/src/linker.cpp index 29dc5afc6..7c1b045b6 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -742,7 +742,9 @@ try_cross_linking:; link_settings = gb_string_appendc(link_settings, "-Wl,-init,'_odin_entry_point' "); link_settings = gb_string_appendc(link_settings, "-Wl,-fini,'_odin_exit_point' "); } - + } else if (is_android) { + // Always shared even in android! + link_settings = gb_string_appendc(link_settings, "-shared "); } if (build_context.build_mode == BuildMode_Executable && build_context.reloc_mode == RelocMode_PIC) { @@ -866,6 +868,150 @@ try_cross_linking:; return result; } } + if (is_android && build_context.build_mode == BuildMode_Executable) { + String android_sdk_build_tools = concatenate3_strings(temporary_allocator(), + build_context.ODIN_ANDROID_SDK, str_lit("build-tools"), NIX_SEPARATOR_STRING); + + Array list = {}; + ReadDirectoryError rd_err = read_directory(android_sdk_build_tools, &list); + defer (array_free(&list)); + + switch (rd_err) { + case ReadDirectory_InvalidPath: + gb_printf_err("Invalid path: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_NotExists: + gb_printf_err("Path does not exist: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_Permission: + gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_NotDir: + gb_printf_err("Expected a directory for a package, got a file: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_Empty: + gb_printf_err("Empty directory: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_Unknown: + gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(android_sdk_build_tools)); + return 1; + } + + auto possible_valid_dirs = array_make(heap_allocator(), 0, list.count); + defer (array_free(&possible_valid_dirs)); + + + for (FileInfo fi : list) if (fi.is_dir) { + bool all_numbers = true; + for (isize i = 0; i < fi.name.len; i++) { + u8 c = fi.name[i]; + if ('0' <= c && c <= '9') { + // true + } else if (i == 0) { + all_numbers = false; + } else if (c == '.') { + break; + } else { + all_numbers = false; + } + } + + if (all_numbers) { + array_add(&possible_valid_dirs, fi); + } + } + + if (possible_valid_dirs.count == 0) { + gb_printf_err("Unable to find any Android SDK/API Level in %.*s\n", LIT(android_sdk_build_tools)); + return 1; + } + + int *dir_numbers = gb_alloc_array(temporary_allocator(), int, possible_valid_dirs.count); + + char buf[1024] = {}; + for_array(i, possible_valid_dirs) { + FileInfo fi = possible_valid_dirs[i]; + isize n = gb_min(gb_size_of(buf)-1, fi.name.len); + memcpy(buf, fi.name.text, n); + buf[n] = 0; + + dir_numbers[i] = atoi(buf); + } + + isize closest_number_idx = -1; + for (isize i = 0; i < possible_valid_dirs.count; i++) { + if (dir_numbers[i] >= ODIN_ANDROID_API_LEVEL) { + if (closest_number_idx < 0) { + closest_number_idx = i; + } else if (dir_numbers[i] < dir_numbers[closest_number_idx]) { + closest_number_idx = i; + } + } + } + + if (closest_number_idx < 0) { + gb_printf_err("Unable to find any Android SDK/API Level in %.*s meeting the minimum API level of %d\n", LIT(android_sdk_build_tools), ODIN_ANDROID_API_LEVEL); + return 1; + } + + String api_number = possible_valid_dirs[closest_number_idx].name; + + android_sdk_build_tools = concatenate_strings(temporary_allocator(), android_sdk_build_tools, api_number); + String android_sdk_platforms = concatenate_strings(temporary_allocator(), + build_context.ODIN_ANDROID_SDK, + make_string_c(gb_bprintf("platforms/android-%d/", dir_numbers[closest_number_idx])) + ); + + + + android_sdk_build_tools = normalize_path(temporary_allocator(), android_sdk_build_tools, NIX_SEPARATOR_STRING); + android_sdk_platforms = normalize_path(temporary_allocator(), android_sdk_platforms, NIX_SEPARATOR_STRING); + + gbString cmd = gb_string_make(heap_allocator(), ""); + defer (gb_string_free(cmd)); + + TIME_SECTION("Android aapt"); + + cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); + cmd = gb_string_appendc(cmd, "aapt"); + cmd = gb_string_appendc(cmd, " package -f"); + cmd = gb_string_append_fmt(cmd, " -M \"%.*s\"", LIT(build_context.android_manifest)); + cmd = gb_string_append_fmt(cmd, " -I \"%.*sandroid.jar\"", LIT(android_sdk_platforms)); + cmd = gb_string_append_fmt(cmd, " -F \"%.*s.apk-build\"", LIT(output_filename)); + + result = system_exec_command_line_app("android-aapt", cmd); + if (result) { + return result; + } + + TIME_SECTION("Android jarsigner"); + gb_string_clear(cmd); + + cmd = gb_string_append_length(cmd, build_context.ODIN_ANDROID_JAR_SIGNER.text, build_context.ODIN_ANDROID_JAR_SIGNER.len); + cmd = gb_string_append_fmt(cmd, " -storepass android -keystore \"%.*s\" \"%.*s.apk-build\" \"%.*s\"", + LIT(build_context.android_keystore), + LIT(output_filename), + LIT(build_context.android_keystore_alias) + ); + result = system_exec_command_line_app("android-jarsigner", cmd); + if (result) { + return result; + } + + TIME_SECTION("Android zipalign"); + gb_string_clear(cmd); + + cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); + cmd = gb_string_appendc(cmd, "zipalign"); + cmd = gb_string_appendc(cmd, " -f 4"); + cmd = gb_string_append_fmt(cmd, " \"%.*s.apk-build\" \"%.*s.apk\"", LIT(output_filename), LIT(output_filename)); + + + result = system_exec_command_line_app("android-zipalign", cmd); + if (result) { + return result; + } + } } } diff --git a/src/main.cpp b/src/main.cpp index 3549eb277..22121db73 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -408,6 +408,10 @@ enum BuildFlagKind { BuildFlag_Subsystem, #endif + BuildFlag_AndroidKeystore, + BuildFlag_AndroidKeystoreAlias, + BuildFlag_AndroidManifest, + BuildFlag_COUNT, }; @@ -624,6 +628,10 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Subsystem, str_lit("subsystem"), BuildFlagParam_String, Command__does_build); #endif + add_flag(&build_flags, BuildFlag_AndroidKeystore, str_lit("android-keystore"), BuildFlagParam_String, Command__does_build); + add_flag(&build_flags, BuildFlag_AndroidKeystoreAlias, str_lit("android-keystore-alias"), BuildFlagParam_String, Command__does_build); + add_flag(&build_flags, BuildFlag_AndroidManifest, str_lit("android-manifest"), BuildFlagParam_String, Command__does_build); + GB_ASSERT(args.count >= 3); Array flag_args = array_slice(args, 3, args.count); @@ -1638,6 +1646,20 @@ gb_internal bool parse_build_flags(Array args) { } #endif + case BuildFlag_AndroidKeystore: + GB_ASSERT(value.kind == ExactValue_String); + build_context.android_keystore = value.value_string; + break; + + case BuildFlag_AndroidKeystoreAlias: + GB_ASSERT(value.kind == ExactValue_String); + build_context.android_keystore_alias = value.value_string; + break; + + case BuildFlag_AndroidManifest: + GB_ASSERT(value.kind == ExactValue_String); + build_context.android_manifest = value.value_string; + break; } } -- cgit v1.2.3 From 346836a098acbf8a79c6affc06f3a24c35761b8c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Mar 2025 17:45:35 +0000 Subject: Disable `-build-mode:exe` for `-subtarget:android` --- src/build_settings.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index bb7cb7208..1823dc8b0 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1889,18 +1889,18 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta if (subtarget == Subtarget_Android) { switch (build_context.build_mode) { - case BuildMode_Executable: 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\texe\n"); gb_printf_err("\t\tshared\n"); gb_printf_err("\t\tobject\n"); gb_printf_err("\t\tassembly\n"); -- cgit v1.2.3 From f13a075cd197a906fe6d5c500dc4f95244eef902 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 26 Mar 2025 18:03:36 +0000 Subject: Begin work on `odin package-android` command --- src/build_settings.cpp | 217 +++++++++++++++++++++++++----------------------- src/linker.cpp | 146 -------------------------------- src/main.cpp | 24 +++++- src/package_android.cpp | 163 ++++++++++++++++++++++++++++++++++++ 4 files changed, 295 insertions(+), 255 deletions(-) create mode 100644 src/package_android.cpp (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 1823dc8b0..21a692c47 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -209,15 +209,15 @@ enum BuildModeKind { enum CommandKind : u32 { 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_pkg_android = 1<<16, + Command_package_android = 1<<8, 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, @@ -232,6 +232,8 @@ gb_global char const *odin_command_strings[32] = { "version", "test", "strip-semicolon", + "", + "package-android", }; @@ -1489,6 +1491,107 @@ 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) { + gb_printf_err("Error: ODIN_ANDROID_NDK not set"); + gb_exit(1); + + } + + if (bc->ODIN_ANDROID_NDK_TOOLCHAIN.len == 0) { + 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/")); + + + bc->ODIN_ANDROID_JAR_SIGNER = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_JAR_SIGNER", permanent_allocator())), NIX_SEPARATOR_STRING); + 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->ODIN_ANDROID_JAR_SIGNER.len == 0) { + gb_printf_err("Error: ODIN_ANDROID_JAR_SIGNER 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: has not been set\n"); + gb_exit(1); + } + if (bc->android_keystore_alias.len == 0) { + gb_printf_err("Error: -android-keystore_alias: has not been set\n"); + gb_exit(1); + } + if (bc->android_manifest.len == 0) { + gb_printf_err("Error: -android-manifest: 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") { @@ -1744,105 +1847,7 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta bc->metrics.target_triplet = concatenate_strings(permanent_allocator(), bc->metrics.target_triplet, bc->minimum_os_version_string); } } else if (selected_subtarget == Subtarget_Android) { - - { // 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) { - gb_printf_err("Error: ODIN_ANDROID_NDK not set"); - gb_exit(1); - - } - - if (bc->ODIN_ANDROID_NDK_TOOLCHAIN.len == 0) { - 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/")); - - - bc->ODIN_ANDROID_JAR_SIGNER = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_JAR_SIGNER", permanent_allocator())), NIX_SEPARATOR_STRING); - if (bc->build_mode == BuildMode_Executable) { - 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->ODIN_ANDROID_JAR_SIGNER.len == 0) { - gb_printf_err("Error: ODIN_ANDROID_JAR_SIGNER 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: has not been set\n"); - gb_exit(1); - } - if (bc->android_keystore_alias.len == 0) { - gb_printf_err("Error: -android-keystore_alias: has not been set\n"); - gb_exit(1); - } - if (bc->android_manifest.len == 0) { - gb_printf_err("Error: -android-manifest: has not been set\n"); - gb_exit(1); - } - } - + init_android_values(bc->build_mode == BuildMode_Executable); } if (!bc->custom_optimization_level) { diff --git a/src/linker.cpp b/src/linker.cpp index 5880014e1..ed82f2fe9 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -868,152 +868,6 @@ try_cross_linking:; return result; } } - if (is_android && build_context.build_mode == BuildMode_Executable) { - String android_sdk_build_tools = concatenate3_strings(temporary_allocator(), - build_context.ODIN_ANDROID_SDK, str_lit("build-tools"), NIX_SEPARATOR_STRING); - - Array list = {}; - ReadDirectoryError rd_err = read_directory(android_sdk_build_tools, &list); - defer (array_free(&list)); - - switch (rd_err) { - case ReadDirectory_InvalidPath: - gb_printf_err("Invalid path: %.*s\n", LIT(android_sdk_build_tools)); - return 1; - case ReadDirectory_NotExists: - gb_printf_err("Path does not exist: %.*s\n", LIT(android_sdk_build_tools)); - return 1; - case ReadDirectory_Permission: - gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(android_sdk_build_tools)); - return 1; - case ReadDirectory_NotDir: - gb_printf_err("Expected a directory for a package, got a file: %.*s\n", LIT(android_sdk_build_tools)); - return 1; - case ReadDirectory_Empty: - gb_printf_err("Empty directory: %.*s\n", LIT(android_sdk_build_tools)); - return 1; - case ReadDirectory_Unknown: - gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(android_sdk_build_tools)); - return 1; - } - - auto possible_valid_dirs = array_make(heap_allocator(), 0, list.count); - defer (array_free(&possible_valid_dirs)); - - - for (FileInfo fi : list) if (fi.is_dir) { - bool all_numbers = true; - for (isize i = 0; i < fi.name.len; i++) { - u8 c = fi.name[i]; - if ('0' <= c && c <= '9') { - // true - } else if (i == 0) { - all_numbers = false; - } else if (c == '.') { - break; - } else { - all_numbers = false; - } - } - - if (all_numbers) { - array_add(&possible_valid_dirs, fi); - } - } - - if (possible_valid_dirs.count == 0) { - gb_printf_err("Unable to find any Android SDK/API Level in %.*s\n", LIT(android_sdk_build_tools)); - return 1; - } - - int *dir_numbers = gb_alloc_array(temporary_allocator(), int, possible_valid_dirs.count); - - char buf[1024] = {}; - for_array(i, possible_valid_dirs) { - FileInfo fi = possible_valid_dirs[i]; - isize n = gb_min(gb_size_of(buf)-1, fi.name.len); - memcpy(buf, fi.name.text, n); - buf[n] = 0; - - dir_numbers[i] = atoi(buf); - } - - isize closest_number_idx = -1; - for (isize i = 0; i < possible_valid_dirs.count; i++) { - if (dir_numbers[i] >= ODIN_ANDROID_API_LEVEL) { - if (closest_number_idx < 0) { - closest_number_idx = i; - } else if (dir_numbers[i] < dir_numbers[closest_number_idx]) { - closest_number_idx = i; - } - } - } - - if (closest_number_idx < 0) { - gb_printf_err("Unable to find any Android SDK/API Level in %.*s meeting the minimum API level of %d\n", LIT(android_sdk_build_tools), ODIN_ANDROID_API_LEVEL); - return 1; - } - - String api_number = possible_valid_dirs[closest_number_idx].name; - - android_sdk_build_tools = concatenate_strings(temporary_allocator(), android_sdk_build_tools, api_number); - String android_sdk_platforms = concatenate_strings(temporary_allocator(), - build_context.ODIN_ANDROID_SDK, - make_string_c(gb_bprintf("platforms/android-%d/", dir_numbers[closest_number_idx])) - ); - - - - android_sdk_build_tools = normalize_path(temporary_allocator(), android_sdk_build_tools, NIX_SEPARATOR_STRING); - android_sdk_platforms = normalize_path(temporary_allocator(), android_sdk_platforms, NIX_SEPARATOR_STRING); - - gbString cmd = gb_string_make(heap_allocator(), ""); - defer (gb_string_free(cmd)); - - TIME_SECTION("Android aapt"); - - String output_apk = path_remove_extension(output_filename); - - cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); - cmd = gb_string_appendc(cmd, "aapt"); - cmd = gb_string_appendc(cmd, " package -f"); - cmd = gb_string_append_fmt(cmd, " -M \"%.*s\"", LIT(build_context.android_manifest)); - cmd = gb_string_append_fmt(cmd, " -I \"%.*sandroid.jar\"", LIT(android_sdk_platforms)); - cmd = gb_string_append_fmt(cmd, " -F \"%.*s.apk-build\"", LIT(output_apk)); - - result = system_exec_command_line_app("android-aapt", cmd); - if (result) { - return result; - } - - TIME_SECTION("Android jarsigner"); - gb_string_clear(cmd); - - cmd = gb_string_append_length(cmd, build_context.ODIN_ANDROID_JAR_SIGNER.text, build_context.ODIN_ANDROID_JAR_SIGNER.len); - cmd = gb_string_append_fmt(cmd, " -storepass android -keystore \"%.*s\" \"%.*s.apk-build\" \"%.*s\"", - LIT(build_context.android_keystore), - LIT(output_apk), - LIT(build_context.android_keystore_alias) - ); - result = system_exec_command_line_app("android-jarsigner", cmd); - if (result) { - return result; - } - - TIME_SECTION("Android zipalign"); - gb_string_clear(cmd); - - cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); - cmd = gb_string_appendc(cmd, "zipalign"); - cmd = gb_string_appendc(cmd, " -f 4"); - cmd = gb_string_append_fmt(cmd, " \"%.*s.apk-build\" \"%.*s.apk\"", LIT(output_apk), LIT(output_apk)); - - - result = system_exec_command_line_app("android-zipalign", cmd); - if (result) { - return result; - } - } } } diff --git a/src/main.cpp b/src/main.cpp index 22121db73..1456717c5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -74,6 +74,7 @@ gb_global Timings global_timings = {0}; #include "cached.cpp" #include "linker.cpp" +#include "package_android.cpp" #if defined(GB_SYSTEM_WINDOWS) && defined(ODIN_TILDE_BACKEND) #define ALLOW_TILDE 1 @@ -628,9 +629,9 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Subsystem, str_lit("subsystem"), BuildFlagParam_String, Command__does_build); #endif - add_flag(&build_flags, BuildFlag_AndroidKeystore, str_lit("android-keystore"), BuildFlagParam_String, Command__does_build); - add_flag(&build_flags, BuildFlag_AndroidKeystoreAlias, str_lit("android-keystore-alias"), BuildFlagParam_String, Command__does_build); - add_flag(&build_flags, BuildFlag_AndroidManifest, str_lit("android-manifest"), BuildFlagParam_String, Command__does_build); + add_flag(&build_flags, BuildFlag_AndroidKeystore, str_lit("android-keystore"), BuildFlagParam_String, Command__does_build | Command_package_android); + add_flag(&build_flags, BuildFlag_AndroidKeystoreAlias, str_lit("android-keystore-alias"), BuildFlagParam_String, Command__does_build | Command_package_android); + add_flag(&build_flags, BuildFlag_AndroidManifest, str_lit("android-manifest"), BuildFlagParam_String, Command__does_build | Command_package_android); GB_ASSERT(args.count >= 3); @@ -2259,6 +2260,8 @@ gb_internal void print_show_help(String const arg0, String command, String optio } else if (command == "strip-semicolon") { print_usage_line(1, "strip-semicolon"); print_usage_line(2, "Parses and type checks .odin file(s) and then removes unneeded semicolons from the entire project."); + } else if (command == "package-android") { + print_usage_line(1, "package-android Packages directory in a specific layout as an APK"); } bool doc = command == "doc"; @@ -3322,6 +3325,13 @@ int main(int arg_count, char const **arg_ptr) { print_show_help(args[0], args[1], args[2]); return 0; } + } else if (command == "package-android") { + if (args.count < 3) { + usage(args[0]); + return 1; + } + build_context.command_kind = Command_package_android; + init_filename = args[2]; } else if (command == "root") { gb_printf("%.*s", LIT(odin_root_dir())); return 0; @@ -3360,6 +3370,10 @@ int main(int arg_count, char const **arg_ptr) { if (init_filename == "-file") { gb_printf_err("Did you mean `%.*s %.*s -file`?\n", LIT(args[0]), LIT(command)); } else { + if (!gb_file_exists(cast(const char*)init_filename.text)) { + gb_printf_err("The file '%.*s' was not found.\n", LIT(init_filename)); + return 1; + } gb_printf_err("Did you mean `%.*s %.*s %.*s -file`?\n", LIT(args[0]), LIT(command), LIT(init_filename)); } @@ -3393,6 +3407,10 @@ int main(int arg_count, char const **arg_ptr) { return 0; } + if (command == "package-android") { + return package_android(args); + } + // NOTE(bill): add 'shared' directory if it is not already set if (!find_library_collection_path(str_lit("shared"), nullptr)) { add_library_collection(str_lit("shared"), diff --git a/src/package_android.cpp b/src/package_android.cpp new file mode 100644 index 000000000..9e6ddeff1 --- /dev/null +++ b/src/package_android.cpp @@ -0,0 +1,163 @@ +i32 package_android(Array args) { + i32 result = 0; + + init_android_values(/*with_sdk*/true); + + int const ODIN_ANDROID_API_LEVEL = build_context.ODIN_ANDROID_API_LEVEL; + + String ODIN_ANDROID_NDK = build_context.ODIN_ANDROID_NDK; + String ODIN_ANDROID_NDK_TOOLCHAIN = build_context.ODIN_ANDROID_NDK_TOOLCHAIN; + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_LIB; + String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL; + String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT; + + + String android_sdk_build_tools = concatenate3_strings(temporary_allocator(), + build_context.ODIN_ANDROID_SDK, str_lit("build-tools"), NIX_SEPARATOR_STRING); + + Array list = {}; + ReadDirectoryError rd_err = read_directory(android_sdk_build_tools, &list); + defer (array_free(&list)); + + switch (rd_err) { + case ReadDirectory_InvalidPath: + gb_printf_err("Invalid path: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_NotExists: + gb_printf_err("Path does not exist: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_Permission: + gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_NotDir: + gb_printf_err("Expected a directory for a package, got a file: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_Empty: + gb_printf_err("Empty directory: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_Unknown: + gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(android_sdk_build_tools)); + return 1; + } + + auto possible_valid_dirs = array_make(heap_allocator(), 0, list.count); + defer (array_free(&possible_valid_dirs)); + + + for (FileInfo fi : list) if (fi.is_dir) { + bool all_numbers = true; + for (isize i = 0; i < fi.name.len; i++) { + u8 c = fi.name[i]; + if ('0' <= c && c <= '9') { + // true + } else if (i == 0) { + all_numbers = false; + } else if (c == '.') { + break; + } else { + all_numbers = false; + } + } + + if (all_numbers) { + array_add(&possible_valid_dirs, fi); + } + } + + if (possible_valid_dirs.count == 0) { + gb_printf_err("Unable to find any Android SDK/API Level in %.*s\n", LIT(android_sdk_build_tools)); + return 1; + } + + int *dir_numbers = gb_alloc_array(temporary_allocator(), int, possible_valid_dirs.count); + + char buf[1024] = {}; + for_array(i, possible_valid_dirs) { + FileInfo fi = possible_valid_dirs[i]; + isize n = gb_min(gb_size_of(buf)-1, fi.name.len); + memcpy(buf, fi.name.text, n); + buf[n] = 0; + + dir_numbers[i] = atoi(buf); + } + + isize closest_number_idx = -1; + for (isize i = 0; i < possible_valid_dirs.count; i++) { + if (dir_numbers[i] >= ODIN_ANDROID_API_LEVEL) { + if (closest_number_idx < 0) { + closest_number_idx = i; + } else if (dir_numbers[i] < dir_numbers[closest_number_idx]) { + closest_number_idx = i; + } + } + } + + if (closest_number_idx < 0) { + gb_printf_err("Unable to find any Android SDK/API Level in %.*s meeting the minimum API level of %d\n", LIT(android_sdk_build_tools), ODIN_ANDROID_API_LEVEL); + return 1; + } + + String api_number = possible_valid_dirs[closest_number_idx].name; + + android_sdk_build_tools = concatenate_strings(temporary_allocator(), android_sdk_build_tools, api_number); + String android_sdk_platforms = concatenate_strings(temporary_allocator(), + build_context.ODIN_ANDROID_SDK, + make_string_c(gb_bprintf("platforms/android-%d/", dir_numbers[closest_number_idx])) + ); + + + + android_sdk_build_tools = normalize_path(temporary_allocator(), android_sdk_build_tools, NIX_SEPARATOR_STRING); + android_sdk_platforms = normalize_path(temporary_allocator(), android_sdk_platforms, NIX_SEPARATOR_STRING); + + gbString cmd = gb_string_make(heap_allocator(), ""); + defer (gb_string_free(cmd)); + + TIME_SECTION("Android aapt"); + + String output_filename = str_lit("test"); + + String output_apk = path_remove_extension(output_filename); + + cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); + cmd = gb_string_appendc(cmd, "aapt"); + cmd = gb_string_appendc(cmd, " package -f"); + cmd = gb_string_append_fmt(cmd, " -M \"%.*s\"", LIT(build_context.android_manifest)); + cmd = gb_string_append_fmt(cmd, " -I \"%.*sandroid.jar\"", LIT(android_sdk_platforms)); + cmd = gb_string_append_fmt(cmd, " -F \"%.*s.apk-build\"", LIT(output_apk)); + + result = system_exec_command_line_app("android-aapt", cmd); + if (result) { + return result; + } + + TIME_SECTION("Android jarsigner"); + gb_string_clear(cmd); + + cmd = gb_string_append_length(cmd, build_context.ODIN_ANDROID_JAR_SIGNER.text, build_context.ODIN_ANDROID_JAR_SIGNER.len); + cmd = gb_string_append_fmt(cmd, " -storepass android -keystore \"%.*s\" \"%.*s.apk-build\" \"%.*s\"", + LIT(build_context.android_keystore), + LIT(output_apk), + LIT(build_context.android_keystore_alias) + ); + result = system_exec_command_line_app("android-jarsigner", cmd); + if (result) { + return result; + } + + TIME_SECTION("Android zipalign"); + gb_string_clear(cmd); + + cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); + cmd = gb_string_appendc(cmd, "zipalign"); + cmd = gb_string_appendc(cmd, " -f 4"); + cmd = gb_string_append_fmt(cmd, " \"%.*s.apk-build\" \"%.*s.apk\"", LIT(output_apk), LIT(output_apk)); + + + result = system_exec_command_line_app("android-zipalign", cmd); + if (result) { + return result; + } + + return 0; +} -- cgit v1.2.3 From 6689c722adbd5814876a98bb9b39790a42a4aeaa Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 27 Mar 2025 09:26:33 +0000 Subject: `odin package android` --- src/build_settings.cpp | 4 +- src/main.cpp | 34 ++++++---- src/package_android.cpp | 163 ---------------------------------------------- src/package_command.cpp | 169 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 192 insertions(+), 178 deletions(-) delete mode 100644 src/package_android.cpp create mode 100644 src/package_command.cpp (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 21a692c47..bdad1d633 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1547,13 +1547,13 @@ gb_internal void init_android_values(bool with_sdk) { bc->ODIN_ANDROID_NDK_TOOLCHAIN = normalize_path(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN, NIX_SEPARATOR_STRING); } - if (bc->ODIN_ANDROID_NDK.len == 0) { + 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) { + if (bc->ODIN_ANDROID_NDK_TOOLCHAIN.len == 0 && !with_sdk) { gb_printf_err("Error: ODIN_ANDROID_NDK not set"); gb_exit(1); } diff --git a/src/main.cpp b/src/main.cpp index 1456717c5..54018b945 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -74,7 +74,7 @@ gb_global Timings global_timings = {0}; #include "cached.cpp" #include "linker.cpp" -#include "package_android.cpp" +#include "package_command.cpp" #if defined(GB_SYSTEM_WINDOWS) && defined(ODIN_TILDE_BACKEND) #define ALLOW_TILDE 1 @@ -629,9 +629,9 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Subsystem, str_lit("subsystem"), BuildFlagParam_String, Command__does_build); #endif - add_flag(&build_flags, BuildFlag_AndroidKeystore, str_lit("android-keystore"), BuildFlagParam_String, Command__does_build | Command_package_android); - add_flag(&build_flags, BuildFlag_AndroidKeystoreAlias, str_lit("android-keystore-alias"), BuildFlagParam_String, Command__does_build | Command_package_android); - add_flag(&build_flags, BuildFlag_AndroidManifest, str_lit("android-manifest"), BuildFlagParam_String, Command__does_build | Command_package_android); + add_flag(&build_flags, BuildFlag_AndroidKeystore, str_lit("android-keystore"), BuildFlagParam_String, Command_package_android); + add_flag(&build_flags, BuildFlag_AndroidKeystoreAlias, str_lit("android-keystore-alias"), BuildFlagParam_String, Command_package_android); + add_flag(&build_flags, BuildFlag_AndroidManifest, str_lit("android-manifest"), BuildFlagParam_String, Command_package_android); GB_ASSERT(args.count >= 3); @@ -2260,8 +2260,10 @@ gb_internal void print_show_help(String const arg0, String command, String optio } else if (command == "strip-semicolon") { print_usage_line(1, "strip-semicolon"); print_usage_line(2, "Parses and type checks .odin file(s) and then removes unneeded semicolons from the entire project."); - } else if (command == "package-android") { - print_usage_line(1, "package-android Packages directory in a specific layout as an APK"); + } else if (command == "package") { + print_usage_line(1, "package Packages directory in a specific layout for that platform"); + print_usage_line(2, "Supported platforms:"); + print_usage_line(3, "android"); } bool doc = command == "doc"; @@ -3325,13 +3327,19 @@ int main(int arg_count, char const **arg_ptr) { print_show_help(args[0], args[1], args[2]); return 0; } - } else if (command == "package-android") { - if (args.count < 3) { + } else if (command == "package") { + if (args.count < 4) { usage(args[0]); return 1; } - build_context.command_kind = Command_package_android; - init_filename = args[2]; + if (args[2] == "android") { + build_context.command_kind = Command_package_android; + } else { + gb_printf_err("Unknown package command: '%.*s'\n", LIT(args[2])); + usage(args[0]); + return 1; + } + init_filename = args[3]; } else if (command == "root") { gb_printf("%.*s", LIT(odin_root_dir())); return 0; @@ -3366,7 +3374,7 @@ int main(int arg_count, char const **arg_ptr) { } if (!single_file_package) { - gb_printf_err("ERROR: `%.*s %.*s` takes a package as its first argument.\n", LIT(args[0]), LIT(command)); + gb_printf_err("ERROR: `%.*s %.*s` takes a package/directory as its first argument.\n", LIT(args[0]), LIT(command)); if (init_filename == "-file") { gb_printf_err("Did you mean `%.*s %.*s -file`?\n", LIT(args[0]), LIT(command)); } else { @@ -3407,8 +3415,8 @@ int main(int arg_count, char const **arg_ptr) { return 0; } - if (command == "package-android") { - return package_android(args); + if (command == "package") { + return package(init_filename); } // NOTE(bill): add 'shared' directory if it is not already set diff --git a/src/package_android.cpp b/src/package_android.cpp deleted file mode 100644 index 9e6ddeff1..000000000 --- a/src/package_android.cpp +++ /dev/null @@ -1,163 +0,0 @@ -i32 package_android(Array args) { - i32 result = 0; - - init_android_values(/*with_sdk*/true); - - int const ODIN_ANDROID_API_LEVEL = build_context.ODIN_ANDROID_API_LEVEL; - - String ODIN_ANDROID_NDK = build_context.ODIN_ANDROID_NDK; - String ODIN_ANDROID_NDK_TOOLCHAIN = build_context.ODIN_ANDROID_NDK_TOOLCHAIN; - String ODIN_ANDROID_NDK_TOOLCHAIN_LIB = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_LIB; - String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL; - String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT = build_context.ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT; - - - String android_sdk_build_tools = concatenate3_strings(temporary_allocator(), - build_context.ODIN_ANDROID_SDK, str_lit("build-tools"), NIX_SEPARATOR_STRING); - - Array list = {}; - ReadDirectoryError rd_err = read_directory(android_sdk_build_tools, &list); - defer (array_free(&list)); - - switch (rd_err) { - case ReadDirectory_InvalidPath: - gb_printf_err("Invalid path: %.*s\n", LIT(android_sdk_build_tools)); - return 1; - case ReadDirectory_NotExists: - gb_printf_err("Path does not exist: %.*s\n", LIT(android_sdk_build_tools)); - return 1; - case ReadDirectory_Permission: - gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(android_sdk_build_tools)); - return 1; - case ReadDirectory_NotDir: - gb_printf_err("Expected a directory for a package, got a file: %.*s\n", LIT(android_sdk_build_tools)); - return 1; - case ReadDirectory_Empty: - gb_printf_err("Empty directory: %.*s\n", LIT(android_sdk_build_tools)); - return 1; - case ReadDirectory_Unknown: - gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(android_sdk_build_tools)); - return 1; - } - - auto possible_valid_dirs = array_make(heap_allocator(), 0, list.count); - defer (array_free(&possible_valid_dirs)); - - - for (FileInfo fi : list) if (fi.is_dir) { - bool all_numbers = true; - for (isize i = 0; i < fi.name.len; i++) { - u8 c = fi.name[i]; - if ('0' <= c && c <= '9') { - // true - } else if (i == 0) { - all_numbers = false; - } else if (c == '.') { - break; - } else { - all_numbers = false; - } - } - - if (all_numbers) { - array_add(&possible_valid_dirs, fi); - } - } - - if (possible_valid_dirs.count == 0) { - gb_printf_err("Unable to find any Android SDK/API Level in %.*s\n", LIT(android_sdk_build_tools)); - return 1; - } - - int *dir_numbers = gb_alloc_array(temporary_allocator(), int, possible_valid_dirs.count); - - char buf[1024] = {}; - for_array(i, possible_valid_dirs) { - FileInfo fi = possible_valid_dirs[i]; - isize n = gb_min(gb_size_of(buf)-1, fi.name.len); - memcpy(buf, fi.name.text, n); - buf[n] = 0; - - dir_numbers[i] = atoi(buf); - } - - isize closest_number_idx = -1; - for (isize i = 0; i < possible_valid_dirs.count; i++) { - if (dir_numbers[i] >= ODIN_ANDROID_API_LEVEL) { - if (closest_number_idx < 0) { - closest_number_idx = i; - } else if (dir_numbers[i] < dir_numbers[closest_number_idx]) { - closest_number_idx = i; - } - } - } - - if (closest_number_idx < 0) { - gb_printf_err("Unable to find any Android SDK/API Level in %.*s meeting the minimum API level of %d\n", LIT(android_sdk_build_tools), ODIN_ANDROID_API_LEVEL); - return 1; - } - - String api_number = possible_valid_dirs[closest_number_idx].name; - - android_sdk_build_tools = concatenate_strings(temporary_allocator(), android_sdk_build_tools, api_number); - String android_sdk_platforms = concatenate_strings(temporary_allocator(), - build_context.ODIN_ANDROID_SDK, - make_string_c(gb_bprintf("platforms/android-%d/", dir_numbers[closest_number_idx])) - ); - - - - android_sdk_build_tools = normalize_path(temporary_allocator(), android_sdk_build_tools, NIX_SEPARATOR_STRING); - android_sdk_platforms = normalize_path(temporary_allocator(), android_sdk_platforms, NIX_SEPARATOR_STRING); - - gbString cmd = gb_string_make(heap_allocator(), ""); - defer (gb_string_free(cmd)); - - TIME_SECTION("Android aapt"); - - String output_filename = str_lit("test"); - - String output_apk = path_remove_extension(output_filename); - - cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); - cmd = gb_string_appendc(cmd, "aapt"); - cmd = gb_string_appendc(cmd, " package -f"); - cmd = gb_string_append_fmt(cmd, " -M \"%.*s\"", LIT(build_context.android_manifest)); - cmd = gb_string_append_fmt(cmd, " -I \"%.*sandroid.jar\"", LIT(android_sdk_platforms)); - cmd = gb_string_append_fmt(cmd, " -F \"%.*s.apk-build\"", LIT(output_apk)); - - result = system_exec_command_line_app("android-aapt", cmd); - if (result) { - return result; - } - - TIME_SECTION("Android jarsigner"); - gb_string_clear(cmd); - - cmd = gb_string_append_length(cmd, build_context.ODIN_ANDROID_JAR_SIGNER.text, build_context.ODIN_ANDROID_JAR_SIGNER.len); - cmd = gb_string_append_fmt(cmd, " -storepass android -keystore \"%.*s\" \"%.*s.apk-build\" \"%.*s\"", - LIT(build_context.android_keystore), - LIT(output_apk), - LIT(build_context.android_keystore_alias) - ); - result = system_exec_command_line_app("android-jarsigner", cmd); - if (result) { - return result; - } - - TIME_SECTION("Android zipalign"); - gb_string_clear(cmd); - - cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); - cmd = gb_string_appendc(cmd, "zipalign"); - cmd = gb_string_appendc(cmd, " -f 4"); - cmd = gb_string_append_fmt(cmd, " \"%.*s.apk-build\" \"%.*s.apk\"", LIT(output_apk), LIT(output_apk)); - - - result = system_exec_command_line_app("android-zipalign", cmd); - if (result) { - return result; - } - - return 0; -} diff --git a/src/package_command.cpp b/src/package_command.cpp new file mode 100644 index 000000000..b5466118f --- /dev/null +++ b/src/package_command.cpp @@ -0,0 +1,169 @@ +i32 package_android(String init_directory); + +i32 package(String init_directory) { + switch (build_context.command_kind) { + case Command_package_android: + return package_android(init_directory); + } + gb_printf_err("Unknown odin package \n"); + return 1; +} + + +i32 package_android(String init_directory) { + i32 result = 0; + + init_android_values(/*with_sdk*/true); + + int const ODIN_ANDROID_API_LEVEL = build_context.ODIN_ANDROID_API_LEVEL; + + String android_sdk_build_tools = concatenate3_strings(temporary_allocator(), + build_context.ODIN_ANDROID_SDK, str_lit("build-tools"), NIX_SEPARATOR_STRING); + + Array list = {}; + ReadDirectoryError rd_err = read_directory(android_sdk_build_tools, &list); + defer (array_free(&list)); + + switch (rd_err) { + case ReadDirectory_InvalidPath: + gb_printf_err("Invalid path: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_NotExists: + gb_printf_err("Path does not exist: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_Permission: + gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_NotDir: + gb_printf_err("Expected a directory for a package, got a file: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_Empty: + gb_printf_err("Empty directory: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_Unknown: + gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(android_sdk_build_tools)); + return 1; + } + + auto possible_valid_dirs = array_make(heap_allocator(), 0, list.count); + defer (array_free(&possible_valid_dirs)); + + + for (FileInfo fi : list) if (fi.is_dir) { + bool all_numbers = true; + for (isize i = 0; i < fi.name.len; i++) { + u8 c = fi.name[i]; + if ('0' <= c && c <= '9') { + // true + } else if (i == 0) { + all_numbers = false; + } else if (c == '.') { + break; + } else { + all_numbers = false; + } + } + + if (all_numbers) { + array_add(&possible_valid_dirs, fi); + } + } + + if (possible_valid_dirs.count == 0) { + gb_printf_err("Unable to find any Android SDK/API Level in %.*s\n", LIT(android_sdk_build_tools)); + return 1; + } + + int *dir_numbers = gb_alloc_array(temporary_allocator(), int, possible_valid_dirs.count); + + char buf[1024] = {}; + for_array(i, possible_valid_dirs) { + FileInfo fi = possible_valid_dirs[i]; + isize n = gb_min(gb_size_of(buf)-1, fi.name.len); + memcpy(buf, fi.name.text, n); + buf[n] = 0; + + dir_numbers[i] = atoi(buf); + } + + isize closest_number_idx = -1; + for (isize i = 0; i < possible_valid_dirs.count; i++) { + if (dir_numbers[i] >= ODIN_ANDROID_API_LEVEL) { + if (closest_number_idx < 0) { + closest_number_idx = i; + } else if (dir_numbers[i] < dir_numbers[closest_number_idx]) { + closest_number_idx = i; + } + } + } + + if (closest_number_idx < 0) { + gb_printf_err("Unable to find any Android SDK/API Level in %.*s meeting the minimum API level of %d\n", LIT(android_sdk_build_tools), ODIN_ANDROID_API_LEVEL); + return 1; + } + + String api_number = possible_valid_dirs[closest_number_idx].name; + + android_sdk_build_tools = concatenate_strings(temporary_allocator(), android_sdk_build_tools, api_number); + String android_sdk_platforms = concatenate_strings(temporary_allocator(), + build_context.ODIN_ANDROID_SDK, + make_string_c(gb_bprintf("platforms/android-%d/", dir_numbers[closest_number_idx])) + ); + + android_sdk_build_tools = normalize_path(temporary_allocator(), android_sdk_build_tools, NIX_SEPARATOR_STRING); + android_sdk_platforms = normalize_path(temporary_allocator(), android_sdk_platforms, NIX_SEPARATOR_STRING); + + gbString cmd = gb_string_make(heap_allocator(), ""); + defer (gb_string_free(cmd)); + + String output_filename = str_lit("test"); + String output_apk = path_remove_extension(output_filename); + + TIME_SECTION("Android aapt"); + { + cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); + cmd = gb_string_appendc(cmd, "aapt"); + cmd = gb_string_appendc(cmd, " package -f"); + cmd = gb_string_append_fmt(cmd, " -M \"%.*s\"", LIT(build_context.android_manifest)); + cmd = gb_string_append_fmt(cmd, " -I \"%.*sandroid.jar\"", LIT(android_sdk_platforms)); + cmd = gb_string_append_fmt(cmd, " -F \"%.*s.apk-build\"", LIT(output_apk)); + + result = system_exec_command_line_app("android-aapt", cmd); + if (result) { + return result; + } + } + + TIME_SECTION("Android jarsigner"); + { + gb_string_clear(cmd); + + cmd = gb_string_append_length(cmd, build_context.ODIN_ANDROID_JAR_SIGNER.text, build_context.ODIN_ANDROID_JAR_SIGNER.len); + cmd = gb_string_append_fmt(cmd, " -storepass android -keystore \"%.*s\" \"%.*s.apk-build\" \"%.*s\"", + LIT(build_context.android_keystore), + LIT(output_apk), + LIT(build_context.android_keystore_alias) + ); + result = system_exec_command_line_app("android-jarsigner", cmd); + if (result) { + return result; + } + } + + TIME_SECTION("Android zipalign"); + { + gb_string_clear(cmd); + + cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); + cmd = gb_string_appendc(cmd, "zipalign"); + cmd = gb_string_appendc(cmd, " -f 4"); + cmd = gb_string_append_fmt(cmd, " \"%.*s.apk-build\" \"%.*s.apk\"", LIT(output_apk), LIT(output_apk)); + + result = system_exec_command_line_app("android-zipalign", cmd); + if (result) { + return result; + } + } + + return 0; +} -- cgit v1.2.3 From e29b5ae8edbd89b50e4c06fcf6a7a6719c89c1d7 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 27 Mar 2025 09:27:54 +0000 Subject: Use `u64` for the command kind just in case --- src/build_settings.cpp | 2 +- src/main.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index bdad1d633..100a01da9 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -206,7 +206,7 @@ enum BuildModeKind { BuildMode_COUNT, }; -enum CommandKind : u32 { +enum CommandKind : u64 { Command_run = 1<<0, Command_build = 1<<1, Command_check = 1<<2, diff --git a/src/main.cpp b/src/main.cpp index 54018b945..48bdb13fb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -431,12 +431,12 @@ struct BuildFlag { BuildFlagKind kind; String name; BuildFlagParamKind param_kind; - u32 command_support; + u64 command_support; bool allow_multiple; }; -gb_internal void add_flag(Array *build_flags, BuildFlagKind kind, String name, BuildFlagParamKind param_kind, u32 command_support, bool allow_multiple=false) { +gb_internal void add_flag(Array *build_flags, BuildFlagKind kind, String name, BuildFlagParamKind param_kind, u64 command_support, bool allow_multiple=false) { BuildFlag flag = {kind, name, param_kind, command_support, allow_multiple}; array_add(build_flags, flag); } @@ -1676,8 +1676,8 @@ gb_internal bool parse_build_flags(Array args) { gb_printf_err("'%.*s' is supported with the following commands:\n", LIT(name)); gb_printf_err("\t"); i32 count = 0; - for (u32 i = 0; i < 32; i++) { - if (found_bf.command_support & (1< 0) { gb_printf_err(", "); } -- cgit v1.2.3 From 0e6cc6ec4ba1c5cee8815303cd5b98e14a30ee29 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 27 Mar 2025 10:31:59 +0000 Subject: Use working directory for `aapt` commands --- src/build_settings.cpp | 4 --- src/package_command.cpp | 46 ++++++++++++++++++++++++++---- src/path.cpp | 76 +++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 104 insertions(+), 22 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 100a01da9..1d20ed82b 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1585,10 +1585,6 @@ gb_internal void init_android_values(bool with_sdk) { gb_printf_err("Error: -android-keystore_alias: has not been set\n"); gb_exit(1); } - if (bc->android_manifest.len == 0) { - gb_printf_err("Error: -android-manifest: has not been set\n"); - gb_exit(1); - } } } diff --git a/src/package_command.cpp b/src/package_command.cpp index de2fd9d3e..43db46521 100644 --- a/src/package_command.cpp +++ b/src/package_command.cpp @@ -10,11 +10,20 @@ i32 package(String init_directory) { } -i32 package_android(String init_directory) { - i32 result = 0; +i32 package_android(String original_init_directory) { + TEMPORARY_ALLOCATOR_GUARD(); + i32 result = 0; init_android_values(/*with_sdk*/true); + bool init_directory_ok = false; + String init_directory = path_to_fullpath(temporary_allocator(), original_init_directory, &init_directory_ok); + if (!init_directory_ok) { + gb_printf_err("Error: '%.*s' is not a valid directory", LIT(original_init_directory)); + return 1; + } + init_directory = normalize_path(temporary_allocator(), init_directory, NIX_SEPARATOR_STRING); + int const ODIN_ANDROID_API_LEVEL = build_context.ODIN_ANDROID_API_LEVEL; String android_sdk_build_tools = concatenate3_strings(temporary_allocator(), @@ -116,16 +125,37 @@ i32 package_android(String init_directory) { gbString cmd = gb_string_make(heap_allocator(), ""); defer (gb_string_free(cmd)); + + String current_directory = normalize_path(temporary_allocator(), get_working_directory(temporary_allocator()), NIX_SEPARATOR_STRING); + defer (set_working_directory(current_directory)); + + if (current_directory.len != 0) { + bool ok = set_working_directory(init_directory); + if (!ok) { + gb_printf_err("Error: Unable to currectly set the current working directory to '%.*s'\n", LIT(init_directory)); + } + } + String output_filename = str_lit("test"); String output_apk = path_remove_extension(output_filename); TIME_SECTION("Android aapt"); { + TEMPORARY_ALLOCATOR_GUARD(); + gb_string_clear(cmd); + + String manifest = {}; + if (build_context.android_manifest.len != 0) { + manifest = concatenate_strings(temporary_allocator(), current_directory, build_context.android_manifest); + } else { + manifest = concatenate_strings(temporary_allocator(), init_directory, str_lit("AndroidManifest.xml")); + } + cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); cmd = gb_string_appendc(cmd, "aapt"); cmd = gb_string_appendc(cmd, " package -f"); - if (build_context.android_manifest.len != 0) { - cmd = gb_string_append_fmt(cmd, " -M \"%.*s\"", LIT(build_context.android_manifest)); + if (manifest.len != 0) { + cmd = gb_string_append_fmt(cmd, " -M \"%.*s\"", LIT(manifest)); } cmd = gb_string_append_fmt(cmd, " -I \"%.*sandroid.jar\"", LIT(android_sdk_platforms)); cmd = gb_string_append_fmt(cmd, " -F \"%.*s.apk-build\"", LIT(output_apk)); @@ -138,16 +168,19 @@ i32 package_android(String init_directory) { TIME_SECTION("Android jarsigner"); { + TEMPORARY_ALLOCATOR_GUARD(); gb_string_clear(cmd); cmd = gb_string_append_length(cmd, build_context.ODIN_ANDROID_JAR_SIGNER.text, build_context.ODIN_ANDROID_JAR_SIGNER.len); cmd = gb_string_append_fmt(cmd, " -storepass android"); if (build_context.android_keystore.len != 0) { - cmd = gb_string_append_fmt(cmd, " -keystore \"%.*s\"", LIT(build_context.android_keystore)); + String keystore = concatenate_strings(temporary_allocator(), current_directory, build_context.android_keystore); + cmd = gb_string_append_fmt(cmd, " -keystore \"%.*s\"", LIT(keystore)); } cmd = gb_string_append_fmt(cmd, " \"%.*s.apk-build\"", LIT(output_apk)); if (build_context.android_keystore_alias.len != 0) { - cmd = gb_string_append_fmt(cmd, " \"%.*s\"", LIT(build_context.android_keystore_alias)); + String keystore_alias = build_context.android_keystore_alias; + cmd = gb_string_append_fmt(cmd, " \"%.*s\"", LIT(keystore_alias)); } result = system_exec_command_line_app("android-jarsigner", cmd); @@ -158,6 +191,7 @@ i32 package_android(String init_directory) { TIME_SECTION("Android zipalign"); { + TEMPORARY_ALLOCATOR_GUARD(); gb_string_clear(cmd); cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); diff --git a/src/path.cpp b/src/path.cpp index 2c08ddd98..2217622c6 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -30,28 +30,80 @@ gb_internal String remove_directory_from_path(String const &s) { } -// NOTE(Mark Naughton): getcwd as String -#if !defined(GB_SYSTEM_WINDOWS) -gb_internal String get_current_directory(void) { - char cwd[256]; - getcwd(cwd, 256); +#if defined(GB_SYSTEM_WINDOWS) +gb_global SRWLOCK cwd_lock; + +String get_working_directory(gbAllocator allocator) { + AcquireSRWLockExclusive(&cwd_lock); + + TEMPORARY_ALLOCATOR_GUARD(); + + DWORD sz_utf16 = GetCurrentDirectoryW(0, nullptr); + wchar_t *dir_buf_wstr = gb_alloc_array(temporary_allocator(), wchar_t, sz_utf16); + if (dir_buf_wstr == nullptr) { + ReleaseSRWLockExclusive(&cwd_lock); + return {}; + } + + DWORD n = GetCurrentDirectoryW(sz_utf16, dir_buf_wstr); + GB_ASSERT(n+1 == sz_utf16); + ReleaseSRWLockExclusive(&cwd_lock); + + + isize buf_len = sz_utf16*4; + u8 *buf = gb_alloc_array(allocator, u8, buf_len); + gb_ucs2_to_utf8(buf, buf_len, cast(u16 *)dir_buf_wstr); + + return make_string_c(cast(char const *)buf); +} + +bool set_working_directory(String dir) { + bool ok = false; + TEMPORARY_ALLOCATOR_GUARD(); + + char const *cdir = alloc_cstring(temporary_allocator(), dir); + wchar_t *wstr = gb__alloc_utf8_to_ucs2(temporary_allocator(), cdir, nullptr); - return make_string_c(cwd); + AcquireSRWLockExclusive(&cwd_lock); + + ok = SetCurrentDirectoryW(wstr); + + ReleaseSRWLockExclusive(&cwd_lock); + + return ok; } #else -gb_internal String get_current_directory(void) { - gbAllocator a = heap_allocator(); - wchar_t cwd[256]; - GetCurrentDirectoryW(256, cwd); +String get_working_directory(gbAllocator allocator) { + TEMPORARY_ALLOCATOR_GUARD(); - String16 wstr = make_string16_c(cwd); + auto buf = array_make(temporary_allocator()); + size_t size = PATH_MAX: - return string16_to_string(a, wstr); + char const *cwd; + for (; cwd == nullptr; size *= 2) { + array_resize(&buf, size); + + cwd = getcwd(buf.data, buf.count); + if cwd == nullptr && errno() != ERANGE { + return {}; + } + } + + return copy_string(allocator, make_string_c(cwd)); +} + +bool set_working_directory(String dir) { + TEMPORARY_ALLOCATOR_GUARD(); + char const *cdir = alloc_cstring(temporary_allocator(), dir); + return !chdir(cdir); } + #endif + + gb_internal bool path_is_directory(String path); gb_internal String directory_from_path(String const &s) { -- cgit v1.2.3 From e7ae7b8fd452dd7a31532695c1b850842049bc52 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 28 Mar 2025 09:27:04 +0000 Subject: Command `package` -> `bundle` --- src/build_settings.cpp | 10 ++- src/bundle_command.cpp | 209 ++++++++++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 28 +++---- src/package_command.cpp | 209 ------------------------------------------------ 4 files changed, 231 insertions(+), 225 deletions(-) create mode 100644 src/bundle_command.cpp delete mode 100644 src/package_command.cpp (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 1d20ed82b..1f5aba254 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -217,7 +217,10 @@ enum CommandKind : u64 { Command_strip_semicolon = 1<<6, Command_bug_report = 1<<7, - Command_package_android = 1<<8, + 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, @@ -233,7 +236,10 @@ gb_global char const *odin_command_strings[32] = { "test", "strip-semicolon", "", - "package-android", + "bundle android", + "bundle macos", + "bundle ios", + "bundle orca", }; diff --git a/src/bundle_command.cpp b/src/bundle_command.cpp new file mode 100644 index 000000000..b3bca2b51 --- /dev/null +++ b/src/bundle_command.cpp @@ -0,0 +1,209 @@ +i32 bundle_android(String init_directory); + +i32 bundle(String init_directory) { + switch (build_context.command_kind) { + case Command_bundle_android: + return bundle_android(init_directory); + } + gb_printf_err("Unknown odin package \n"); + return 1; +} + + +i32 bundle_android(String original_init_directory) { + TEMPORARY_ALLOCATOR_GUARD(); + + i32 result = 0; + init_android_values(/*with_sdk*/true); + + bool init_directory_ok = false; + String init_directory = path_to_fullpath(temporary_allocator(), original_init_directory, &init_directory_ok); + if (!init_directory_ok) { + gb_printf_err("Error: '%.*s' is not a valid directory", LIT(original_init_directory)); + return 1; + } + init_directory = normalize_path(temporary_allocator(), init_directory, NIX_SEPARATOR_STRING); + + int const ODIN_ANDROID_API_LEVEL = build_context.ODIN_ANDROID_API_LEVEL; + + String android_sdk_build_tools = concatenate3_strings(temporary_allocator(), + build_context.ODIN_ANDROID_SDK, str_lit("build-tools"), NIX_SEPARATOR_STRING); + + Array list = {}; + ReadDirectoryError rd_err = read_directory(android_sdk_build_tools, &list); + defer (array_free(&list)); + + switch (rd_err) { + case ReadDirectory_InvalidPath: + gb_printf_err("Invalid path: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_NotExists: + gb_printf_err("Path does not exist: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_Permission: + gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_NotDir: + gb_printf_err("Expected a directory for a package, got a file: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_Empty: + gb_printf_err("Empty directory: %.*s\n", LIT(android_sdk_build_tools)); + return 1; + case ReadDirectory_Unknown: + gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(android_sdk_build_tools)); + return 1; + } + + auto possible_valid_dirs = array_make(heap_allocator(), 0, list.count); + defer (array_free(&possible_valid_dirs)); + + + for (FileInfo fi : list) if (fi.is_dir) { + bool all_numbers = true; + for (isize i = 0; i < fi.name.len; i++) { + u8 c = fi.name[i]; + if ('0' <= c && c <= '9') { + // true + } else if (i == 0) { + all_numbers = false; + } else if (c == '.') { + break; + } else { + all_numbers = false; + } + } + + if (all_numbers) { + array_add(&possible_valid_dirs, fi); + } + } + + if (possible_valid_dirs.count == 0) { + gb_printf_err("Unable to find any Android SDK/API Level in %.*s\n", LIT(android_sdk_build_tools)); + return 1; + } + + int *dir_numbers = gb_alloc_array(temporary_allocator(), int, possible_valid_dirs.count); + + char buf[1024] = {}; + for_array(i, possible_valid_dirs) { + FileInfo fi = possible_valid_dirs[i]; + isize n = gb_min(gb_size_of(buf)-1, fi.name.len); + memcpy(buf, fi.name.text, n); + buf[n] = 0; + + dir_numbers[i] = atoi(buf); + } + + isize closest_number_idx = -1; + for (isize i = 0; i < possible_valid_dirs.count; i++) { + if (dir_numbers[i] >= ODIN_ANDROID_API_LEVEL) { + if (closest_number_idx < 0) { + closest_number_idx = i; + } else if (dir_numbers[i] < dir_numbers[closest_number_idx]) { + closest_number_idx = i; + } + } + } + + if (closest_number_idx < 0) { + gb_printf_err("Unable to find any Android SDK/API Level in %.*s meeting the minimum API level of %d\n", LIT(android_sdk_build_tools), ODIN_ANDROID_API_LEVEL); + return 1; + } + + String api_number = possible_valid_dirs[closest_number_idx].name; + + android_sdk_build_tools = concatenate_strings(temporary_allocator(), android_sdk_build_tools, api_number); + String android_sdk_platforms = concatenate_strings(temporary_allocator(), + build_context.ODIN_ANDROID_SDK, + make_string_c(gb_bprintf("platforms/android-%d/", dir_numbers[closest_number_idx])) + ); + + android_sdk_build_tools = normalize_path(temporary_allocator(), android_sdk_build_tools, NIX_SEPARATOR_STRING); + android_sdk_platforms = normalize_path(temporary_allocator(), android_sdk_platforms, NIX_SEPARATOR_STRING); + + gbString cmd = gb_string_make(heap_allocator(), ""); + defer (gb_string_free(cmd)); + + + String current_directory = normalize_path(temporary_allocator(), get_working_directory(temporary_allocator()), NIX_SEPARATOR_STRING); + defer (set_working_directory(current_directory)); + + if (current_directory.len != 0) { + bool ok = set_working_directory(init_directory); + if (!ok) { + gb_printf_err("Error: Unable to currectly set the current working directory to '%.*s'\n", LIT(init_directory)); + } + } + + String output_filename = str_lit("test"); + String output_apk = path_remove_extension(output_filename); + + TIME_SECTION("Android aapt"); + { + TEMPORARY_ALLOCATOR_GUARD(); + gb_string_clear(cmd); + + String manifest = {}; + if (build_context.android_manifest.len != 0) { + manifest = concatenate_strings(temporary_allocator(), current_directory, build_context.android_manifest); + } else { + manifest = concatenate_strings(temporary_allocator(), init_directory, str_lit("AndroidManifest.xml")); + } + + cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); + cmd = gb_string_appendc(cmd, "aapt"); + cmd = gb_string_appendc(cmd, " package -f"); + if (manifest.len != 0) { + cmd = gb_string_append_fmt(cmd, " -M \"%.*s\"", LIT(manifest)); + } + cmd = gb_string_append_fmt(cmd, " -I \"%.*sandroid.jar\"", LIT(android_sdk_platforms)); + cmd = gb_string_append_fmt(cmd, " -F \"%.*s.apk-build\"", LIT(output_apk)); + + result = system_exec_command_line_app("android-aapt", cmd); + if (result) { + return result; + } + } + + TIME_SECTION("Android jarsigner"); + { + TEMPORARY_ALLOCATOR_GUARD(); + gb_string_clear(cmd); + + cmd = gb_string_append_length(cmd, build_context.ODIN_ANDROID_JAR_SIGNER.text, build_context.ODIN_ANDROID_JAR_SIGNER.len); + cmd = gb_string_append_fmt(cmd, " -storepass android"); + if (build_context.android_keystore.len != 0) { + String keystore = concatenate_strings(temporary_allocator(), current_directory, build_context.android_keystore); + cmd = gb_string_append_fmt(cmd, " -keystore \"%.*s\"", LIT(keystore)); + } + cmd = gb_string_append_fmt(cmd, " \"%.*s.apk-build\"", LIT(output_apk)); + if (build_context.android_keystore_alias.len != 0) { + String keystore_alias = build_context.android_keystore_alias; + cmd = gb_string_append_fmt(cmd, " \"%.*s\"", LIT(keystore_alias)); + } + + result = system_exec_command_line_app("android-jarsigner", cmd); + if (result) { + return result; + } + } + + TIME_SECTION("Android zipalign"); + { + TEMPORARY_ALLOCATOR_GUARD(); + gb_string_clear(cmd); + + cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); + cmd = gb_string_appendc(cmd, "zipalign"); + cmd = gb_string_appendc(cmd, " -f 4"); + cmd = gb_string_append_fmt(cmd, " \"%.*s.apk-build\" \"%.*s.apk\"", LIT(output_apk), LIT(output_apk)); + + result = system_exec_command_line_app("android-zipalign", cmd); + if (result) { + return result; + } + } + + return 0; +} diff --git a/src/main.cpp b/src/main.cpp index fa06a84af..c19bbde22 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -74,7 +74,7 @@ gb_global Timings global_timings = {0}; #include "cached.cpp" #include "linker.cpp" -#include "package_command.cpp" +#include "bundle_command.cpp" #if defined(GB_SYSTEM_WINDOWS) && defined(ODIN_TILDE_BACKEND) #define ALLOW_TILDE 1 @@ -572,7 +572,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Microarch, str_lit("microarch"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_TargetFeatures, str_lit("target-features"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_StrictTargetFeatures, str_lit("strict-target-features"), BuildFlagParam_None, Command__does_build); - add_flag(&build_flags, BuildFlag_MinimumOSVersion, str_lit("minimum-os-version"), BuildFlagParam_String, Command__does_build | Command_package_android); + add_flag(&build_flags, BuildFlag_MinimumOSVersion, str_lit("minimum-os-version"), BuildFlagParam_String, Command__does_build | Command_bundle_android); add_flag(&build_flags, BuildFlag_RelocMode, str_lit("reloc-mode"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_DisableRedZone, str_lit("disable-red-zone"), BuildFlagParam_None, Command__does_build); @@ -629,14 +629,14 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Subsystem, str_lit("subsystem"), BuildFlagParam_String, Command__does_build); #endif - add_flag(&build_flags, BuildFlag_AndroidKeystore, str_lit("android-keystore"), BuildFlagParam_String, Command_package_android); - add_flag(&build_flags, BuildFlag_AndroidKeystoreAlias, str_lit("android-keystore-alias"), BuildFlagParam_String, Command_package_android); - add_flag(&build_flags, BuildFlag_AndroidManifest, str_lit("android-manifest"), BuildFlagParam_String, Command_package_android); + add_flag(&build_flags, BuildFlag_AndroidKeystore, str_lit("android-keystore"), BuildFlagParam_String, Command_bundle_android); + add_flag(&build_flags, BuildFlag_AndroidKeystoreAlias, str_lit("android-keystore-alias"), BuildFlagParam_String, Command_bundle_android); + add_flag(&build_flags, BuildFlag_AndroidManifest, str_lit("android-manifest"), BuildFlagParam_String, Command_bundle_android); Array flag_args = {}; - if (build_context.command_kind == Command_package_android) { + if (build_context.command_kind == Command_bundle_android) { GB_ASSERT(args.count >= 4); flag_args = array_slice(args, 4, args.count); } else { @@ -2267,8 +2267,8 @@ gb_internal void print_show_help(String const arg0, String command, String optio } else if (command == "strip-semicolon") { print_usage_line(1, "strip-semicolon"); print_usage_line(2, "Parses and type checks .odin file(s) and then removes unneeded semicolons from the entire project."); - } else if (command == "package") { - print_usage_line(1, "package Packages directory in a specific layout for that platform"); + } else if (command == "bundle") { + print_usage_line(1, "bundle Bundles a directory in a specific layout for that platform"); print_usage_line(2, "Supported platforms:"); print_usage_line(3, "android"); } @@ -2280,7 +2280,7 @@ gb_internal void print_show_help(String const arg0, String command, String optio bool strip_semicolon = command == "strip-semicolon"; bool check_only = command == "check" || strip_semicolon; bool check = run_or_build || check_only; - bool is_package = command == "package"; + bool bundle = command == "bundle"; if (command == "help") { doc = true; @@ -2548,7 +2548,7 @@ gb_internal void print_show_help(String const arg0, String command, String optio } } - if (run_or_build || is_package) { + if (run_or_build || bundle) { if (print_flag("-minimum-os-version:")) { print_usage_line(2, "Sets the minimum OS version targeted by the application."); print_usage_line(2, "Default: -minimum-os-version:11.0.0"); @@ -3337,13 +3337,13 @@ int main(int arg_count, char const **arg_ptr) { print_show_help(args[0], args[1], args[2]); return 0; } - } else if (command == "package") { + } else if (command == "bundle") { if (args.count < 4) { usage(args[0]); return 1; } if (args[2] == "android") { - build_context.command_kind = Command_package_android; + build_context.command_kind = Command_bundle_android; } else { gb_printf_err("Unknown package command: '%.*s'\n", LIT(args[2])); usage(args[0]); @@ -3425,8 +3425,8 @@ int main(int arg_count, char const **arg_ptr) { return 0; } - if (command == "package") { - return package(init_filename); + if (command == "bundle") { + return bundle(init_filename); } // NOTE(bill): add 'shared' directory if it is not already set diff --git a/src/package_command.cpp b/src/package_command.cpp deleted file mode 100644 index 43db46521..000000000 --- a/src/package_command.cpp +++ /dev/null @@ -1,209 +0,0 @@ -i32 package_android(String init_directory); - -i32 package(String init_directory) { - switch (build_context.command_kind) { - case Command_package_android: - return package_android(init_directory); - } - gb_printf_err("Unknown odin package \n"); - return 1; -} - - -i32 package_android(String original_init_directory) { - TEMPORARY_ALLOCATOR_GUARD(); - - i32 result = 0; - init_android_values(/*with_sdk*/true); - - bool init_directory_ok = false; - String init_directory = path_to_fullpath(temporary_allocator(), original_init_directory, &init_directory_ok); - if (!init_directory_ok) { - gb_printf_err("Error: '%.*s' is not a valid directory", LIT(original_init_directory)); - return 1; - } - init_directory = normalize_path(temporary_allocator(), init_directory, NIX_SEPARATOR_STRING); - - int const ODIN_ANDROID_API_LEVEL = build_context.ODIN_ANDROID_API_LEVEL; - - String android_sdk_build_tools = concatenate3_strings(temporary_allocator(), - build_context.ODIN_ANDROID_SDK, str_lit("build-tools"), NIX_SEPARATOR_STRING); - - Array list = {}; - ReadDirectoryError rd_err = read_directory(android_sdk_build_tools, &list); - defer (array_free(&list)); - - switch (rd_err) { - case ReadDirectory_InvalidPath: - gb_printf_err("Invalid path: %.*s\n", LIT(android_sdk_build_tools)); - return 1; - case ReadDirectory_NotExists: - gb_printf_err("Path does not exist: %.*s\n", LIT(android_sdk_build_tools)); - return 1; - case ReadDirectory_Permission: - gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(android_sdk_build_tools)); - return 1; - case ReadDirectory_NotDir: - gb_printf_err("Expected a directory for a package, got a file: %.*s\n", LIT(android_sdk_build_tools)); - return 1; - case ReadDirectory_Empty: - gb_printf_err("Empty directory: %.*s\n", LIT(android_sdk_build_tools)); - return 1; - case ReadDirectory_Unknown: - gb_printf_err("Unknown error whilst reading path %.*s\n", LIT(android_sdk_build_tools)); - return 1; - } - - auto possible_valid_dirs = array_make(heap_allocator(), 0, list.count); - defer (array_free(&possible_valid_dirs)); - - - for (FileInfo fi : list) if (fi.is_dir) { - bool all_numbers = true; - for (isize i = 0; i < fi.name.len; i++) { - u8 c = fi.name[i]; - if ('0' <= c && c <= '9') { - // true - } else if (i == 0) { - all_numbers = false; - } else if (c == '.') { - break; - } else { - all_numbers = false; - } - } - - if (all_numbers) { - array_add(&possible_valid_dirs, fi); - } - } - - if (possible_valid_dirs.count == 0) { - gb_printf_err("Unable to find any Android SDK/API Level in %.*s\n", LIT(android_sdk_build_tools)); - return 1; - } - - int *dir_numbers = gb_alloc_array(temporary_allocator(), int, possible_valid_dirs.count); - - char buf[1024] = {}; - for_array(i, possible_valid_dirs) { - FileInfo fi = possible_valid_dirs[i]; - isize n = gb_min(gb_size_of(buf)-1, fi.name.len); - memcpy(buf, fi.name.text, n); - buf[n] = 0; - - dir_numbers[i] = atoi(buf); - } - - isize closest_number_idx = -1; - for (isize i = 0; i < possible_valid_dirs.count; i++) { - if (dir_numbers[i] >= ODIN_ANDROID_API_LEVEL) { - if (closest_number_idx < 0) { - closest_number_idx = i; - } else if (dir_numbers[i] < dir_numbers[closest_number_idx]) { - closest_number_idx = i; - } - } - } - - if (closest_number_idx < 0) { - gb_printf_err("Unable to find any Android SDK/API Level in %.*s meeting the minimum API level of %d\n", LIT(android_sdk_build_tools), ODIN_ANDROID_API_LEVEL); - return 1; - } - - String api_number = possible_valid_dirs[closest_number_idx].name; - - android_sdk_build_tools = concatenate_strings(temporary_allocator(), android_sdk_build_tools, api_number); - String android_sdk_platforms = concatenate_strings(temporary_allocator(), - build_context.ODIN_ANDROID_SDK, - make_string_c(gb_bprintf("platforms/android-%d/", dir_numbers[closest_number_idx])) - ); - - android_sdk_build_tools = normalize_path(temporary_allocator(), android_sdk_build_tools, NIX_SEPARATOR_STRING); - android_sdk_platforms = normalize_path(temporary_allocator(), android_sdk_platforms, NIX_SEPARATOR_STRING); - - gbString cmd = gb_string_make(heap_allocator(), ""); - defer (gb_string_free(cmd)); - - - String current_directory = normalize_path(temporary_allocator(), get_working_directory(temporary_allocator()), NIX_SEPARATOR_STRING); - defer (set_working_directory(current_directory)); - - if (current_directory.len != 0) { - bool ok = set_working_directory(init_directory); - if (!ok) { - gb_printf_err("Error: Unable to currectly set the current working directory to '%.*s'\n", LIT(init_directory)); - } - } - - String output_filename = str_lit("test"); - String output_apk = path_remove_extension(output_filename); - - TIME_SECTION("Android aapt"); - { - TEMPORARY_ALLOCATOR_GUARD(); - gb_string_clear(cmd); - - String manifest = {}; - if (build_context.android_manifest.len != 0) { - manifest = concatenate_strings(temporary_allocator(), current_directory, build_context.android_manifest); - } else { - manifest = concatenate_strings(temporary_allocator(), init_directory, str_lit("AndroidManifest.xml")); - } - - cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); - cmd = gb_string_appendc(cmd, "aapt"); - cmd = gb_string_appendc(cmd, " package -f"); - if (manifest.len != 0) { - cmd = gb_string_append_fmt(cmd, " -M \"%.*s\"", LIT(manifest)); - } - cmd = gb_string_append_fmt(cmd, " -I \"%.*sandroid.jar\"", LIT(android_sdk_platforms)); - cmd = gb_string_append_fmt(cmd, " -F \"%.*s.apk-build\"", LIT(output_apk)); - - result = system_exec_command_line_app("android-aapt", cmd); - if (result) { - return result; - } - } - - TIME_SECTION("Android jarsigner"); - { - TEMPORARY_ALLOCATOR_GUARD(); - gb_string_clear(cmd); - - cmd = gb_string_append_length(cmd, build_context.ODIN_ANDROID_JAR_SIGNER.text, build_context.ODIN_ANDROID_JAR_SIGNER.len); - cmd = gb_string_append_fmt(cmd, " -storepass android"); - if (build_context.android_keystore.len != 0) { - String keystore = concatenate_strings(temporary_allocator(), current_directory, build_context.android_keystore); - cmd = gb_string_append_fmt(cmd, " -keystore \"%.*s\"", LIT(keystore)); - } - cmd = gb_string_append_fmt(cmd, " \"%.*s.apk-build\"", LIT(output_apk)); - if (build_context.android_keystore_alias.len != 0) { - String keystore_alias = build_context.android_keystore_alias; - cmd = gb_string_append_fmt(cmd, " \"%.*s\"", LIT(keystore_alias)); - } - - result = system_exec_command_line_app("android-jarsigner", cmd); - if (result) { - return result; - } - } - - TIME_SECTION("Android zipalign"); - { - TEMPORARY_ALLOCATOR_GUARD(); - gb_string_clear(cmd); - - cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); - cmd = gb_string_appendc(cmd, "zipalign"); - cmd = gb_string_appendc(cmd, " -f 4"); - cmd = gb_string_append_fmt(cmd, " \"%.*s.apk-build\" \"%.*s.apk\"", LIT(output_apk), LIT(output_apk)); - - result = system_exec_command_line_app("android-zipalign", cmd); - if (result) { - return result; - } - } - - return 0; -} -- cgit v1.2.3 From 7c26024920d3fe684edc66016f71db28e1f7542b Mon Sep 17 00:00:00 2001 From: IllusionMan1212 Date: Fri, 4 Apr 2025 05:22:04 +0200 Subject: fix: strip trailing slashes for android keystore and jarsigner paths The `system()` call on linux was failing to execute the `jarsigner` command because its path had a trailing slash --- src/build_settings.cpp | 2 ++ src/bundle_command.cpp | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 1f5aba254..8339b111a 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1574,6 +1574,8 @@ gb_internal void init_android_values(bool with_sdk) { bc->ODIN_ANDROID_JAR_SIGNER = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_JAR_SIGNER", permanent_allocator())), NIX_SEPARATOR_STRING); + // Strip trailing slash so system() call doesn't fail. + bc->ODIN_ANDROID_JAR_SIGNER = substring(bc->ODIN_ANDROID_JAR_SIGNER, 0, bc->ODIN_ANDROID_JAR_SIGNER.len - 1); 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"); diff --git a/src/bundle_command.cpp b/src/bundle_command.cpp index b3bca2b51..c5274ca3d 100644 --- a/src/bundle_command.cpp +++ b/src/bundle_command.cpp @@ -132,7 +132,7 @@ i32 bundle_android(String original_init_directory) { if (current_directory.len != 0) { bool ok = set_working_directory(init_directory); if (!ok) { - gb_printf_err("Error: Unable to currectly set the current working directory to '%.*s'\n", LIT(init_directory)); + gb_printf_err("Error: Unable to correctly set the current working directory to '%.*s'\n", LIT(init_directory)); } } @@ -174,7 +174,8 @@ i32 bundle_android(String original_init_directory) { cmd = gb_string_append_length(cmd, build_context.ODIN_ANDROID_JAR_SIGNER.text, build_context.ODIN_ANDROID_JAR_SIGNER.len); cmd = gb_string_append_fmt(cmd, " -storepass android"); if (build_context.android_keystore.len != 0) { - String keystore = concatenate_strings(temporary_allocator(), current_directory, build_context.android_keystore); + String keystore = normalize_path(temporary_allocator(), build_context.android_keystore, NIX_SEPARATOR_STRING); + keystore = substring(keystore, 0, keystore.len - 1); cmd = gb_string_append_fmt(cmd, " -keystore \"%.*s\"", LIT(keystore)); } cmd = gb_string_append_fmt(cmd, " \"%.*s.apk-build\"", LIT(output_apk)); -- cgit v1.2.3 From 4495f0f0f245e4534aa39e153176b42b4d2db8f6 Mon Sep 17 00:00:00 2001 From: IllusionMan1212 Date: Fri, 4 Apr 2025 05:23:12 +0200 Subject: feat: added a `-android-keystore-password` option to pass a password for the keystore instead of hardcoding it as `android` --- src/build_settings.cpp | 5 +++++ src/bundle_command.cpp | 2 +- src/main.cpp | 8 ++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 8339b111a..1e44a8bc5 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -554,6 +554,7 @@ struct BuildContext { String ODIN_ANDROID_JAR_SIGNER; String android_keystore; String android_keystore_alias; + String android_keystore_password; String android_manifest; }; @@ -1593,6 +1594,10 @@ gb_internal void init_android_values(bool with_sdk) { gb_printf_err("Error: -android-keystore_alias: has not been set\n"); gb_exit(1); } + if (bc->android_keystore_password.len == 0) { + gb_printf_err("Error: -android-keystore-password: has not been set\n"); + gb_exit(1); + } } } diff --git a/src/bundle_command.cpp b/src/bundle_command.cpp index c5274ca3d..11ff4e6e1 100644 --- a/src/bundle_command.cpp +++ b/src/bundle_command.cpp @@ -172,7 +172,7 @@ i32 bundle_android(String original_init_directory) { gb_string_clear(cmd); cmd = gb_string_append_length(cmd, build_context.ODIN_ANDROID_JAR_SIGNER.text, build_context.ODIN_ANDROID_JAR_SIGNER.len); - cmd = gb_string_append_fmt(cmd, " -storepass android"); + cmd = gb_string_append_fmt(cmd, " -storepass \"%.*s\"", LIT(build_context.android_keystore_password)); if (build_context.android_keystore.len != 0) { String keystore = normalize_path(temporary_allocator(), build_context.android_keystore, NIX_SEPARATOR_STRING); keystore = substring(keystore, 0, keystore.len - 1); diff --git a/src/main.cpp b/src/main.cpp index c19bbde22..5a54e9bc3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -277,6 +277,7 @@ gb_internal void usage(String argv0, String argv1 = {}) { print_usage_line(1, "build Compiles directory of .odin files, as an executable."); print_usage_line(1, " One must contain the program's entry point, all must be in the same package."); print_usage_line(1, "run Same as 'build', but also then runs the newly compiled executable."); + print_usage_line(1, "bundle Bundles a directory in a specific layout for that platform."); print_usage_line(1, "check Parses, and type checks a directory of .odin files."); print_usage_line(1, "strip-semicolon Parses, type checks, and removes unneeded semicolons from the entire program."); print_usage_line(1, "test Builds and runs procedures with the attribute @(test) in the initial package."); @@ -411,6 +412,7 @@ enum BuildFlagKind { BuildFlag_AndroidKeystore, BuildFlag_AndroidKeystoreAlias, + BuildFlag_AndroidKeystorePassword, BuildFlag_AndroidManifest, BuildFlag_COUNT, @@ -631,6 +633,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_AndroidKeystore, str_lit("android-keystore"), BuildFlagParam_String, Command_bundle_android); add_flag(&build_flags, BuildFlag_AndroidKeystoreAlias, str_lit("android-keystore-alias"), BuildFlagParam_String, Command_bundle_android); + add_flag(&build_flags, BuildFlag_AndroidKeystorePassword, str_lit("android-keystore-password"), BuildFlagParam_String, Command_bundle_android); add_flag(&build_flags, BuildFlag_AndroidManifest, str_lit("android-manifest"), BuildFlagParam_String, Command_bundle_android); @@ -1664,6 +1667,11 @@ gb_internal bool parse_build_flags(Array args) { build_context.android_keystore_alias = value.value_string; break; + case BuildFlag_AndroidKeystorePassword: + GB_ASSERT(value.kind == ExactValue_String); + build_context.android_keystore_password = value.value_string; + break; + case BuildFlag_AndroidManifest: GB_ASSERT(value.kind == ExactValue_String); build_context.android_manifest = value.value_string; -- cgit v1.2.3 From 44950d5f37f1a288182179b9b106f3510f51704e Mon Sep 17 00:00:00 2001 From: IllusionMan1212 Date: Sat, 5 Apr 2025 02:18:06 +0200 Subject: fix: cross-compilation for android on linux add `-nodefaultlibs` when cross-linking for android to prevent clang from linking with libgcc check build mode first before calling `init_android_values` to prevent printing a message that tells the user to set `-android-keystore` if its not set and build mode is exe --- src/build_settings.cpp | 48 ++++++++++++++++++++++++------------------------ src/linker.cpp | 3 ++- 2 files changed, 26 insertions(+), 25 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 1e44a8bc5..2152f7566 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1781,6 +1781,30 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta bc->ODIN_WINDOWS_SUBSYSTEM = windows_subsystem_names[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) { switch (metrics->arch) { case TargetArch_arm64: @@ -1900,30 +1924,6 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta if (bc->metrics.os == TargetOs_freestanding) { bc->ODIN_DEFAULT_TO_NIL_ALLOCATOR = !bc->ODIN_DEFAULT_TO_PANIC_ALLOCATOR; } - - 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 defined(GB_SYSTEM_WINDOWS) diff --git a/src/linker.cpp b/src/linker.cpp index 5c0fe446f..8f484f734 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -143,7 +143,7 @@ gb_internal i32 linker_stage(LinkerData *gen) { LIT(target_arch_names[build_context.metrics.arch]) ); #endif - } else if (build_context.cross_compiling && build_context.different_os) { + } else if (build_context.cross_compiling) { switch (selected_subtarget) { case Subtarget_Android: is_cross_linking = true; @@ -840,6 +840,7 @@ try_cross_linking:; if (is_android) { link_command_line = gb_string_append_fmt(link_command_line, " --target=aarch64-linux-android%d ", ODIN_ANDROID_API_LEVEL); + link_command_line = gb_string_appendc(link_command_line, " -nodefaultlibs"); } link_command_line = gb_string_appendc(link_command_line, " -Wno-unused-command-line-argument "); link_command_line = gb_string_appendc(link_command_line, object_files); -- cgit v1.2.3 From da885fb80789ba07475bd85415f9f0b662e9c282 Mon Sep 17 00:00:00 2001 From: IllusionMan1212 Date: Sat, 5 Apr 2025 02:21:56 +0200 Subject: android bundling improvements replace `jarsigner` with build tools' `apksigner` which is capable of using newer signature schemes remove the `android-manifest` flag and assume the file exists in the directory we're bundling make `android-keystore-alias` and `android-keystore-password` optional. The former is not needed if there's only one key in the keystore, and the latter will be prompted by `apksigner` if missing don't change the working directory to the bundled directory to prevent confusion when passing a relative path to `android-keystore` add the `res`, `assets`, and `lib` directories to the bundle if they exist in the bundled directory --- src/build_settings.cpp | 17 ----------- src/bundle_command.cpp | 78 ++++++++++++++++++++++++++------------------------ src/main.cpp | 11 ++----- 3 files changed, 42 insertions(+), 64 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 2152f7566..954cb018c 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -551,11 +551,9 @@ struct BuildContext { String ODIN_ANDROID_NDK_TOOLCHAIN_LIB_LEVEL; String ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT; - String ODIN_ANDROID_JAR_SIGNER; String android_keystore; String android_keystore_alias; String android_keystore_password; - String android_manifest; }; gb_global BuildContext build_context = {0}; @@ -1574,30 +1572,15 @@ gb_internal void init_android_values(bool with_sdk) { bc->ODIN_ANDROID_NDK_TOOLCHAIN_SYSROOT = concatenate_strings(permanent_allocator(), bc->ODIN_ANDROID_NDK_TOOLCHAIN, str_lit("sysroot/")); - bc->ODIN_ANDROID_JAR_SIGNER = normalize_path(permanent_allocator(), make_string_c(gb_get_env("ODIN_ANDROID_JAR_SIGNER", permanent_allocator())), NIX_SEPARATOR_STRING); - // Strip trailing slash so system() call doesn't fail. - bc->ODIN_ANDROID_JAR_SIGNER = substring(bc->ODIN_ANDROID_JAR_SIGNER, 0, bc->ODIN_ANDROID_JAR_SIGNER.len - 1); 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->ODIN_ANDROID_JAR_SIGNER.len == 0) { - gb_printf_err("Error: ODIN_ANDROID_JAR_SIGNER 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: has not been set\n"); gb_exit(1); } - if (bc->android_keystore_alias.len == 0) { - gb_printf_err("Error: -android-keystore_alias: has not been set\n"); - gb_exit(1); - } - if (bc->android_keystore_password.len == 0) { - gb_printf_err("Error: -android-keystore-password: has not been set\n"); - gb_exit(1); - } } } diff --git a/src/bundle_command.cpp b/src/bundle_command.cpp index 11ff4e6e1..cd0cd589f 100644 --- a/src/bundle_command.cpp +++ b/src/bundle_command.cpp @@ -126,16 +126,6 @@ i32 bundle_android(String original_init_directory) { defer (gb_string_free(cmd)); - String current_directory = normalize_path(temporary_allocator(), get_working_directory(temporary_allocator()), NIX_SEPARATOR_STRING); - defer (set_working_directory(current_directory)); - - if (current_directory.len != 0) { - bool ok = set_working_directory(init_directory); - if (!ok) { - gb_printf_err("Error: Unable to correctly set the current working directory to '%.*s'\n", LIT(init_directory)); - } - } - String output_filename = str_lit("test"); String output_apk = path_remove_extension(output_filename); @@ -144,63 +134,75 @@ i32 bundle_android(String original_init_directory) { TEMPORARY_ALLOCATOR_GUARD(); gb_string_clear(cmd); - String manifest = {}; - if (build_context.android_manifest.len != 0) { - manifest = concatenate_strings(temporary_allocator(), current_directory, build_context.android_manifest); - } else { - manifest = concatenate_strings(temporary_allocator(), init_directory, str_lit("AndroidManifest.xml")); - } + String manifest = concatenate_strings(temporary_allocator(), init_directory, str_lit("AndroidManifest.xml")); cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); cmd = gb_string_appendc(cmd, "aapt"); cmd = gb_string_appendc(cmd, " package -f"); - if (manifest.len != 0) { - cmd = gb_string_append_fmt(cmd, " -M \"%.*s\"", LIT(manifest)); - } + cmd = gb_string_append_fmt(cmd, " -M \"%.*s\"", LIT(manifest)); cmd = gb_string_append_fmt(cmd, " -I \"%.*sandroid.jar\"", LIT(android_sdk_platforms)); cmd = gb_string_append_fmt(cmd, " -F \"%.*s.apk-build\"", LIT(output_apk)); + String resources_dir = concatenate_strings(temporary_allocator(), init_directory, str_lit("res")); + if (gb_file_exists((const char *)resources_dir.text)) { + cmd = gb_string_append_fmt(cmd, " -S \"%.*s\"", LIT(resources_dir)); + } + + String assets_dir = concatenate_strings(temporary_allocator(), init_directory, str_lit("assets")); + if (gb_file_exists((const char *)assets_dir.text)) { + cmd = gb_string_append_fmt(cmd, " -A \"%.*s\"", LIT(assets_dir)); + } + + String lib_dir = concatenate_strings(temporary_allocator(), init_directory, str_lit("lib")); + if (gb_file_exists((const char *)lib_dir.text)) { + cmd = gb_string_append_fmt(cmd, " \"%.*s\"", LIT(lib_dir)); + } + result = system_exec_command_line_app("android-aapt", cmd); if (result) { return result; } } - TIME_SECTION("Android jarsigner"); + TIME_SECTION("Android zipalign"); { TEMPORARY_ALLOCATOR_GUARD(); gb_string_clear(cmd); - cmd = gb_string_append_length(cmd, build_context.ODIN_ANDROID_JAR_SIGNER.text, build_context.ODIN_ANDROID_JAR_SIGNER.len); - cmd = gb_string_append_fmt(cmd, " -storepass \"%.*s\"", LIT(build_context.android_keystore_password)); - if (build_context.android_keystore.len != 0) { - String keystore = normalize_path(temporary_allocator(), build_context.android_keystore, NIX_SEPARATOR_STRING); - keystore = substring(keystore, 0, keystore.len - 1); - cmd = gb_string_append_fmt(cmd, " -keystore \"%.*s\"", LIT(keystore)); - } - cmd = gb_string_append_fmt(cmd, " \"%.*s.apk-build\"", LIT(output_apk)); - if (build_context.android_keystore_alias.len != 0) { - String keystore_alias = build_context.android_keystore_alias; - cmd = gb_string_append_fmt(cmd, " \"%.*s\"", LIT(keystore_alias)); - } + cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); + cmd = gb_string_appendc(cmd, "zipalign"); + cmd = gb_string_appendc(cmd, " -f 4"); + cmd = gb_string_append_fmt(cmd, " \"%.*s.apk-build\" \"%.*s.apk\"", LIT(output_apk), LIT(output_apk)); - result = system_exec_command_line_app("android-jarsigner", cmd); + result = system_exec_command_line_app("android-zipalign", cmd); if (result) { return result; } } - TIME_SECTION("Android zipalign"); + TIME_SECTION("Android apksigner"); { TEMPORARY_ALLOCATOR_GUARD(); gb_string_clear(cmd); cmd = gb_string_append_length(cmd, android_sdk_build_tools.text, android_sdk_build_tools.len); - cmd = gb_string_appendc(cmd, "zipalign"); - cmd = gb_string_appendc(cmd, " -f 4"); - cmd = gb_string_append_fmt(cmd, " \"%.*s.apk-build\" \"%.*s.apk\"", LIT(output_apk), LIT(output_apk)); + cmd = gb_string_appendc(cmd, "apksigner"); + cmd = gb_string_appendc(cmd, " sign"); - result = system_exec_command_line_app("android-zipalign", cmd); + String keystore = normalize_path(temporary_allocator(), build_context.android_keystore, NIX_SEPARATOR_STRING); + keystore = substring(keystore, 0, keystore.len - 1); + cmd = gb_string_append_fmt(cmd, " --ks \"%.*s\"", LIT(keystore)); + + if (build_context.android_keystore_alias.len != 0) { + cmd = gb_string_append_fmt(cmd, " --ks-key-alias \"%.*s\"", LIT(build_context.android_keystore_alias)); + } + if (build_context.android_keystore_password.len != 0) { + cmd = gb_string_append_fmt(cmd, " --ks-pass pass:\"%.*s\"", LIT(build_context.android_keystore_password)); + } + + cmd = gb_string_append_fmt(cmd, " \"%.*s.apk\"", LIT(output_apk)); + + result = system_exec_command_line_app("android-apksigner", cmd); if (result) { return result; } diff --git a/src/main.cpp b/src/main.cpp index 5a54e9bc3..155e48d9c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -413,7 +413,6 @@ enum BuildFlagKind { BuildFlag_AndroidKeystore, BuildFlag_AndroidKeystoreAlias, BuildFlag_AndroidKeystorePassword, - BuildFlag_AndroidManifest, BuildFlag_COUNT, }; @@ -634,7 +633,6 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_AndroidKeystore, str_lit("android-keystore"), BuildFlagParam_String, Command_bundle_android); add_flag(&build_flags, BuildFlag_AndroidKeystoreAlias, str_lit("android-keystore-alias"), BuildFlagParam_String, Command_bundle_android); add_flag(&build_flags, BuildFlag_AndroidKeystorePassword, str_lit("android-keystore-password"), BuildFlagParam_String, Command_bundle_android); - add_flag(&build_flags, BuildFlag_AndroidManifest, str_lit("android-manifest"), BuildFlagParam_String, Command_bundle_android); Array flag_args = {}; @@ -1671,11 +1669,6 @@ gb_internal bool parse_build_flags(Array args) { GB_ASSERT(value.kind == ExactValue_String); build_context.android_keystore_password = value.value_string; break; - - case BuildFlag_AndroidManifest: - GB_ASSERT(value.kind == ExactValue_String); - build_context.android_manifest = value.value_string; - break; } } @@ -2208,7 +2201,7 @@ gb_internal void remove_temp_files(lbGenerator *gen) { return; } - TIME_SECTION("remove keep temp files"); + TIME_SECTION("remove temp files"); for (String const &path : gen->output_temp_paths) { gb_file_remove(cast(char const *)path.text); @@ -2560,7 +2553,7 @@ gb_internal void print_show_help(String const arg0, String command, String optio if (print_flag("-minimum-os-version:")) { print_usage_line(2, "Sets the minimum OS version targeted by the application."); print_usage_line(2, "Default: -minimum-os-version:11.0.0"); - print_usage_line(2, "Only used when target is Darwin, if given, linking mismatched versions will emit a warning."); + print_usage_line(2, "Only used when target is Darwin or subtarget is Android, if given, linking mismatched versions will emit a warning."); } } -- cgit v1.2.3 From 5e63388de289f6cbf17e3fdae60f3a092f4419e5 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 10 Apr 2025 11:07:44 +0100 Subject: Fix `init_android_values` SDK check for `odin check` --- src/build_settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 954cb018c..c2575e2d4 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1863,7 +1863,7 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta 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); + init_android_values(bc->build_mode == BuildMode_Executable && (bc->command_kind & Command__does_build) != 0); } if (!bc->custom_optimization_level) { -- cgit v1.2.3 From 1f814c33dcfccec9073d15214268457c0d6ea273 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 10 Apr 2025 11:36:03 +0100 Subject: Support subtargets in build tags: `#build darwin:generic` and `#build linux:android, darwin:ios` --- base/runtime/core.odin | 4 +++ core/odin/parser/file_tags.odin | 24 ++++++++++--- src/build_settings.cpp | 34 +++++++++++++++--- src/parser.cpp | 12 ++++--- src/string.cpp | 77 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 138 insertions(+), 13 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/base/runtime/core.odin b/base/runtime/core.odin index cd7d35540..5ab8a7008 100644 --- a/base/runtime/core.odin +++ b/base/runtime/core.odin @@ -559,10 +559,14 @@ ALL_ODIN_OS_TYPES :: Odin_OS_Types{ Odin_Platform_Subtarget_Type :: enum int { Default, iOS, + Android, } */ Odin_Platform_Subtarget_Type :: type_of(ODIN_PLATFORM_SUBTARGET) +Odin_Platform_Subtarget_Types :: bit_set[Odin_Platform_Subtarget_Type] + + /* // Defined internally by the compiler Odin_Sanitizer_Flag :: enum u32 { diff --git a/core/odin/parser/file_tags.odin b/core/odin/parser/file_tags.odin index c5c6637c3..fff59ee1e 100644 --- a/core/odin/parser/file_tags.odin +++ b/core/odin/parser/file_tags.odin @@ -30,14 +30,27 @@ File_Tags :: struct { } @require_results -get_build_os_from_string :: proc(str: string) -> runtime.Odin_OS_Type { +get_build_os_from_string :: proc(str: string) -> (found_os: runtime.Odin_OS_Type, found_subtarget: runtime.Odin_Platform_Subtarget_Type) { + str_os, _, str_subtarget := strings.partition(str, ":") + fields := reflect.enum_fields_zipped(runtime.Odin_OS_Type) for os in fields { - if strings.equal_fold(os.name, str) { - return runtime.Odin_OS_Type(os.value) + if strings.equal_fold(os.name, str_os) { + found_os = runtime.Odin_OS_Type(os.value) + break } } - return .Unknown + if str_subtarget != "" { + fields := reflect.enum_fields_zipped(runtime.Odin_Platform_Subtarget_Type) + for subtarget in fields { + if strings.equal_fold(subtarget.name, str_subtarget) { + found_subtarget = runtime.Odin_Platform_Subtarget_Type(subtarget.value) + break + } + } + } + + return } @require_results get_build_arch_from_string :: proc(str: string) -> runtime.Odin_Arch_Type { @@ -187,7 +200,8 @@ parse_file_tags :: proc(file: ast.File, allocator := context.allocator) -> (tags if value == "ignore" { tags.ignore = true - } else if os := get_build_os_from_string(value); os != .Unknown { + } else if os, subtarget := get_build_os_from_string(value); os != .Unknown { + _ = subtarget // TODO(bill): figure out how to handle the subtarget logic if is_notted { os_negative += {os} } else { diff --git a/src/build_settings.cpp b/src/build_settings.cpp index c2575e2d4..c941e0f68 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -847,13 +847,39 @@ 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 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; } } - return TargetOs_Invalid; + if (subtarget_) *subtarget_ = Subtarget_Default; + + if (subtarget.len != 0) { + if (str_eq_ignore_case(subtarget, "generic") || str_eq_ignore_case(subtarget, "default")) { + if (subtarget_) *subtarget_ = Subtarget_Default; + } else { + for (isize i = 1; i < Subtarget_COUNT; i++) { + if (str_eq_ignore_case(subtarget_strings[i], subtarget)) { + if (subtarget_) *subtarget_ = cast(Subtarget)i; + break; + } + } + } + } + + return kind; } gb_internal TargetArchKind get_target_arch_from_string(String str) { diff --git a/src/parser.cpp b/src/parser.cpp index f38f79607..a397585e8 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -6157,7 +6157,7 @@ gb_internal String build_tag_get_token(String s, String *out) { isize width = utf8_decode(&s[n], s.len-n, &rune); if (n == 0 && rune == '!') { - } else if (!rune_is_letter(rune) && !rune_is_digit(rune)) { + } else if (!rune_is_letter(rune) && !rune_is_digit(rune) && rune != ':') { isize k = gb_max(gb_max(n, width), 1); *out = substring(s, k, s.len); return substring(s, 0, k); @@ -6209,7 +6209,9 @@ gb_internal bool parse_build_tag(Token token_for_pos, String s) { continue; } - TargetOsKind os = get_target_os_from_string(p); + Subtarget subtarget = Subtarget_Default; + + TargetOsKind os = get_target_os_from_string(p, &subtarget); TargetArchKind arch = get_target_arch_from_string(p); num_tokens += 1; @@ -6223,11 +6225,13 @@ gb_internal bool parse_build_tag(Token token_for_pos, String s) { if (os != TargetOs_Invalid) { this_kind_os_seen = true; + bool same_subtarget = (subtarget == Subtarget_Default) || (subtarget == selected_subtarget); + GB_ASSERT(arch == TargetArch_Invalid); if (is_notted) { - this_kind_correct = this_kind_correct && (os != build_context.metrics.os); + this_kind_correct = this_kind_correct && (os != build_context.metrics.os || !same_subtarget); } else { - this_kind_correct = this_kind_correct && (os == build_context.metrics.os); + this_kind_correct = this_kind_correct && (os == build_context.metrics.os && same_subtarget); } } else if (arch != TargetArch_Invalid) { this_kind_arch_seen = true; diff --git a/src/string.cpp b/src/string.cpp index 88b679540..ae8d066b1 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -336,6 +336,83 @@ gb_internal Array split_lines_from_array(Array const &array, gbAlloc return lines; } +enum : u32 { PRIME_RABIN_KARP = 16777619u }; + +gb_internal u32 hash_str_rabin_karp(String const &s, u32 *pow_) { + u32 hash = 0; + u32 pow = 1; + for (isize i = 0; i < s.len; i++) { + hash = hash*PRIME_RABIN_KARP + cast(u32)s.text[i]; + } + u32 sq = PRIME_RABIN_KARP; + for (isize i = s.len; i > 0; i >>= 1) { + if ((i & 1) != 0) { + pow *= sq; + } + sq *= sq; + } + if (pow_) *pow_ = pow; + return hash; + +} + + +gb_internal isize string_index(String const &s, String const &substr) { + isize n = substr.len; + if (n == 0) { + return 0; + } else if (n == 1) { + return string_index_byte(s, substr[0]); + } else if (n == s.len) { + if (s == substr) { + return 0; + } + return -1; + } else if (n > s.len) { + return -1; + } + u32 pow = 1; + u32 hash = hash_str_rabin_karp(s, &pow); + u32 h = 0; + for (isize i = 0; i < n; i++) { + h = h*PRIME_RABIN_KARP + cast(u32)s.text[i]; + } + if (h == hash && substring(s, 0, n) == substr) { + return 0; + } + for (isize i = n; i < s.len; /**/) { + h *= PRIME_RABIN_KARP; + h += cast(u32)s.text[i]; + h -= pow * u32(s.text[i-n]); + i += 1; + if (h == hash && substring(s, i-n, i) == substr) { + return i - n; + } + } + return -1; +} + + +struct StringPartition { + String head; + String match; + String tail; +}; + +gb_internal StringPartition string_partition(String const &str, String const &sep) { + StringPartition res = {}; + isize i = string_index(str, sep); + if (i < 0) { + res.head = str; + return res; + } + + res.head = substring(str, 0, i); + res.match = substring(str, i, i+sep.len); + res.tail = substring(str, i+sep.len, str.len); + return res; +} + gb_internal bool string_contains_char(String const &s, u8 c) { isize i; for (i = 0; i < s.len; i++) { -- cgit v1.2.3 From eb051a2d7c0ddfa1b28d22ba5466ea973eb0e40d Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Sun, 18 May 2025 17:13:39 -0400 Subject: Re-enable static map calls on AMD64 SysV --- src/build_settings.cpp | 6 ------ 1 file changed, 6 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index c941e0f68..04101761c 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1915,12 +1915,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) { -- cgit v1.2.3 From ab9593250295137d0a654e942965feee7f506206 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Mon, 19 May 2025 20:44:27 +0200 Subject: -dynamic-literals --- src/build_settings.cpp | 1 + src/check_expr.cpp | 2 +- src/llvm_backend_expr.cpp | 2 +- src/main.cpp | 5 +++++ 4 files changed, 8 insertions(+), 2 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 04101761c..8364bbfbe 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -459,6 +459,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; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 7ccca1b57..167052772 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -9433,7 +9433,7 @@ gb_internal bool is_expr_inferred_fixed_array(Ast *type_expr) { } gb_internal bool check_for_dynamic_literals(CheckerContext *c, Ast *node, AstCompoundLit *cl) { - if (cl->elems.count > 0 && (check_feature_flags(c, node) & OptInFeatureFlag_DynamicLiterals) == 0) { + if (cl->elems.count > 0 && (check_feature_flags(c, node) & OptInFeatureFlag_DynamicLiterals) == 0 && !build_context.dynamic_literals) { ERROR_BLOCK(); error(node, "Compound literals of dynamic types are disabled by default"); error_line("\tSuggestion: If you want to enable them for this specific file, add '#+feature dynamic-literals' at the top of the file\n"); diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 0909b189a..e17d958d7 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -4844,7 +4844,7 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) { if (cl->elems.count == 0) { break; } - GB_ASSERT(expr->file()->feature_flags & OptInFeatureFlag_DynamicLiterals); + GB_ASSERT(expr->file()->feature_flags & OptInFeatureFlag_DynamicLiterals || build_context.dynamic_literals); lbValue err = lb_dynamic_map_reserve(p, v.addr, 2*cl->elems.count, pos); gb_unused(err); diff --git a/src/main.cpp b/src/main.cpp index 00032c1ff..3692e4f06 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -319,6 +319,7 @@ enum BuildFlagKind { BuildFlag_NoBoundsCheck, BuildFlag_NoTypeAssert, BuildFlag_NoDynamicLiterals, + BuildFlag_DynamicLiterals, BuildFlag_NoCRT, BuildFlag_NoRPath, BuildFlag_NoEntryPoint, @@ -538,6 +539,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_NoTypeAssert, str_lit("no-type-assert"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_NoThreadLocal, str_lit("no-thread-local"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_NoDynamicLiterals, str_lit("no-dynamic-literals"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_DynamicLiterals, str_lit("dynamic-literals"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_NoCRT, str_lit("no-crt"), BuildFlagParam_None, Command__does_build); add_flag(&build_flags, BuildFlag_NoRPath, str_lit("no-rpath"), BuildFlagParam_None, Command__does_build); add_flag(&build_flags, BuildFlag_NoEntryPoint, str_lit("no-entry-point"), BuildFlagParam_None, Command__does_check &~ Command_test); @@ -1207,6 +1209,9 @@ gb_internal bool parse_build_flags(Array args) { case BuildFlag_NoDynamicLiterals: gb_printf_err("Warning: Use of -no-dynamic-literals is now redundant\n"); break; + case BuildFlag_DynamicLiterals: + build_context.dynamic_literals = true; + break; case BuildFlag_NoCRT: build_context.no_crt = true; break; -- cgit v1.2.3 From e35e1dcc7b4814a063c94b9bb02f1e371ae251a5 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Thu, 22 May 2025 08:08:53 -0400 Subject: Only trim `.odin` from build filenames --- src/build_settings.cpp | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 8364bbfbe..b3bbf726b 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -2209,11 +2209,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) { -- cgit v1.2.3 From 0536f8626833e6b2938cbedf84b2cf06c95c0ae0 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Thu, 22 May 2025 17:33:24 -0400 Subject: Add `-build-only` for `odin test` command This allows test executables to be only built, not run too. --- src/build_settings.cpp | 1 + src/main.cpp | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index b3bbf726b..ae6fa3463 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -441,6 +441,7 @@ struct BuildContext { String extra_assembler_flags; String microarch; BuildModeKind build_mode; + bool build_only; bool generate_docs; bool custom_optimization_level; i32 optimization_level; diff --git a/src/main.cpp b/src/main.cpp index 90f2aad7a..5aaadc0d2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -312,6 +312,7 @@ enum BuildFlagKind { BuildFlag_Collection, BuildFlag_Define, BuildFlag_BuildMode, + BuildFlag_BuildOnly, BuildFlag_Target, BuildFlag_Subtarget, BuildFlag_Debug, @@ -531,6 +532,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Collection, str_lit("collection"), BuildFlagParam_String, Command__does_check); add_flag(&build_flags, BuildFlag_Define, str_lit("define"), BuildFlagParam_String, Command__does_check, true); add_flag(&build_flags, BuildFlag_BuildMode, str_lit("build-mode"), BuildFlagParam_String, Command__does_build); // Commands_build is not used to allow for a better error message + add_flag(&build_flags, BuildFlag_BuildOnly, str_lit("build-only"), BuildFlagParam_None, Command_test); add_flag(&build_flags, BuildFlag_Target, str_lit("target"), BuildFlagParam_String, Command__does_check); add_flag(&build_flags, BuildFlag_Subtarget, str_lit("subtarget"), BuildFlagParam_String, Command__does_check); add_flag(&build_flags, BuildFlag_Debug, str_lit("debug"), BuildFlagParam_None, Command__does_check); @@ -1193,6 +1195,9 @@ gb_internal bool parse_build_flags(Array args) { break; } + case BuildFlag_BuildOnly: + build_context.build_only = true; + break; case BuildFlag_Debug: build_context.ODIN_DEBUG = true; @@ -2381,6 +2386,12 @@ gb_internal int print_show_help(String const arg0, String command, String option } } + if (test_only) { + if (print_flag("-build-only")) { + print_usage_line(2, "Only builds the test executable; does not automatically run it afterwards."); + } + } + if (check) { if (print_flag("-collection:=")) { print_usage_line(2, "Defines a library collection used for imports."); @@ -3861,7 +3872,7 @@ end_of_code_gen:; show_timings(checker, &global_timings); } - if (run_output) { + if (!build_context.build_only && run_output) { String exe_name = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Output]); defer (gb_free(heap_allocator(), exe_name.text)); -- cgit v1.2.3 From 5b5822effce461e3ecfdc3b57009736208999959 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Thu, 22 May 2025 17:54:15 -0400 Subject: Delete test executable after running, add `-keep-test-executable` --- src/build_settings.cpp | 1 + src/main.cpp | 30 +++++++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index ae6fa3463..4f573a8ca 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -442,6 +442,7 @@ struct BuildContext { String microarch; BuildModeKind build_mode; bool build_only; + bool keep_test_executable; bool generate_docs; bool custom_optimization_level; i32 optimization_level; diff --git a/src/main.cpp b/src/main.cpp index 5aaadc0d2..faedb9074 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -313,6 +313,7 @@ enum BuildFlagKind { BuildFlag_Define, BuildFlag_BuildMode, BuildFlag_BuildOnly, + BuildFlag_KeepTestExecutable, BuildFlag_Target, BuildFlag_Subtarget, BuildFlag_Debug, @@ -533,6 +534,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Define, str_lit("define"), BuildFlagParam_String, Command__does_check, true); add_flag(&build_flags, BuildFlag_BuildMode, str_lit("build-mode"), BuildFlagParam_String, Command__does_build); // Commands_build is not used to allow for a better error message add_flag(&build_flags, BuildFlag_BuildOnly, str_lit("build-only"), BuildFlagParam_None, Command_test); + add_flag(&build_flags, BuildFlag_KeepTestExecutable, str_lit("keep-test-executable"), BuildFlagParam_None, Command_test); add_flag(&build_flags, BuildFlag_Target, str_lit("target"), BuildFlagParam_String, Command__does_check); add_flag(&build_flags, BuildFlag_Subtarget, str_lit("subtarget"), BuildFlagParam_String, Command__does_check); add_flag(&build_flags, BuildFlag_Debug, str_lit("debug"), BuildFlagParam_None, Command__does_check); @@ -1196,7 +1198,22 @@ gb_internal bool parse_build_flags(Array args) { break; } case BuildFlag_BuildOnly: - build_context.build_only = true; + if (build_context.keep_test_executable) { + gb_printf_err("`-keep-test-executable` is mutually exclusive with `-build-only`.\n"); + gb_printf_err("We either only build or run the test and optionally keep the executable.\n"); + bad_flags = true; + } else { + build_context.build_only = true; + } + break; + case BuildFlag_KeepTestExecutable: + if (build_context.build_only) { + gb_printf_err("`-build-only` is mutually exclusive with `-keep-test-executable`.\n"); + gb_printf_err("We either only build or run the test and optionally keep the executable.\n"); + bad_flags = true; + } else { + build_context.keep_test_executable = true; + } break; case BuildFlag_Debug: @@ -2554,6 +2571,12 @@ gb_internal int print_show_help(String const arg0, String command, String option } } + if (test_only) { + if (print_flag("-keep-test-executable")) { + print_usage_line(2, "Keep the test executable after running it instead of deleting it normally."); + } + } + if (run_or_build) { if (print_flag("-linker:")) { print_usage_line(2, "Specify the linker to use."); @@ -3877,6 +3900,11 @@ end_of_code_gen:; defer (gb_free(heap_allocator(), exe_name.text)); system_must_exec_command_line_app("odin run", "\"%.*s\" %.*s", LIT(exe_name), LIT(run_args_string)); + + if (build_context.command_kind == Command_test && !build_context.keep_test_executable) { + char const *filename = cast(char const *)exe_name.text; + gb_file_remove(filename); + } } return 0; } -- cgit v1.2.3 From 6c5b96948e827a0b22435c1bb367414c8a187666 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Thu, 22 May 2025 20:47:10 -0400 Subject: Enable all sanitizers on FreeBSD --- src/build_settings.cpp | 12 ++++++------ src/linker.cpp | 12 ++++++++++++ src/llvm_backend.cpp | 20 ++++++++++++++++---- 3 files changed, 34 insertions(+), 10 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 4f573a8ca..9c530df19 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -2303,9 +2303,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; } } @@ -2313,12 +2314,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; } } @@ -2327,9 +2326,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; } } diff --git a/src/linker.cpp b/src/linker.cpp index 41d4a13a1..447d66d0a 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -802,6 +802,18 @@ try_cross_linking:; link_settings = gb_string_appendc(link_settings, "-e _main "); } } else if (build_context.metrics.os == TargetOs_freebsd) { + if (build_context.sanitizer_flags & (SanitizerFlag_Address | SanitizerFlag_Memory)) { + // It's imperative that `pthread` is linked before `libc`, + // otherwise ASan/MSan will be unable to call `pthread_key_create` + // because FreeBSD's `libthr` implementation of `pthread` + // needs to replace the relevant stubs first. + // + // (Presumably TSan implements its own `pthread` interface, + // which is why it isn't required.) + // + // See: https://reviews.llvm.org/D39254 + platform_lib_str = gb_string_appendc(platform_lib_str, "-lpthread "); + } // FreeBSD pkg installs third-party shared libraries in /usr/local/lib. platform_lib_str = gb_string_appendc(platform_lib_str, "-Wl,-L/usr/local/lib "); } else if (build_context.metrics.os == TargetOs_openbsd) { diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index f0bbe5473..90e7b2793 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -3425,36 +3425,48 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { if (build_context.sanitizer_flags & SanitizerFlag_Address) { - if (build_context.metrics.os == TargetOs_windows) { + switch (build_context.metrics.os) { + case TargetOs_windows: { auto paths = array_make(heap_allocator(), 0, 1); String path = concatenate_strings(permanent_allocator(), build_context.ODIN_ROOT, str_lit("\\bin\\llvm\\windows\\clang_rt.asan-x86_64.lib")); array_add(&paths, path); Entity *lib = alloc_entity_library_name(nullptr, make_token_ident("asan_lib"), nullptr, slice_from_array(paths), str_lit("asan_lib")); array_add(&gen->foreign_libraries, lib); - } else if (build_context.metrics.os == TargetOs_darwin || build_context.metrics.os == TargetOs_linux) { + } break; + case TargetOs_darwin: + case TargetOs_linux: + case TargetOs_freebsd: if (!build_context.extra_linker_flags.text) { build_context.extra_linker_flags = str_lit("-fsanitize=address"); } else { build_context.extra_linker_flags = concatenate_strings(permanent_allocator(), build_context.extra_linker_flags, str_lit(" -fsanitize=address")); } + break; } } if (build_context.sanitizer_flags & SanitizerFlag_Memory) { - if (build_context.metrics.os == TargetOs_darwin || build_context.metrics.os == TargetOs_linux) { + switch (build_context.metrics.os) { + case TargetOs_linux: + case TargetOs_freebsd: if (!build_context.extra_linker_flags.text) { build_context.extra_linker_flags = str_lit("-fsanitize=memory"); } else { build_context.extra_linker_flags = concatenate_strings(permanent_allocator(), build_context.extra_linker_flags, str_lit(" -fsanitize=memory")); } + break; } } if (build_context.sanitizer_flags & SanitizerFlag_Thread) { - if (build_context.metrics.os == TargetOs_darwin || build_context.metrics.os == TargetOs_linux) { + switch (build_context.metrics.os) { + case TargetOs_darwin: + case TargetOs_linux: + case TargetOs_freebsd: if (!build_context.extra_linker_flags.text) { build_context.extra_linker_flags = str_lit("-fsanitize=thread"); } else { build_context.extra_linker_flags = concatenate_strings(permanent_allocator(), build_context.extra_linker_flags, str_lit(" -fsanitize=thread")); } + break; } } -- cgit v1.2.3 From 12167bace05915abda62c93881d711e993e062cd Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Fri, 23 May 2025 08:28:27 +0200 Subject: Tweak #5202 Back out the new `-build-only` for tests in favor of the more established `-build-mode:test`, but retain the new `-keep-test-executable` option and default cleanup of test executables. --- src/build_settings.cpp | 1 - src/main.cpp | 25 +++++-------------------- 2 files changed, 5 insertions(+), 21 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 9c530df19..ecbe0a45a 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -441,7 +441,6 @@ struct BuildContext { String extra_assembler_flags; String microarch; BuildModeKind build_mode; - bool build_only; bool keep_test_executable; bool generate_docs; bool custom_optimization_level; diff --git a/src/main.cpp b/src/main.cpp index faedb9074..e905d291d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -312,7 +312,6 @@ enum BuildFlagKind { BuildFlag_Collection, BuildFlag_Define, BuildFlag_BuildMode, - BuildFlag_BuildOnly, BuildFlag_KeepTestExecutable, BuildFlag_Target, BuildFlag_Subtarget, @@ -533,7 +532,6 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Collection, str_lit("collection"), BuildFlagParam_String, Command__does_check); add_flag(&build_flags, BuildFlag_Define, str_lit("define"), BuildFlagParam_String, Command__does_check, true); add_flag(&build_flags, BuildFlag_BuildMode, str_lit("build-mode"), BuildFlagParam_String, Command__does_build); // Commands_build is not used to allow for a better error message - add_flag(&build_flags, BuildFlag_BuildOnly, str_lit("build-only"), BuildFlagParam_None, Command_test); add_flag(&build_flags, BuildFlag_KeepTestExecutable, str_lit("keep-test-executable"), BuildFlagParam_None, Command_test); add_flag(&build_flags, BuildFlag_Target, str_lit("target"), BuildFlagParam_String, Command__does_check); add_flag(&build_flags, BuildFlag_Subtarget, str_lit("subtarget"), BuildFlagParam_String, Command__does_check); @@ -1197,23 +1195,8 @@ gb_internal bool parse_build_flags(Array args) { break; } - case BuildFlag_BuildOnly: - if (build_context.keep_test_executable) { - gb_printf_err("`-keep-test-executable` is mutually exclusive with `-build-only`.\n"); - gb_printf_err("We either only build or run the test and optionally keep the executable.\n"); - bad_flags = true; - } else { - build_context.build_only = true; - } - break; case BuildFlag_KeepTestExecutable: - if (build_context.build_only) { - gb_printf_err("`-build-only` is mutually exclusive with `-keep-test-executable`.\n"); - gb_printf_err("We either only build or run the test and optionally keep the executable.\n"); - bad_flags = true; - } else { - build_context.keep_test_executable = true; - } + build_context.keep_test_executable = true; break; case BuildFlag_Debug: @@ -2573,7 +2556,9 @@ gb_internal int print_show_help(String const arg0, String command, String option if (test_only) { if (print_flag("-keep-test-executable")) { - print_usage_line(2, "Keep the test executable after running it instead of deleting it normally."); + print_usage_line(2, "Keep the test executable after running it with `odin test`, instead of deleting it after the test completes."); + print_usage_line(2, "If you build your your tests using `odin build -build-mode:test`, the compiler does not execute"); + print_usage_line(2, "the resulting test program, and this option is not applicable."); } } @@ -3895,7 +3880,7 @@ end_of_code_gen:; show_timings(checker, &global_timings); } - if (!build_context.build_only && run_output) { + if (run_output) { String exe_name = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Output]); defer (gb_free(heap_allocator(), exe_name.text)); -- cgit v1.2.3 From 84b140f963126391faba0a5e873f119803d80c3c Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Fri, 23 May 2025 08:47:48 +0200 Subject: Rename -keep-test-executable to -keep-executable --- src/build_settings.cpp | 2 +- src/main.cpp | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index ecbe0a45a..00594c1b4 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -441,7 +441,7 @@ struct BuildContext { String extra_assembler_flags; String microarch; BuildModeKind build_mode; - bool keep_test_executable; + bool keep_executable; bool generate_docs; bool custom_optimization_level; i32 optimization_level; diff --git a/src/main.cpp b/src/main.cpp index d28faf77c..1ffdd0dba 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -312,7 +312,7 @@ enum BuildFlagKind { BuildFlag_Collection, BuildFlag_Define, BuildFlag_BuildMode, - BuildFlag_KeepTestExecutable, + BuildFlag_KeepExecutable, BuildFlag_Target, BuildFlag_Subtarget, BuildFlag_Debug, @@ -532,7 +532,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Collection, str_lit("collection"), BuildFlagParam_String, Command__does_check); add_flag(&build_flags, BuildFlag_Define, str_lit("define"), BuildFlagParam_String, Command__does_check, true); add_flag(&build_flags, BuildFlag_BuildMode, str_lit("build-mode"), BuildFlagParam_String, Command__does_build); // Commands_build is not used to allow for a better error message - add_flag(&build_flags, BuildFlag_KeepTestExecutable, str_lit("keep-test-executable"), BuildFlagParam_None, Command_test); + add_flag(&build_flags, BuildFlag_KeepExecutable, str_lit("keep-executable"), BuildFlagParam_None, Command__does_build | Command_test); add_flag(&build_flags, BuildFlag_Target, str_lit("target"), BuildFlagParam_String, Command__does_check); add_flag(&build_flags, BuildFlag_Subtarget, str_lit("subtarget"), BuildFlagParam_String, Command__does_check); add_flag(&build_flags, BuildFlag_Debug, str_lit("debug"), BuildFlagParam_None, Command__does_check); @@ -1195,8 +1195,8 @@ gb_internal bool parse_build_flags(Array args) { break; } - case BuildFlag_KeepTestExecutable: - build_context.keep_test_executable = true; + case BuildFlag_KeepExecutable: + build_context.keep_executable = true; break; case BuildFlag_Debug: @@ -2554,11 +2554,11 @@ gb_internal int print_show_help(String const arg0, String command, String option } } - if (test_only) { - if (print_flag("-keep-test-executable")) { - print_usage_line(2, "Keep the test executable after running it with `odin test`, instead of deleting it after the test completes."); - print_usage_line(2, "If you build your tests using `odin build -build-mode:test`, the compiler does not execute"); - print_usage_line(2, "the resulting test program, and this option is not applicable."); + if (test_only || run_or_build) { + if (print_flag("-keep-executable")) { + print_usage_line(2, "Keep the executable generated by `odin test` or `odin run` after running it. We clean it up by default."); + print_usage_line(2, "If you build your program or test using `odin build`, the compiler does not automatically execute"); + print_usage_line(2, "the resulting program, and this option is not applicable."); } } @@ -3886,7 +3886,7 @@ end_of_code_gen:; system_must_exec_command_line_app("odin run", "\"%.*s\" %.*s", LIT(exe_name), LIT(run_args_string)); - if (build_context.command_kind == Command_test && !build_context.keep_test_executable) { + if (!build_context.keep_executable) { char const *filename = cast(char const *)exe_name.text; gb_file_remove(filename); } -- cgit v1.2.3 From 229c734820f4cfa3deb84386e1613a982d92eede Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Mon, 26 May 2025 18:58:59 +0200 Subject: Add comments to `builtin.odin`, documenting ODIN_* constants. (#5218) And document constants not previously listed. --- base/builtin/builtin.odin | 230 ++++++++++++++++++++++++++++++++++++++++++++-- src/build_settings.cpp | 135 +++++++++++++-------------- src/checker.cpp | 31 +++++-- src/linker.cpp | 6 +- src/main.cpp | 10 +- 5 files changed, 324 insertions(+), 88 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/base/builtin/builtin.odin b/base/builtin/builtin.odin index 14da9603d..019fd93ff 100644 --- a/base/builtin/builtin.odin +++ b/base/builtin/builtin.odin @@ -7,13 +7,226 @@ nil :: nil false :: 0!=0 true :: 0==0 -ODIN_OS :: ODIN_OS -ODIN_ARCH :: ODIN_ARCH -ODIN_ENDIAN :: ODIN_ENDIAN -ODIN_VENDOR :: ODIN_VENDOR -ODIN_VERSION :: ODIN_VERSION -ODIN_ROOT :: ODIN_ROOT -ODIN_DEBUG :: ODIN_DEBUG +// The following constants are added in `checker.cpp`'s `init_universal` procedure. + +/* + An `enum` value indicating what the CPU architecture of the target is. + Possible values are: `.amd64`, `.i386`, `.arm32`, `.arm64`, `.wasm32`, `.wasm64p32`, and `.riscv64`. +*/ +ODIN_ARCH :: ODIN_ARCH + +/* + A `string` indicating what the CPU architecture of the target is. + Possible values are: "amd64", "i386", "arm32", "arm64", "wasm32", "wasm64p32", "riscv64". +*/ +ODIN_ARCH_STRING :: ODIN_ARCH_STRING + +/* + An `enum` value indicating the type of compiled output, chosen using `-build-mode`. + Possible values are: `.Executable`, `.Dynamic`, `.Static`, `.Object`, `.Assembly`, and `.LLVM_IR`. +*/ +ODIN_BUILD_MODE :: ODIN_BUILD_MODE + +/* + A `string` containing the name of the folder that contains the entry point, + e.g. for `%ODIN_ROOT%/examples/demo`, this would contain `demo`. +*/ +ODIN_BUILD_PROJECT_NAME :: ODIN_BUILD_PROJECT_NAME + +/* + An `i64` containing the time at which the executable was compiled, in nanoseconds. + This is compatible with the `time.Time` type, i.e. `time.Time{_nsec=ODIN_COMPILE_TIMESTAMP}` +*/ +ODIN_COMPILE_TIMESTAMP :: ODIN_COMPILE_TIMESTAMP + +/* + `true` if the `-debug` command line switch is passed, which enables debug info generation. +*/ +ODIN_DEBUG :: ODIN_DEBUG + +/* + `true` if the `-default-to-nil-allocator` command line switch is passed, + which sets the initial `context.allocator` to an allocator that does nothing. +*/ +ODIN_DEFAULT_TO_NIL_ALLOCATOR :: ODIN_DEFAULT_TO_NIL_ALLOCATOR + +/* + `true` if the `-default-to-panic-allocator` command line switch is passed, + which sets the initial `context.allocator` to an allocator that panics if allocated from. +*/ +ODIN_DEFAULT_TO_PANIC_ALLOCATOR :: ODIN_DEFAULT_TO_PANIC_ALLOCATOR + +/* + `true` if the `-disable-assert` command line switch is passed, + which removes all calls to `assert` from the program. +*/ +ODIN_DISABLE_ASSERT :: ODIN_DISABLE_ASSERT + +/* + An `enum` value indicating the endianness of the target. + Possible values are: `.Little` and `.Big`. +*/ +ODIN_ENDIAN :: ODIN_ENDIAN + +/* + An `enum` value indicating the endianness of the target. + Possible values are: "little" and "big". +*/ +ODIN_ENDIAN_STRING :: ODIN_ENDIAN_STRING + +/* + An `enum` value set using the `-error-pos-style` switch, indicating the source location style used for compile errors and warnings. + Possible values are: `.Default` (Odin-style) and `.Unix`. +*/ +ODIN_ERROR_POS_STYLE :: ODIN_ERROR_POS_STYLE + +/* + `true` if the `-foreign-error-procedures` command line switch is passed, + which inhibits generation of runtime error procedures, so that they can be in a separate compilation unit. +*/ +ODIN_FOREIGN_ERROR_PROCEDURES :: ODIN_FOREIGN_ERROR_PROCEDURES + +/* + A `string` describing the microarchitecture used for code generation. + If not set using the `-microarch` command line switch, the compiler will pick a default. + Possible values include, but are not limited to: "sandybridge", "x86-64-v2". +*/ +ODIN_MICROARCH_STRING :: ODIN_MICROARCH_STRING + +/* + An `int` value representing the minimum OS version given to the linker, calculated as `major * 10_000 + minor * 100 + revision`. + If not set using the `-minimum-os-version` command line switch, it defaults to `0`. +*/ +ODIN_MINIMUM_OS_VERSION :: ODIN_MINIMUM_OS_VERSION + +/* + `true` if the `-no-bounds-check` command line switch is passed, which disables bounds checking at runtime. +*/ +ODIN_NO_BOUNDS_CHECK :: ODIN_NO_BOUNDS_CHECK + +/* + `true` if the `-no-crt` command line switch is passed, which inhibits linking with the C Runtime Library, a.k.a. LibC. +*/ +ODIN_NO_CRT :: ODIN_NO_CRT + +/* + `true` if the `-no-entry-point` command line switch is passed, which makes the declaration of a `main` procedure optional. +*/ +ODIN_NO_ENTRY_POINT :: ODIN_NO_ENTRY_POINT + +/* + `true` if the `-no-rtti` command line switch is passed, which inhibits generation of full Runtime Type Information. +*/ +ODIN_NO_RTTI :: ODIN_NO_RTTI + +/* + `true` if the `-no-type-assert` command line switch is passed, which disables type assertion checking program wide. +*/ +ODIN_NO_TYPE_ASSERT :: ODIN_NO_TYPE_ASSERT + +/* + An `enum` value indicating the optimization level selected using the `-o` command line switch. + Possible values are: `.None`, `.Minimal`, `.Size`, `.Speed`, and `.Aggressive`. +*/ +ODIN_OPTIMIZATION_MODE :: ODIN_OPTIMIZATION_MODE + +/* + An `enum` value indicating what the target operating system is. +*/ +ODIN_OS :: ODIN_OS + +/* + A `string` indicating what the target operating system is. +*/ +ODIN_OS_STRING :: ODIN_OS_STRING + +/* + An `enum` value indicating the platform subtarget, chosen using the `-subtarget` switch. + Possible values are: `.Default` `.iOS`, and `.Android`. +*/ +ODIN_PLATFORM_SUBTARGET :: ODIN_PLATFORM_SUBTARGET + +/* + A `string` representing the path of the folder containing the Odin compiler, + relative to which we expect to find the `base` and `core` package collections. +*/ +ODIN_ROOT :: ODIN_ROOT + +/* + A `bit_set` indicating the sanitizer flags set using the `-sanitize` command line switch. + Supported flags are `.Address`, `.Memory`, and `.Thread`. +*/ +ODIN_SANITIZER_FLAGS :: ODIN_SANITIZER_FLAGS + +/* + `true` if the code is being compiled via an invocation of `odin test`. +*/ +ODIN_TEST :: ODIN_TEST + +/* + `true` if built using the experimental Tilde backend. +*/ +ODIN_TILDE :: ODIN_TILDE + +/* + `true` if the `-use-separate-modules` command line switch is passed, + which builds each package into its own object file, and then links them together, instead of performing a unity build. +*/ +ODIN_USE_SEPARATE_MODULES :: ODIN_USE_SEPARATE_MODULES + +/* + `true` if Valgrind integration is supported on the target. +*/ +ODIN_VALGRIND_SUPPORT :: ODIN_VALGRIND_SUPPORT + +/* + A `string` which identifies the compiler being used. The official compiler sets this to `"odin"`. +*/ +ODIN_VENDOR :: ODIN_VENDOR + +/* + A `string` containing the version of the Odin compiler, typically in the format `dev-YYYY-MM`. +*/ +ODIN_VERSION :: ODIN_VERSION + +/* + A `string` containing the Git hash part of the Odin version. + Empty if `.git` could not be detected at the time the compiler was built. +*/ +ODIN_VERSION_HASH :: ODIN_VERSION_HASH + +/* + An `enum` set by the `-subsystem` flag, specifying which Windows subsystem the PE file was created for. + Possible values are: + `.Unknown` - Default and only value on non-Windows platforms + `.Console` - Default on Windows + `.Windows` - Can be used by graphical applications so Windows doesn't open an empty console + + There are some other possible values for e.g. EFI applications, but only Console and Windows are supported. + + See also: https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header64 +*/ +ODIN_WINDOWS_SUBSYSTEM :: ODIN_WINDOWS_SUBSYSTEM + +/* + An `string` set by the `-subsystem` flag, specifying which Windows subsystem the PE file was created for. + Possible values are: + "UNKNOWN" - Default and only value on non-Windows platforms + "CONSOLE" - Default on Windows + "WINDOWS" - Can be used by graphical applications so Windows doesn't open an empty console + + There are some other possible values for e.g. EFI applications, but only Console and Windows are supported. + + See also: https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header64 +*/ +ODIN_WINDOWS_SUBSYSTEM_STRING :: ODIN_WINDOWS_SUBSYSTEM_STRING + +/* + `true` if LLVM supports the f16 type. +*/ +__ODIN_LLVM_F16_SUPPORTED :: __ODIN_LLVM_F16_SUPPORTED + + byte :: u8 // alias @@ -131,3 +344,6 @@ soa_zip :: proc(slices: ...) -> #soa[]Struct --- soa_unzip :: proc(value: $S/#soa[]$E) -> (slices: ...) --- unreachable :: proc() -> ! --- + +// Where T is a string, slice, dynamic array, or pointer to an array type +raw_data :: proc(t: $T) -> rawptr \ No newline at end of file diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 00594c1b4..9d1685cd7 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,38 +116,23 @@ 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) @@ -114,20 +140,8 @@ gb_global String target_arch_names[TargetArch_COUNT] = { #else #include #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, @@ -138,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 @@ -393,17 +394,17 @@ String linker_choices[Linker_COUNT] = { // 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; @@ -1788,8 +1789,8 @@ 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) { diff --git a/src/checker.cpp b/src/checker.cpp index aaa815365..9bc02cd87 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1078,11 +1078,30 @@ 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_BUILD_PROJECT_NAME", bc->ODIN_BUILD_PROJECT_NAME); - add_global_string_constant("ODIN_WINDOWS_SUBSYSTEM", bc->ODIN_WINDOWS_SUBSYSTEM); + 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); + + { + GlobalEnumValue values[Windows_Subsystem_COUNT] = { + {"Unknown", Windows_Subsystem_UNKNOWN}, + {"Boot_Application", Windows_Subsystem_BOOT_APPLICATION}, + {"Console", Windows_Subsystem_CONSOLE}, + {"EFI_Application", Windows_Subsystem_EFI_APPLICATION}, + {"EFI_Boot_Service_Driver", Windows_Subsystem_EFI_BOOT_SERVICE_DRIVER}, + {"EFI_Rom", Windows_Subsystem_EFI_ROM}, + {"EFI_Runtime_Driver", Windows_Subsystem_EFI_RUNTIME_DRIVER}, + {"Native", Windows_Subsystem_NATIVE}, + {"Posix", Windows_Subsystem_POSIX}, + {"Windows", Windows_Subsystem_WINDOWS}, + {"Windows_CE", Windows_Subsystem_WINDOWSCE}, + }; + + auto fields = add_global_enum_type(str_lit("Odin_Windows_Subsystem_Type"), values, gb_count_of(values)); + add_global_enum_constant(fields, "ODIN_WINDOWS_SUBSYSTEM", bc->ODIN_WINDOWS_SUBSYSTEM); + add_global_string_constant("ODIN_WINDOWS_SUBSYSTEM_STRING", windows_subsystem_names[bc->ODIN_WINDOWS_SUBSYSTEM]); + } { GlobalEnumValue values[TargetOs_COUNT] = { @@ -1102,7 +1121,7 @@ gb_internal void init_universal(void) { }; auto fields = add_global_enum_type(str_lit("Odin_OS_Type"), values, gb_count_of(values)); - add_global_enum_constant(fields, "ODIN_OS", bc->metrics.os); + add_global_enum_constant(fields, "ODIN_OS", bc->metrics.os); add_global_string_constant("ODIN_OS_STRING", target_os_names[bc->metrics.os]); } diff --git a/src/linker.cpp b/src/linker.cpp index 447d66d0a..71aee3a3b 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -321,7 +321,7 @@ try_cross_linking:; "", LIT(build_context.ODIN_ROOT), object_files, LIT(output_filename), link_settings, - LIT(build_context.ODIN_WINDOWS_SUBSYSTEM), + LIT(windows_subsystem_names[build_context.ODIN_WINDOWS_SUBSYSTEM]), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags), lib_str @@ -341,7 +341,7 @@ try_cross_linking:; "", LIT(build_context.ODIN_ROOT), object_files, LIT(output_filename), link_settings, - LIT(build_context.ODIN_WINDOWS_SUBSYSTEM), + LIT(windows_subsystem_names[build_context.ODIN_WINDOWS_SUBSYSTEM]), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags), lib_str @@ -404,7 +404,7 @@ try_cross_linking:; "", LIT(vs_exe_path), LIT(linker_name), object_files, LIT(res_path), LIT(output_filename), link_settings, - LIT(build_context.ODIN_WINDOWS_SUBSYSTEM), + LIT(windows_subsystem_names[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 1ffdd0dba..dfc2f3213 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1627,9 +1627,9 @@ gb_internal bool parse_build_flags(Array args) { GB_ASSERT(value.kind == ExactValue_String); String subsystem = value.value_string; bool subsystem_found = false; - for (int i = 0; i < Windows_Subsystem_COUNT; i++) { + for (int i = 1; i < Windows_Subsystem_COUNT; i++) { if (str_eq_ignore_case(subsystem, windows_subsystem_names[i])) { - build_context.ODIN_WINDOWS_SUBSYSTEM = windows_subsystem_names[i]; + build_context.ODIN_WINDOWS_SUBSYSTEM = Windows_Subsystem(i); subsystem_found = true; break; } @@ -1638,7 +1638,7 @@ gb_internal bool parse_build_flags(Array args) { // 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]; + build_context.ODIN_WINDOWS_SUBSYSTEM = Windows_Subsystem_WINDOWS; subsystem_found = true; break; } @@ -1646,8 +1646,8 @@ gb_internal bool parse_build_flags(Array args) { 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) { + for (int i = 1; i < Windows_Subsystem_COUNT; i++) { + if (i > 1) { gb_printf_err(", "); } gb_printf_err("%.*s", LIT(windows_subsystem_names[i])); -- cgit v1.2.3 From 0d0f311df1e31102f4138c1a28110f86dcf60fca Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Thu, 29 May 2025 19:02:46 +0200 Subject: Always provide /PDB option to linker if generating debug info. radlink by default places the .PDB file in the working directory, even if /OUT says to place it elsewhere, unlike link.exe, which places it next to the executable by default. So, if compiling using -debug, we generate a PDB path even if -pdb-name wasn't used to override it. --- src/build_settings.cpp | 16 ++++++++++++---- src/linker.cpp | 2 +- 2 files changed, 13 insertions(+), 5 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 9d1685cd7..e46670528 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -2066,10 +2066,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(); @@ -2268,6 +2264,18 @@ gb_internal bool init_build_paths(String init_filename) { bc->build_paths[BuildPath_Output] = output_path; } + if (build_context.metrics.os == TargetOs_windows && build_context.ODIN_DEBUG) { + if (bc->pdb_filepath.len > 0) { + bc->build_paths[BuildPath_PDB] = path_from_string(ha, bc->pdb_filepath); + } else { + Path pdb_path; + pdb_path.basename = copy_string(ha, bc->build_paths[BuildPath_Output].basename); + pdb_path.name = copy_string(ha, bc->build_paths[BuildPath_Output].name); + pdb_path.ext = copy_string(ha, STR_LIT("pdb")); + bc->build_paths[BuildPath_PDB] = pdb_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) { diff --git a/src/linker.cpp b/src/linker.cpp index 71aee3a3b..f10e47ec3 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -281,7 +281,7 @@ try_cross_linking:; link_settings = gb_string_append_fmt(link_settings, " /ENTRY:mainCRTStartup"); } - if (build_context.pdb_filepath != "") { + if (build_context.build_paths[BuildPath_PDB].name != "") { String pdb_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_PDB]); link_settings = gb_string_append_fmt(link_settings, " /PDB:\"%.*s\"", LIT(pdb_path)); } -- cgit v1.2.3 From 73866b6b3d1c1e8d7f4f57ee966efbafbc0e5185 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Fri, 30 May 2025 07:31:03 -0400 Subject: Remove trailing whitespace --- src/build_settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index e46670528..5e99f6a7a 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -2181,7 +2181,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 { -- cgit v1.2.3 From 598c1a1f1987ebaea4833b23d3c48f842c71f589 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Fri, 30 May 2025 07:55:40 -0400 Subject: Allow overriding object extension in `-build-mode:obj` --- src/build_settings.cpp | 42 +++++++++++++++++++++++++++++++++++------- src/llvm_backend.cpp | 35 ++++++----------------------------- 2 files changed, 41 insertions(+), 36 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 5e99f6a7a..e0ca03a61 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -2023,6 +2023,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) { @@ -2155,13 +2188,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"); diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 801da52a3..3cf77256b 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -2527,38 +2527,15 @@ gb_internal String lb_filepath_obj_for_module(lbModule *m) { String ext = {}; if (build_context.build_mode == BuildMode_Assembly) { - ext = STR_LIT(".S"); + ext = STR_LIT("S"); + } else if (build_context.build_mode == BuildMode_Object) { + // Allow a user override for the object extension. + ext = build_context.build_paths[BuildPath_Output].ext; } else { - if (is_arch_wasm()) { - ext = STR_LIT(".wasm.o"); - } else { - switch (build_context.metrics.os) { - case TargetOs_windows: - ext = STR_LIT(".obj"); - break; - default: - case TargetOs_darwin: - case TargetOs_linux: - case TargetOs_essence: - ext = STR_LIT(".o"); - break; - - case TargetOs_freestanding: - switch (build_context.metrics.abi) { - default: - case TargetABI_Default: - case TargetABI_SysV: - ext = STR_LIT(".o"); - break; - case TargetABI_Win64: - ext = STR_LIT(".obj"); - break; - } - break; - } - } + ext = infer_object_extension_from_build_context(); } + path = gb_string_append_length(path, ".", 1); path = gb_string_append_length(path, ext.text, ext.len); return make_string(cast(u8 *)path, gb_string_length(path)); -- cgit v1.2.3 From 405bf7cd5549edd1f718fce2b53f845dde6fe690 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Sun, 1 Jun 2025 15:59:38 +0200 Subject: Also clean up .dSym on Darwin --- src/build_settings.cpp | 28 ++++++++++++++++++---------- src/linker.cpp | 6 +++--- src/main.cpp | 12 +++++++----- 3 files changed, 28 insertions(+), 18 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index e0ca03a61..2c444f4eb 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -288,7 +288,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, }; @@ -2292,15 +2292,23 @@ gb_internal bool init_build_paths(String init_filename) { bc->build_paths[BuildPath_Output] = output_path; } - if (build_context.metrics.os == TargetOs_windows && build_context.ODIN_DEBUG) { - if (bc->pdb_filepath.len > 0) { - bc->build_paths[BuildPath_PDB] = path_from_string(ha, bc->pdb_filepath); - } else { - Path pdb_path; - pdb_path.basename = copy_string(ha, bc->build_paths[BuildPath_Output].basename); - pdb_path.name = copy_string(ha, bc->build_paths[BuildPath_Output].name); - pdb_path.ext = copy_string(ha, STR_LIT("pdb")); - bc->build_paths[BuildPath_PDB] = pdb_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; } } diff --git a/src/linker.cpp b/src/linker.cpp index f10e47ec3..2210c1306 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -281,9 +281,9 @@ try_cross_linking:; link_settings = gb_string_append_fmt(link_settings, " /ENTRY:mainCRTStartup"); } - if (build_context.build_paths[BuildPath_PDB].name != "") { - String pdb_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_PDB]); - link_settings = gb_string_append_fmt(link_settings, " /PDB:\"%.*s\"", LIT(pdb_path)); + if (build_context.build_paths[BuildPath_Symbols].name != "") { + String symbol_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Symbols]); + link_settings = gb_string_append_fmt(link_settings, " /PDB:\"%.*s\"", LIT(symbol_path)); } if (build_context.build_mode != BuildMode_StaticLibrary) { diff --git a/src/main.cpp b/src/main.cpp index b0f839509..af321258c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3890,12 +3890,14 @@ end_of_code_gen:; char const *filename = cast(char const *)exe_name.text; gb_file_remove(filename); - if (build_context.metrics.os == TargetOs_windows && build_context.ODIN_DEBUG) { - String pdb_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_PDB]); - defer (gb_free(heap_allocator(), pdb_path.text)); + if (build_context.ODIN_DEBUG) { + if (build_context.metrics.os == TargetOs_windows || build_context.metrics.os == TargetOs_darwin) { + String symbol_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Symbols]); + defer (gb_free(heap_allocator(), symbol_path.text)); - filename = cast(char const *)pdb_path.text; - gb_file_remove(filename); + filename = cast(char const *)symbol_path.text; + gb_file_remove(filename); + } } } } -- cgit v1.2.3 From 805f7ce973db57a9420cf84fb0f55a54c0018284 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Sun, 1 Jun 2025 19:22:51 +0200 Subject: Typo fix --- src/build_settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 2c444f4eb..05709902a 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -2307,7 +2307,7 @@ gb_internal bool init_build_paths(String init_filename) { 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")); + symbol_path.ext = copy_string(ha, STR_LIT("dSYM")); bc->build_paths[BuildPath_Symbols] = symbol_path; } } -- cgit v1.2.3