diff options
| author | Colin Davidson <colrdavidson@gmail.com> | 2025-04-26 18:22:21 -0700 |
|---|---|---|
| committer | Colin Davidson <colrdavidson@gmail.com> | 2025-04-26 18:22:21 -0700 |
| commit | f1fdd1a8b9a53d34b59f8bac86ebba5f35189f28 (patch) | |
| tree | 5d8e0f200c25ae3451f666e7292f9cc9ad3db743 /src/main.cpp | |
| parent | 78d8ed2d391e8def6b303445c82f7d143897c251 (diff) | |
| parent | 7d4c3d23e6156c1b4be1f91e6d18e51a8e9814f0 (diff) | |
Merge branch 'master' into macharena
Diffstat (limited to 'src/main.cpp')
| -rw-r--r-- | src/main.cpp | 166 |
1 files changed, 139 insertions, 27 deletions
diff --git a/src/main.cpp b/src/main.cpp index 8a5339000..b2cfbe018 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 "bundle_command.cpp" #if defined(GB_SYSTEM_WINDOWS) && defined(ODIN_TILDE_BACKEND) #define ALLOW_TILDE 1 @@ -87,13 +88,6 @@ gb_global Timings global_timings = {0}; #include "llvm_backend.cpp" -#if defined(GB_SYSTEM_OSX) - #include <llvm/Config/llvm-config.h> - #if LLVM_VERSION_MAJOR < 11 || (LLVM_VERSION_MAJOR > 14 && LLVM_VERSION_MAJOR < 17) || LLVM_VERSION_MAJOR > 18 - #error LLVM Version 11..=14 or =18 is required => "brew install llvm@14" - #endif -#endif - #include "bug_report.cpp" // NOTE(bill): 'name' is used in debugging and profiling modes @@ -283,6 +277,7 @@ gb_internal void usage(String argv0, String argv1 = {}) { print_usage_line(1, "build Compiles directory of .odin files, as an executable."); print_usage_line(1, " One must contain the program's entry point, all must be in the same package."); print_usage_line(1, "run Same as 'build', but also then runs the newly compiled executable."); + print_usage_line(1, "bundle Bundles a directory in a specific layout for that platform."); print_usage_line(1, "check Parses, and type checks a directory of .odin files."); print_usage_line(1, "strip-semicolon Parses, type checks, and removes unneeded semicolons from the entire program."); print_usage_line(1, "test Builds and runs procedures with the attribute @(test) in the initial package."); @@ -331,6 +326,7 @@ enum BuildFlagKind { BuildFlag_UseRADLink, BuildFlag_Linker, BuildFlag_UseSeparateModules, + BuildFlag_UseSingleModule, BuildFlag_NoThreadedChecker, BuildFlag_ShowDebugMessages, @@ -401,6 +397,7 @@ enum BuildFlagKind { BuildFlag_InternalModulePerFile, BuildFlag_InternalCached, BuildFlag_InternalNoInline, + BuildFlag_InternalByValue, BuildFlag_Tilde, @@ -413,6 +410,10 @@ enum BuildFlagKind { BuildFlag_Subsystem, #endif + BuildFlag_AndroidKeystore, + BuildFlag_AndroidKeystoreAlias, + BuildFlag_AndroidKeystorePassword, + BuildFlag_COUNT, }; @@ -431,12 +432,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<BuildFlag> *build_flags, BuildFlagKind kind, String name, BuildFlagParamKind param_kind, u32 command_support, bool allow_multiple=false) { +gb_internal void add_flag(Array<BuildFlag> *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); } @@ -544,6 +545,7 @@ gb_internal bool parse_build_flags(Array<String> args) { add_flag(&build_flags, BuildFlag_UseRADLink, str_lit("radlink"), BuildFlagParam_None, Command__does_build); add_flag(&build_flags, BuildFlag_Linker, str_lit("linker"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_UseSeparateModules, str_lit("use-separate-modules"), BuildFlagParam_None, Command__does_build); + add_flag(&build_flags, BuildFlag_UseSingleModule, str_lit("use-single-module"), BuildFlagParam_None, Command__does_build); add_flag(&build_flags, BuildFlag_NoThreadedChecker, str_lit("no-threaded-checker"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_ShowDebugMessages, str_lit("show-debug-messages"), BuildFlagParam_None, Command_all); @@ -571,7 +573,7 @@ gb_internal bool parse_build_flags(Array<String> args) { add_flag(&build_flags, BuildFlag_Microarch, str_lit("microarch"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_TargetFeatures, str_lit("target-features"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_StrictTargetFeatures, str_lit("strict-target-features"), BuildFlagParam_None, Command__does_build); - add_flag(&build_flags, BuildFlag_MinimumOSVersion, str_lit("minimum-os-version"), BuildFlagParam_String, Command__does_build); + add_flag(&build_flags, BuildFlag_MinimumOSVersion, str_lit("minimum-os-version"), BuildFlagParam_String, Command__does_build | Command_bundle_android); add_flag(&build_flags, BuildFlag_RelocMode, str_lit("reloc-mode"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_DisableRedZone, str_lit("disable-red-zone"), BuildFlagParam_None, Command__does_build); @@ -612,6 +614,7 @@ gb_internal bool parse_build_flags(Array<String> args) { add_flag(&build_flags, BuildFlag_InternalModulePerFile, str_lit("internal-module-per-file"), BuildFlagParam_None, Command_all); add_flag(&build_flags, BuildFlag_InternalCached, str_lit("internal-cached"), BuildFlagParam_None, Command_all); add_flag(&build_flags, BuildFlag_InternalNoInline, str_lit("internal-no-inline"), BuildFlagParam_None, Command_all); + add_flag(&build_flags, BuildFlag_InternalByValue, str_lit("internal-by-value"), BuildFlagParam_None, Command_all); #if ALLOW_TILDE add_flag(&build_flags, BuildFlag_Tilde, str_lit("tilde"), BuildFlagParam_None, Command__does_build); @@ -627,9 +630,20 @@ gb_internal bool parse_build_flags(Array<String> 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_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); - GB_ASSERT(args.count >= 3); - Array<String> flag_args = array_slice(args, 3, args.count); + + Array<String> flag_args = {}; + + if (build_context.command_kind == Command_bundle_android) { + GB_ASSERT(args.count >= 4); + flag_args = array_slice(args, 4, args.count); + } else { + GB_ASSERT(args.count >= 3); + flag_args = array_slice(args, 3, args.count); + } bool set_flags[BuildFlag_COUNT] = {}; @@ -1108,8 +1122,9 @@ gb_internal bool parse_build_flags(Array<String> args) { String str = value.value_string; bool found = false; - if (selected_target_metrics->metrics->os != TargetOs_darwin) { - gb_printf_err("-subtarget can only be used with darwin based targets at the moment\n"); + if (selected_target_metrics->metrics->os != TargetOs_darwin && + selected_target_metrics->metrics->os != TargetOs_linux ) { + gb_printf_err("-subtarget can only be used with darwin and linux based targets at the moment\n"); bad_flags = true; break; } @@ -1190,7 +1205,7 @@ gb_internal bool parse_build_flags(Array<String> args) { build_context.no_type_assert = true; break; case BuildFlag_NoDynamicLiterals: - build_context.no_dynamic_literals = true; + gb_printf_err("Warning: Use of -no-dynamic-literals is now redundant\n"); break; case BuildFlag_NoCRT: build_context.no_crt = true; @@ -1238,8 +1253,19 @@ gb_internal bool parse_build_flags(Array<String> args) { case BuildFlag_UseSeparateModules: + if (build_context.use_single_module) { + gb_printf_err("-use-separate-modules cannot be used with -use-single-module\n"); + bad_flags = true; + } build_context.use_separate_modules = true; break; + case BuildFlag_UseSingleModule: + if (build_context.use_separate_modules) { + gb_printf_err("-use-single-module cannot be used with -use-separate-modules\n"); + bad_flags = true; + } + build_context.use_single_module = true; + break; case BuildFlag_NoThreadedChecker: build_context.no_threaded_checker = true; break; @@ -1508,6 +1534,9 @@ gb_internal bool parse_build_flags(Array<String> args) { case BuildFlag_InternalNoInline: build_context.internal_no_inline = true; break; + case BuildFlag_InternalByValue: + build_context.internal_by_value = true; + break; case BuildFlag_Tilde: build_context.tilde_backend = true; @@ -1626,6 +1655,20 @@ gb_internal bool parse_build_flags(Array<String> 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_AndroidKeystorePassword: + GB_ASSERT(value.kind == ExactValue_String); + build_context.android_keystore_password = value.value_string; + break; } } @@ -1641,8 +1684,8 @@ gb_internal bool parse_build_flags(Array<String> 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<<i)) { + for (u64 i = 0; i < 64; i++) { + if (found_bf.command_support & (1ull<<i)) { if (count > 0) { gb_printf_err(", "); } @@ -1796,7 +1839,10 @@ gb_internal void check_defines(BuildContext *bc, Checker *c) { if (!found) { ERROR_BLOCK(); warning(nullptr, "given -define:%.*s is unused in the project", LIT(name)); - error_line("\tSuggestion: use the -show-defineables flag for an overview of the possible defines\n"); + + if (!global_ignore_warnings()) { + error_line("\tSuggestion: use the -show-defineables flag for an overview of the possible defines\n"); + } } } } @@ -2115,7 +2161,7 @@ gb_internal void export_dependencies(Checker *c) { for_array(i, files) { AstFile *file = files[i]; gb_fprintf(&f, "\t\t\"%.*s\"", LIT(file->fullpath)); - if (i+1 == files.count) { + if (i+1 < files.count) { gb_fprintf(&f, ","); } gb_fprintf(&f, "\n"); @@ -2128,7 +2174,7 @@ gb_internal void export_dependencies(Checker *c) { for_array(i, load_files) { LoadFileCache *cache = load_files[i]; gb_fprintf(&f, "\t\t\"%.*s\"", LIT(cache->path)); - if (i+1 == load_files.count) { + if (i+1 < load_files.count) { gb_fprintf(&f, ","); } gb_fprintf(&f, "\n"); @@ -2155,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); @@ -2175,13 +2221,19 @@ gb_internal void remove_temp_files(lbGenerator *gen) { } -gb_internal void print_show_help(String const arg0, String const &command, String optional_flag = {}) { +gb_internal void print_show_help(String const arg0, String command, String optional_flag = {}) { + if (command == "help" && optional_flag.len != 0 && optional_flag[0] != '-') { + command = optional_flag; + optional_flag = {}; + } + print_usage_line(0, "%.*s is a tool for managing Odin source code.", LIT(arg0)); print_usage_line(0, "Usage:"); print_usage_line(1, "%.*s %.*s [arguments]", LIT(arg0), LIT(command)); print_usage_line(0, ""); defer (print_usage_line(0, "")); + if (command == "build") { print_usage_line(1, "build Compiles directory of .odin files as an executable."); print_usage_line(2, "One must contain the program's entry point, all must be in the same package."); @@ -2216,6 +2268,10 @@ gb_internal void print_show_help(String const arg0, String const &command, Strin } 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 == "bundle") { + print_usage_line(1, "bundle <platform> Bundles a directory in a specific layout for that platform"); + print_usage_line(2, "Supported platforms:"); + print_usage_line(3, "android"); } bool doc = command == "doc"; @@ -2225,6 +2281,7 @@ gb_internal void print_show_help(String const arg0, String const &command, Strin bool strip_semicolon = command == "strip-semicolon"; bool check_only = command == "check" || strip_semicolon; bool check = run_or_build || check_only; + bool bundle = command == "bundle"; if (command == "help") { doc = true; @@ -2320,6 +2377,10 @@ gb_internal void print_show_help(String const arg0, String const &command, Strin print_usage_line(2, "Sets the default allocator to be the nil_allocator, an allocator which does nothing."); } + if (print_flag("-default-to-panic-allocator")) { + print_usage_line(2, "Sets the default allocator to be the panic_allocator, an allocator which calls panic() on any allocation attempt."); + } + if (print_flag("-define:<name>=<value>")) { print_usage_line(2, "Defines a scalar boolean, integer or string as global constant."); print_usage_line(2, "Example: -define:SPAM=123"); @@ -2488,13 +2549,15 @@ gb_internal void print_show_help(String const arg0, String const &command, Strin } } - if (run_or_build) { + if (run_or_build || bundle) { if (print_flag("-minimum-os-version:<string>")) { 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."); } + } + if (run_or_build) { if (print_flag("-no-bounds-check")) { print_usage_line(2, "Disables bounds checking program wide."); } @@ -2699,8 +2762,12 @@ gb_internal void print_show_help(String const arg0, String const &command, Strin if (run_or_build) { if (print_flag("-use-separate-modules")) { print_usage_line(2, "The backend generates multiple build units which are then linked together."); - print_usage_line(2, "Normally, a single build unit is generated for a standard project."); - print_usage_line(2, "This is the default behaviour on Windows for '-o:none' and '-o:minimal' builds."); + print_usage_line(2, "This is the default behaviour for '-o:none' and '-o:minimal' builds."); + print_usage_line(2, "Normally, a single build unit is generated for a standard project for '-o:speed' or '-o:size'."); + } + if (print_flag("-use-single-module")) { + print_usage_line(2, "The backend generates only a single build unit."); + print_usage_line(2, "This is the default behaviour for '-o:speed' or '-o:size'."); } } @@ -2781,6 +2848,25 @@ gb_internal void print_show_help(String const arg0, String const &command, Strin print_usage_line(2, "Treats warning messages as error messages."); } } + + if (bundle) { + print_usage_line(0, ""); + print_usage_line(1, "Android-specific flags"); + print_usage_line(0, ""); + if (print_flag("-android-keystore:<string>")) { + print_usage_line(2, "Specifies the keystore file to use to sign the apk."); + } + + if (print_flag("-android-keystore-alias:<string>")) { + print_usage_line(2, "Specifies the key alias to use when signing the apk"); + print_usage_line(2, "Can be omitted if the keystore only contains one key"); + } + + if (print_flag("-android-keystore-password:<string>")) { + print_usage_line(2, "Sets the password to use to unlock the keystore"); + print_usage_line(2, "If this is omitted, the terminal will prompt you to provide it."); + } + } } gb_internal void print_show_unused(Checker *c) { @@ -3271,6 +3357,19 @@ int main(int arg_count, char const **arg_ptr) { print_show_help(args[0], args[1], args[2]); return 0; } + } else if (command == "bundle") { + if (args.count < 4) { + usage(args[0]); + return 1; + } + if (args[2] == "android") { + build_context.command_kind = Command_bundle_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; @@ -3305,10 +3404,14 @@ 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 <filename.odin> -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)); } @@ -3342,6 +3445,10 @@ int main(int arg_count, char const **arg_ptr) { return 0; } + if (command == "bundle") { + return bundle(init_filename); + } + // 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"), @@ -3558,10 +3665,15 @@ int main(int arg_count, char const **arg_ptr) { } if (build_context.generate_docs) { + MAIN_TIME_SECTION("generate documentation"); if (global_error_collector.count != 0) { return 1; } generate_documentation(checker); + + if (build_context.show_timings) { + show_timings(checker, &global_timings); + } return 0; } |