Version: 1.0
Language: Luma
Lumix is a build system for the Luma programming language that automates dependency detection, module compilation, and linking. It scans your project directory for .lx files, analyzes their dependencies, and generates the appropriate compilation commands.
- Automatic Entry Point Detection - Finds the file containing
pub const main -> fn ()automatically - Dependency Scanning - Parses
@usedirectives to identify module dependencies - Deduplication - Ensures each dependency is only included once in the build command
- Standard Library Support - Automatically converts
std_*module names tostd/*.lxpaths - Interactive CLI - Simple command-based interface for building, cleaning, and inspecting dependencies
Compile Lumix with the following command:
luma src/lumix.lx -name lumix -l src/utility.lx src/parser.lx src/file_system.lx src/module.lx src/user_input.lx std/io.lx std/sys.lx std/vector.lx std/string.lx std/memory.lxThis creates the lumix executable in your current directory.
- Navigate to your Luma project directory
- Run
./lumix - Choose a command:
build- Compile your projectclean- Remove build artifactsdeps- Show dependency tree
Command (build/clean/deps): build
The build process:
- Scans for
.lxfiles in the current directory - Auto-detects the entry point (file with
pub const main -> fn ()) - Prompts for output binary name (defaults to
main) - Compiles all modules with proper dependency linking
Example:
=== Building Luma Project ===
Scanning for entry point...
Auto-detected entry point: game.lx
Output binary name (press Enter for 'main'): my_game
Found files:
- game.lx
- player.lx
- renderer.lx
Compiling modules...
Executing command:
luma game.lx -l std/io.lx std/string.lx player.lx renderer.lx -name my_game
Build completed successfully. Output: my_game
Removes build artifacts:
*.oobject files- Default
mainexecutable - Temporary files in
/tmp/luma_*.txt
Command (build/clean/deps): clean
=== Cleaning Build Artifacts ===
Done.
Shows the dependency tree for your project:
Command (build/clean/deps): deps
=== Dependency Tree ===
Module dependencies:
game depends on:
- player
- renderer
- std_io
player depends on:
- std_string
- std_memory
renderer (no dependencies)
Lumix uses the find command to locate all .lx files:
find . -name '*.lx' -type f 2>/dev/null > /tmp/luma_files.txtFalls back to ls if find is unavailable.
Scans each file for the pattern:
pub const main -> fn ()
The first file containing this pattern becomes the entry point.
For each file, Lumix:
- Reads the file content
- Finds all
@usedirectives - Extracts module names from quotes:
@use "module_name" - Ignores comments (
//)
Standard library modules are converted:
std_io→std/io.lxstd_string→std/string.lxstd_memory→std/memory.lx
Lumix constructs a command like:
luma <entry_point> -l <std_libs> <other_files> -name <output_name>With deduplication to ensure each dependency appears only once.
The has_dep() function checks if a dependency is already in the build command:
const has_dep -> fn (slice_ptr: *Slice, slice_count: int, dep_path: *byte) int {
loop [i: int = 0](i < slice_count) : (i = i + 1) {
if (string::strcmp(slice_ptr[i].ptr, dep_path) == 0) return 1;
}
return 0;
}
This prevents duplicate inclusions while keeping the implementation simple.
lumix.lx- Main entry point, CLI, and build orchestrationfile_system.lx- File discovery and directory operationsparser.lx- Parsing@usedirectives and file contentmodule.lx- Module name extraction from file pathsutility.lx- Helper functions (string ops, file checks, main detection)user_input.lx- Helper function (get_user_input)
Dependency graph stored in global arrays:
g_module_names- Module names extracted from filesg_file_paths- Full paths to source filesg_dependencies- List of dependencies for each fileg_dep_counts- Number of dependencies per fileg_visited/g_in_stack- For future cycle detection
- Maximum 500 files per project (
fs::MAX_FILES) - Maximum 200 dependencies per file (
parser::MAX_DEPS) - No circular dependency detection (currently unused but infrastructure exists)
- Simple deduplication - relies on string matching, no version resolution
- Local files only - no remote package management (yet)
The BuildConfig struct defines build settings:
const BuildConfig -> struct {
entry_point: *byte, // Path to main file
output_name: *byte, // Binary name
stdlib_path: *byte, // Path to std lib (default: "std")
optimize: int, // Optimization level (unused)
debug_symbols: int, // Debug symbols flag (unused)
verbose: int // Verbose output (1 = on)
};
Currently, only entry_point, output_name, and verbose are used.
- Ensure you're in a directory with
.lxfiles - Check file permissions
- Make sure one file has
pub const main -> fn () - Check for typos in the function signature
- Files must have
.lxextension - Filenames should be valid identifiers
- Ensure all imported modules exist as files
- Check that standard library is in the
std/directory or accessible to the compiler (which if you install it using the install.sh everything should be setup for luma)
See TODO.md for planned features and improvements.