Build SystemΒΆ

Example of more complex build system pipeline with handling of compilation command line options. Use blc -b [arguments] to start building.

$ blc -b -h
Compile assembly: out [BUILD]
Options:
    -h, --help    Print this help.
    -r, --release Release build.
    -c, --clean   Cleanup build artifacts and exit.

File main.bl representing project source code:

main :: fn () s32 {
    print("Hello world!\n");
    return 0;
}

File build.bl representing build pipeline setup:

#import "std/arg_parser"
#import "std/fs"

// Build output directory (where executable will be produced)
BIN_DIR :: "bin";

// Mandatory build entry function.
build :: fn () #build_entry {
    args: Args;
    // Parse all command line arguments.
    if !handle_args(&args) { return; }
    // When user requested help, just do nothing.
    if args.help { return; }
    // User requested cleanup operation.
    if args.clean {
        print("Cleanup '%'.\n", BIN_DIR);
        // Basically remove 'bin' directory.
        fs_dir_remove_all(BIN_DIR);
        return;
    }

    // Create new executable 'run'.
    exe :: add_executable("run");
    // Add 'main.bl' file into executable.
    add_unit(exe, "main.bl");
    // Set directory where all desired modules will be stored.
    set_module_dir(exe, "modules", ModuleImportPolicy.BundleLatest);
    // Set binary output directory.
    set_output_dir(exe, BIN_DIR);
    // Require all runtime dependencies to be copied into build
    // directory.
    set_copy_deps(exe, true);

    // Set release mode if required by user.
    if args.release {
        set_build_mode(exe, BuildMode.ReleaseFast);
    }

    // Print some logs.
    print("Out dir:       %\n", get_output_dir(exe));
    print("Module dir:    %\n", get_module_dir(exe));
    print("Module policy: %\n", get_module_import_policy(exe));
}

Args :: struct #base ArgCtx {
    release: bool;
    clean: bool;
}

// Handle command line arguments.
handle_args :: fn (args: *Args) bool {
    arg_parser :: arg_parser_new();
    defer arg_parser_delete(arg_parser);

    // Add release option.
    arg_parser_add(
        arg_parser,
        "-r",
        "--release",
        "Release build.",
        &fn (parser: ArgParser, args: []string, ctx: *ArgCtx) s32 {
            a: *Args = auto ctx;
            a.release = true;
            return 1;
        });

    // Add cleanup option.
    arg_parser_add(
        arg_parser,
        "-c",
        "--clean",
        "Cleanup build artifacts and exit.",
        &fn (parser: ArgParser, args: []string, ctx: *ArgCtx) s32 {
            a: *Args = auto ctx;
            a.clean = true;
            return 1;
        });

    // Start parsing of 'command_line_arguments'.
    state :: arg_parser_run(arg_parser, command_line_arguments, args);
    if !is_ok(state) {
        print_err("%", state);
        arg_parser_print_help(arg_parser);
        return false;
    }
    return true;
}