Build System

#load "build/build.bl"

Compiler-integrated build pipeline. The build pipeline can be used to manage the entire project compilation process directly in BL. All you need is to create a build file called build.bl.

Example of a minimal build.bl:

main :: fn () s32 {
    // create a new executable target
    exe :: add_executable("MyProgram");

    // add 'main.bl' file into the target 'exe'
    add_unit(exe, "main.bl");

    // start compilation
    compile(exe);
    return 0;
}

Start the build pipeline using your build.bl file:

$ blc -build

The compiler will automatically use the build.bl file as a build script and execute the main function at compile-time. The build/build.bl file containing the compiler API for build pipeline manipulation is loaded implicitly.

Warning: The Build API is available only at compile-time.

Basics

Create a new executable target

A target represents a single build target consisting of build Units, where each Unit represents one source file required for compilation. It is essentially a target compiled into an executable or binary file. Use the add_executable function to specify your target. Several options related to the target are described later in this documentation.

exe :: add_executable("MyProgram");

Add a file to a target

Use the add_unit function to add source files to the target. There is no need to add all files you want to use; the general load and import mechanisms will handle that automatically. Only main or entry-point files must be included explicitly.

add_unit(exe, "main.bl");

Specify the output directory

The output directory is the directory where all compiler-produced files will be written (for example, native executables). Use the set_output_dir function to specify this directory. By default, the current directory is used.

set_output_dir(exe, "bin");

Compile the target

compile(exe);

Command-line arguments

All arguments passed after the -build compiler flag are automatically forwarded to the command_line_arguments global variable. This allows customization of the build command by adding project-specific build flags. See the extra/argparse module.

BuilderOptions

BuilderOptions :: struct {
    verbose: bool;
    no_color: bool;
    silent: bool;
    no_jobs: bool;
    no_warning: bool;
    full_path_reports: bool;
    no_usage_check: bool;
    stats: bool;
    enable_experimental_targets: bool;
    do_cleanup_when_done: bool;
    error_limit: s32;
    legacy_colors: bool;
    warnings_as_errors: bool;
    _doc_out_dir: *C.char;
}

Global builder options.

Members

File: build.bl

get_builder_options

get_builder_options :: fn () BuilderOptions

Returns copy of current builder options. These are by default initializad from command line arguments passed to the compiler.

File: build.bl

set_builder_options

set_builder_options :: fn (opt: BuilderOptions) 

Overrides current builder options previously set from the command line or by calling this function.

File: build.bl

Target

Target :: struct {
    kind: TargetKind;
    build_mode: BuildMode;
    debug_info_kind: DebugInfo;
    register_split: bool;
    verify_llvm: bool;
    run_tests: bool;
    tests_minimal_output: bool;
    no_api: bool;
    copy_dependencies: bool;
    run: bool;
    print_tokens: bool;
    print_ast: bool;
    print_scopes: bool;
    print_scopes_mode: ScopeDumpMode;
    emit_llvm: bool;
    emit_asm: bool;
    emit_mir: bool;
    no_bin: bool;
    no_llvm: bool;
    no_analyze: bool;
    x64: bool;
    assert_mode: AssertMode;
    syntax_only: bool;
    vmdbg_enabled: bool;
    vmdbg_break_on: s32;
    enable_experimental_targets: bool;
    triple: TargetTriple;
    sanitize_address: bool;
}

Target is representation of whole program workspace, it's a consist of Units, every unit represents one source file.

Members

File: build.bl

ScopeDumpMode

ScopeDumpMode :: enum {
    PARENTING = 0;
    INJECTION = 1;
}

File: build.bl

TargetKind

TargetKind :: enum {
    EXECUTABLE = 0;
    SHARED_LIBRARY = 1;
}

Specification of compiler output binary kind.

File: build.bl

TargetArch

TargetArch :: enum s32 {
    UNKNOWN = 0;
    X86_64 = 1;
    AARCH64 = 2;
    ARM64 = 3;
}

File: build.bl

TargetVendor

TargetVendor :: enum s32 {
    UNKNOWN = 0;
    PC = 1;
    APPLE = 2;
}

File: build.bl

TargetSystem

TargetSystem :: enum s32 {
    UNKNOWN = 0;
    WINDOWS = 1;
    DARWIN = 2;
    LINUX = 3;
}

File: build.bl

TargetEnvironment

TargetEnvironment :: enum s32 {
    UNKNOWN = 0;
    MSVC = 1;
    GNU = 2;
    MUSL = 3;
}

File: build.bl

TargetTriple

TargetTriple :: struct {
    arch: TargetArch;
    vendor: TargetVendor;
    os: TargetSystem;
    env: TargetEnvironment;
}

File: build.bl

BuildMode

BuildMode :: enum s32 {
    DEBUG = 0;
    RELEASE_FAST = 1;
    RELEASE_SMALL = 2;
    RELEASE_WITH_DEBUG_INFO = 3;
}

Specify the target build mode. Each Target can be compiled with various configuration options. The BuildMode determines which set of compiler options is used.

Variants

File: build.bl

DebugInfo

DebugInfo :: enum s32 {
    DWARF = 0;
    CODE_VIEW = 1;
}

Debug information format.

File: build.bl

AssertMode

AssertMode :: enum s32 {
    DEFAULT = 0;
    ALWAYS_ENABLED = 1;
    ALWAYS_DISABLED = 2;
}

Specification of the assert mode used for a Target.

Variants

File: build.bl

add_executable

add_executable :: fn (name: string_view) *Target

Add a new executable target to the current compilation queue. The newly created target can be compiled explicitly using compile, or compile_all can be used to compile all added targets at once.

Example

main :: fn () s32 {
    exe :: add_executable("MyProgram");
    add_unit(exe, "src/main.bl");

    mode :: get_build_mode(exe);
    switch mode {
        BuildMode.DEBUG {
            set_output_dir(exe, "build/debug");
        }

        BuildMode.RELEASE_SMALL,
        BuildMode.RELEASE_FAST {
            set_output_dir(exe, "build/release");
        }
    }
    compile(exe);
    return 0;
}

File: build.bl

add_library

add_library :: fn (name: string_view) *Target

Add a new shared library target to the current compilation queue.

File: build.bl

add_unit

add_unit :: fn (target: *Target, filepath: string_view) 

Add a new source file to the target. The function does nothing if filepath is already present in the target assembly.

File: build.bl

compile

compile :: fn (target: *Target) Error

Start compilation of the target assembly and return ok or error if compilation fails.

File: build.bl

compile_all

compile_all :: fn () Error

Compile all created targets one by one in the order in which they were created. See also compile.

File: build.bl

add_lib_path

add_lib_path :: fn (target: *Target, path: string_view) 

Add a path for linker library lookup.

File: build.bl

add_bool_constant

add_bool_constant :: fn (target: *Target, name: string_view, value: bool, loc :: #call_location) 

Add a new immutable boolean variable to the global scope of the target assembly.

File: build.bl

link_library :: fn (target: *Target, name: string_view) 

Link a dynamic library. Only the name is required (without extension or prefix). The compiler will look for this library in the working directory, the system PATH, and the linker_lib_path variable specified in the bl.conf file (use blc --where-is-config to get the file location). You can add custom search locations using the add_lib_path function.

The linked library can also be used during compile-time execution. In that case, all required symbols are loaded at compile time using dlopen.

Platform-specific library naming rules:

Example

main :: fn () s32 {
    exe :: add_executable("MyGame");
    add_unit(exe, "src/main.bl");

    switch PLATFORM {
        Platform.WINDOWS { target_windows(exe); }
        default          { panic("Unknown build target!"); }
    }
    compile(exe);
    return 0;
}

target_windows :: fn (exe: *Target) {
    link_library(exe, "freetype");
    link_library(exe, "zlib");
    link_library(exe, "png");
}

File: build.bl

link_static_library :: fn (target: *Target, name: string_view) 

Link a static library. Only the name is required (without extension or prefix). The compiler will look for this library in the working directory, the system PATH, and the linker_lib_path variable specified in the bl.conf file (use blc --where-is-config to get the file location). You can add custom search locations using the add_lib_path function.

The linked library cannot be used during compile-time execution, because the compiler cannot load static libraries at runtime.

Platform-specific library naming rules:

File: build.bl

link_framework :: fn (target: *Target, name: string_view) 

Link a framework on macOS.

File: build.bl

add_framework_path

add_framework_path :: fn (target: *Target, path: string_view) 

Add a framework search path on macOS.

File: build.bl

append_linker_options

append_linker_options :: fn (target: *Target, option: string_view) 

Append raw string directly to the linker command. The passed option is added without any processing or compatibility validation.

File: build.bl

set_output_dir

set_output_dir :: fn (target: *Target, dir: string_view) 

Set the build output directory. This is the directory where all output files will be written. For example, a different output directory can be set for each build mode.

The directory path dir may contain non-existing directories separated by /. The compiler will create all missing directories in the specified path.

The specified directory is also used for build temporary files.

File: build.bl

get_output_dir

get_output_dir :: fn (target: *Target) string_view

Get output directory specified by set_output_dir or empty string.

File: build.bl

set_module_dir

set_module_dir :: fn (target: *Target, dir: string_view) 

Set the module directory dir for the target. When the #import directive is used, the compiler searches this directory first when resolving modules. If the module is not found, the default compiler API location is used. The default location is specified as lib_dir in the bl.conf file (use blc --where-is-config to get the file location).

File: build.bl

get_module_dir

get_module_dir :: fn (target: *Target) string_view

Get the output directory specified by set_output_dir, or an empty string if no directory was set.

File: build.bl

get_default_module_dir

get_default_module_dir :: fn () string_view

Get the module directory specified by set_module_dir or empty string.

File: build.bl

get_default_triple

get_default_triple :: fn () TargetTriple

Return the target triple of the current host machine.

File: build.bl

triple_to_string

triple_to_string :: fn (triple: TargetTriple) string_view

Convert a target triple to a string.

Note: The returned string is allocated using the current temporary allocator.

File: build.bl