Author:ptrace Comitter:ptrace Date:2025-11-04 12:38:08 UTC

Added support for multiple build.jai templates

diff --git a/README.md b/README.md index 1ff3b29..d0f1f41 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,31 @@ Smol program that creates some basic files and folders for Jai development. Adapt it to your own needs.   ## Build ```plain $ jai -version Version: beta 0.2.018, built on 11 October 2025. ``` ```plain $ jai jinit.jai ``` ## Usage - `jai jinit.jai` - add the binary to your $PATH or symlink it where appropriate - `$ jinit -help` for available args ## Templates You can create multiple `build.jai` templates and invoke them with args.   For example, there's a template inside `jinit.jai` called `CONTENT_BUILD_VARIANT_MINIMAL`,  it contains a very small `build.jai` script.   You can create it with `jinit -v1`.   You can also add own templates: - create a new multiline string that contains your build template - inside the struct `Arguments`, add a new argument - inside the proc `create_files()`, add it to the `if args` construct - optionally, define a default template by adapting the constant `DEFAULT_CONTENT_BUILD_FILE` diff --git a/jinit.jai b/jinit.jai index e26e156..ecd1c30 100755 --- a/jinit.jai +++ b/jinit.jai @@ -16,6 +16,11 @@ OTHER_EMPTY_FILES :: string.[     "README.md", ]; // You can choose between multiple template via CLI args. // But you can also set a default template here. DEFAULT_CONTENT_BUILD_FILE :: CONTENT_BUILD_VARIANT_MINIMAL; CONTENT_GIT_IGNORE :: #string END # Jai .build @@ -23,47 +28,15 @@ bin *.codex END; CONTENT_MAIN_JAI :: #string END #import "Basic"; main :: () {     print("Hello, Sailor!\n"); } END; CONTENT_BUILD_JAI :: #string END #import "Basic"; #import "Compiler"; #import "File"; build :: () {     w := compiler_create_workspace();     if !w {         print("Workspace creation failed.\n");         return;     }     print("The workspace w is %\n", w);     make_directory_if_it_does_not_exist("bin");     target_options := get_build_options(w);     target_options.output_executable_name = "program";     target_options.output_path = "bin";     //import_path: [..] string;     //array_add(*import_path, ..target_options.import_path);     //array_add(*import_path, "modules");     //target_options.import_path = import_path;     set_build_options_dc(.{do_output = false});     set_build_options(target_options, w);     add_build_file(tprint("%src/main.jai", #filepath), w); } main :: () {} #run build(); END; @@ -80,8 +53,8 @@ create_git_project :: (root_fp: string, args: Arguments) {     );     if process_result.exit_code != 0 {         if error_str  print("Error: %\n", error_str);         if output_str print("Error: %\n", output_str);         if error_str  log("Error: %", error_str);         if output_str log("Error: %", output_str);         exit(1);     } } @@ -89,7 +62,7 @@ create_git_project :: (root_fp: string, args: Arguments) { create_directories :: (root_fp: string) {     for FP_SRC_DIR {         if String.starts_with(it, "/") {             print("Are you sure you want to create it at the root dir? Input: %\n", it);             log("Are you sure you want to create it at the root dir? Input: %", it);             exit(1);         }         File.make_directory_if_it_does_not_exist(tprint("%/%", root_fp, it)); @@ -97,9 +70,12 @@ create_directories :: (root_fp: string) { } create_file :: (fp: string, content: string = "") {     if FileUtils.file_exists(fp) return;     if FileUtils.file_exists(fp) {         log("[Info]: The file '%' already exists.", fp);         return;     }     if !File.write_entire_file(fp, content) {         print("Cannot create or write into file: '%'\n", fp);         log("Cannot create or write into file: %", fp);         exit(1);     } } @@ -108,8 +84,17 @@ create_files :: (root_fp: string, args: Arguments) {     fp_entrypoint := tprint("%/%", root_fp, JAI_ENTRYPOINT);     fp_jai_build := tprint("%/%", root_fp, JAI_BUILD);     fp_gitignore := tprint("%/%", root_fp, GIT_IGNORE);     content_build_file := DEFAULT_CONTENT_BUILD_FILE;     if args.v1 {         content_build_file = CONTENT_BUILD_VARIANT_MINIMAL;     } else if args.v2 {         content_build_file = CONTENT_BUILD_VARIANT_WITH_ARGS;     }     create_file(fp_entrypoint, CONTENT_MAIN_JAI);     create_file(fp_jai_build, CONTENT_BUILD_JAI);     create_file(fp_jai_build, content_build_file);     if !args.g {         create_file(fp_gitignore, CONTENT_GIT_IGNORE); @@ -120,8 +105,11 @@ create_files :: (root_fp: string, args: Arguments) {     } } Arguments :: struct {     g: bool; @"?If provided, no Git repository and .gitignore file will be created."     g: bool; @"?If provided, no Git repository and .gitignore file will be created"     v1: bool; @"?Creates a minimal build.jai script"     v2: bool; @"?a build.jai script with more features (Args support, release builds, ...)" } @@ -129,17 +117,177 @@ main :: () {     success, args, is_set := Cli.parse_arguments(Arguments);     if !success {         log("[Error]: Cannot parse arguments");         exit(1);     }     current_path := get_working_directory();     if !current_path {         print("Cannot resolve root path\n");         log("Cannot resolve project path");         exit(1);     }     create_directories(current_path);     create_files(current_path, args);     create_git_project(current_path, args);     print("[Jai Init]: Done\n");     log("[Jai Init]: Done"); } // -------------------------------------- // Build Templates // --------------- CONTENT_BUILD_VARIANT_MINIMAL :: #string _JINIT_END_ #import "Basic"; #import "Compiler"; #import "File"; build :: () {     w := compiler_create_workspace();     if !w {         print("Workspace creation failed.\n");         return;     }     print("The workspace w is %\n", w);     make_directory_if_it_does_not_exist("bin");     target_options := get_build_options(w);     target_options.output_executable_name = "program";     target_options.output_path = "bin";     //import_path: [..] string;     //array_add(*import_path, ..target_options.import_path);     //array_add(*import_path, "modules");     //target_options.import_path = import_path;     set_build_options_dc(.{do_output = false});     set_build_options(target_options, w);     add_build_file(tprint("%src/main.jai", #filepath), w); } main :: () {} #run build(); _JINIT_END_; CONTENT_BUILD_VARIANT_WITH_ARGS :: #string _JINIT_END_ #import "Basic"; #import "Compiler"; #import "File"; #import "Autorun"; build :: () {     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");     // -----------------------------------------     w := compiler_create_workspace();     if !w {         log("Workspace creation failed.");         return;     }     set_build_options_dc(.{ do_output = false });     if args_help {         args_help_print();         return;     }     print("The workspace w is %\n", w);     make_directory_if_it_does_not_exist("bin");     target_options := get_build_options(w);     target_options.output_executable_name = "program";     target_options.output_path = "bin";     if args_compiler_silent  target_options.text_output_flags = 0;     if args_build_release {         build_release(w, *target_options);     } else {         build_debug(w, *target_options);     }     compiler_begin_intercept(w);     add_build_file(tprint("%src/main.jai", #filepath), w);     jinit_compiler_response := jinit_compiler_intercept();     compiler_end_intercept(w);     if !jinit_compiler_response {         log("Compiler response failed.");         return;     }     if args_program_run  run_build_result(w); } // adapted from: https://github.com/Ivo-Balbaert/The_Way_to_Jai/blob/main/book/30B_Manipulating_the_build_process.md build_debug :: (w: Workspace, target_options: *Build_Options) {     log("Choosing debug options...");     target_options.backend =.X64;     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;     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 - [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. _END_;     log(help_message); } jinit_compiler_intercept :: () -> 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; } main :: () {} #run build(); _JINIT_END_