program_args: []string; args_help: bool; args_compiler_silent: bool; args_program_run: bool; args_build_release: bool; args_memory_debug: bool; args_ua_alloc: bool; args_hot_reload: bool; args_rebuild_editor: bool; Release_Kind :: enum_flags { DEBUG; SHARED; RELEASE; } Program :: struct { name: string; workspace: Workspace; } build :: () { set_build_options_dc(.{ do_output = false }); args := get_build_options().compile_time_command_line; // args args_help = array_find(args, "help"); args_compiler_silent = array_find(args, "silent"); args_program_run = array_find(args, "run"); args_build_release = array_find(args, "release"); args_memory_debug = array_find(args, "memory"); args_ua_alloc = array_find(args, "ua"); args_hot_reload = array_find(args, "hotreload"); args_rebuild_editor = array_find(args, "rebuild"); // program args program_args := program_args_collect(args); /** Workspaces */ workspace_host := create_workspace("host"); workspace_editor := create_workspace("editor"); if args_help { args_help_print(); return; } make_directory_if_it_does_not_exist("bin"); make_directory_if_it_does_not_exist("bin/debug"); make_directory_if_it_does_not_exist("bin/release"); make_directory_if_it_does_not_exist("bin/debug_hot"); make_directory_if_it_does_not_exist("bin/release_hot"); release_as: Release_Kind = ifx args_build_release then .RELEASE else .DEBUG; if args_hot_reload then release_as |= .SHARED; should_run_program := args_program_run ^ (args_hot_reload & args_program_run); workspace_setup(workspace_editor, run=should_run_program, release_as, #code { add_build_string(tprint("IS_HOT_RELOAD :: %;", args_hot_reload), workspace); add_build_file(tprint("%src/main.jai", #filepath), workspace); }); if args_hot_reload && !args_rebuild_editor { workspace_setup(workspace_host, run=true, .DEBUG, #code { add_build_string( tprint("FP_EDITOR_SO :: \"%\";", "bin/debug_hot/editor.so"), workspace ); add_build_file(tprint("%src/host.jai", #filepath), workspace); }); } } build_debug :: (w: Workspace, target_options: *Build_Options) { log("Choosing debug options..."); target_options.backend =.X64; target_options.output_path = "bin/debug"; set_optimization(target_options, Optimization_Type.DEBUG, true); set_build_options(target_options.*, w); } build_release :: (w: Workspace, target_options: *Build_Options) { log("Choosing release options..."); target_options.backend = .LLVM; target_options.output_path = "bin/release"; set_optimization(target_options, Optimization_Type.VERY_OPTIMIZED); set_build_options(target_options.*, w); } build_dynamic_debug :: (w: Workspace, target_options: *Build_Options) { log("Choosing dyn debug options ..."); target_options.backend = .X64; target_options.output_type = .DYNAMIC_LIBRARY; target_options.output_path = "bin/debug_hot"; set_optimization(target_options, Optimization_Type.DEBUG, true); set_build_options(target_options.*, w); } build_dynamic_release :: (w: Workspace, target_options: *Build_Options) { log("Choosing dyn release options ..."); target_options.backend = .LLVM; target_options.output_type = .DYNAMIC_LIBRARY; target_options.output_path = "bin/release_hot"; set_optimization(target_options, Optimization_Type.VERY_OPTIMIZED); set_build_options(target_options.*, w); } args_help_print :: () { help_message := #string _END_ Usage: jai build.jai - [OPTIONS] :: [PROGRAM ARGS] Options: help Prints this help menu. silent Disables compiler/linker statistics. run Runs your program afterwards. release Builds with release options. If omitted, it builds a debug build. memory Enables the memory leak detector. Passing Args to your Program: If you want to supply args to your program, pass it like that: `jai build.jai - run :: my_arg1 foo bar abc ABC` Everything after the `::` get's forwarded to your program. _END_; log(help_message); } program_args_collect :: (args: []string, divider: string = "::") -> [..]string { buf: [..]string; success, match := array_find(args, divider); if success for i: match+1..args.count-1 array_add(*buf, args[i]); return buf; } message_loop :: () -> success: bool { while true { message := compiler_wait_for_message(); if !message break; if message.kind == { case .COMPLETE; message_complete := cast(*Message_Complete) message; return message_complete.error_code == 0; } } return false; } create_workspace :: (name: string) -> Program #expand { w := compiler_create_workspace(name); if !w{ log("Workspace creation failed: %", name); `return; } return { name, w }; } workspace_setup :: (using program: Program, run: bool, release_kind: Release_Kind, $intercept: Code) #expand { insert_constant :: (label: string, any: Any) #expand { add_build_string(tprint("% :: %;", label, any), `workspace); } print("The workspace w is %\n", workspace); target_options := get_build_options(workspace); target_options.output_executable_name = name; if args_compiler_silent target_options.text_output_flags = 0; if release_kind == { case .RELEASE; build_release(workspace, *target_options); case (.SHARED | .RELEASE); build_dynamic_release(workspace, *target_options); case (.SHARED | .DEBUG); build_dynamic_debug(workspace, *target_options); case .DEBUG; build_debug(workspace, *target_options); case; compiler_report("Unkown release kind"); } compiler_begin_intercept(workspace); #insert,scope() intercept; insert_constant("IS_DEVELOPER", !args_build_release); insert_constant("IS_UA_ALLOCATOR", args_ua_alloc); insert_constant("MEMORY_DEBUGGER_ENABLED", args_memory_debug); compiler_response := message_loop(); compiler_end_intercept(workspace); if !compiler_response { log("Compiler response failed."); return; } if run then run_build_result_of_workspace(workspace, program_args); } main :: () {} #run build(); #import "Basic"; #import "Compiler"; #import "File"; #import "String"; #import "Autorun"; #import "Print_Vars";