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 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) (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 -- 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