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