Blitz3D+ Language Reference

Modules (Extended mode)

A Module gives one source file a stable namespace. Importers use a short alias, so independently written libraries may reuse ordinary names without Function, Global, Type, Enum, Interface, array, or generated-label clashes.

Imported source Modules are also incremental compilation boundaries. Unchanged implementations can reuse validated native objects from the compiler-managed cache, which can substantially reduce repeated build time in larger projects. See Organising Projects with Modules for layouts, realistic cold/warm behaviour, cache statistics, and precompiled library workflows.

; math.bb
Dialect "modern"
Module Acme.Math

Global Offset = 2

Function Add(a, b)
    Return a + b + Offset
End Function

Private Function InternalValue()
    Return 2
End Function
; game.bb
Dialect "modern"
Import "math.bb" As Math

Print Math.Add(1, 1)

Dialect, when present, remains first. Module follows it, then every Import, before declarations or executable statements. Imported .bb files must declare a Module. Module names and aliases are case-insensitive dotted identifiers. A missing As uses the final component of the Module name.

Quoted imports are relative to the importing source file. Logical imports such as Import Acme.Math search command-line --module-path roots, B3D_MODULE_PATH, then the installation's modules directory. They look for Acme/Math.bb or Acme/Math.b3m.

Top-level declarations are public by default. Private may prefix a top-level Const, Global, Dim, Function, Worker Function, Type, Interface, or Enum. Private declarations remain usable inside their Module and are absent from its public interface.

Qualified names work for Functions, Globals, constants, arrays, Enums, Types, Interfaces, constructors, Methods, Implements clauses, and StartJob(Alias.Worker, ...). Instance syntax continues to follow the current Dialect.

Include is still textual and is the way to split one Module over several implementation files. Module and Import declarations are not permitted inside an Include. Imports create separate compilation units; dependencies initialize once in dependency-first order.

Precompiled and cached modules

Emit a target-specific distributable object with:

blitzcc --mode extended --emit-module -o Acme/Math.b3m math.bb

Add -d when producing and consuming a Debug object. Debug objects embed a validated copy of their source and Include closure so the debugger can show source, scopes, and locations when producer files are not installed. Release and Debug objects and caches are kept separate.

A .b3m contains the public semantic interface and relocatable native code; it is statically merged into the final program and does not add a DLL dependency. Objects are architecture-, compiler-, runtime-, and build-kind-specific.

Imported source modules are cached automatically. Use --module-cache directory to select a cache root, --no-module-cache to disable reuse, and --module-stats to print deterministic resolved, cached, missed, invalidated, compiled, and linked counts.

Using modules in the IDE

Select Program / Create module... while editing a named Module in Extended mode to create its .b3m object. The suggested path is derived from the dotted Module name. The IDE follows the current Debug setting, so turn Debug off when producing a Release object.

Program / Module search paths... manages the configured roots used by logical imports. Use Add, Remove, Move up, and Move down to edit the list. These paths are saved with the IDE preferences and applied automatically to Run, Check for errors, Create executable, and Create module.

Program / Rebuild all source modules performs one error-check build with --no-module-cache. Every imported .bb Module generates fresh native code without consuming, publishing, or deleting compiler-managed cache entries. Explicit .b3m imports remain precompiled inputs.