This file provides guidance to Claude Code (claude.ai/code) when working with the Malterlib BuildSystem module.
The BuildSystem module is the core of Malterlib's custom build system (mib/MTool). It provides a sophisticated build configuration DSL, cross-platform project generation, and repository management capabilities. The module implements parsing, evaluation, and generation of build configurations across multiple platforms (macOS, Windows, Linux) and IDEs (Xcode, Visual Studio).
The build system uses a custom Domain-Specific Language (DSL) for describing build configurations:
- File Types:
.MBuildSystem- Root build system configuration.MHeader- Module header files defining targets and properties.MTarget- Target definitions.MConfig- Configuration files.MSettings- Settings files.MRepo- Repository configuration
CBuildSystem- Main build system orchestratorCTarget- Build target representationCWorkspace- Workspace (collection of targets) managementCProperty- Property management and evaluationCEntity- Base class for build entitiesCGenerator- Base class for platform-specific generatorsCGeneratorState- Generation state managementCRegistry- Build system registry for properties and settings
BuildSystem/
├── Include/Mib/BuildSystem/ # Public API headers
│ ├── BuildSystem # Main build system API
│ ├── BuildSystemDependency # Dependency management
│ ├── BuildSystemPreprocessor # Preprocessor functionality
│ └── Registry # Registry API
├── Source/ # Implementation
│ ├── Generators/ # Platform-specific generators
│ │ ├── VisualStudio/ # Visual Studio project generation
│ │ └── Xcode/ # Xcode project generation
│ ├── Malterlib_BuildSystem_*.cpp/h # Core implementation files
│ └── Various subsystems (Parse, Evaluate, Generate, etc.)
├── Test/ # Unit tests
└── TestFiles/ # Test configuration files
Entities are prefixed with special characters:
%- Declares an entity (Target, Group, File, Dependency, etc.)*- Declares configuration tuple (Configuration, Platform, Architecture)- No prefix - Property assignment
Properties support various types and modifiers based on EJSON:
- Basic types:
bool,string,int,float - Arrays:
[string],[int],[bool], etc. - Maps/Objects:
{string: string},{string: any} - Optional:
?suffix (e.g.,bool?) - Functions:
function(parameters) return_type - Custom types: Defined with
Typedeclarations - Any type:
anyfor dynamic values
Key "Value"- Direct assignment, overwrites any previous valueKey: type = "Default"- Sets a default value that only applies if the property remains undefined after all other processing+=- Prepends to existing value (if a property has+=, any default value set with=is ignored)=+- Appends to existing value (if a property has=+, any default value set with=is ignored)
Conditions filter when properties or entities apply:
Property
{
OptimizationLevel "O3"
{
!!Configuration "Release" // Double !! means condition
}
}
Common condition operators:
!!- Condition prefix!- NOT operator&- AND operator|- OR operator
%Target "Lib_Malterlib_BuildSystem"
{
Target
{
Name "Lib_Malterlib_BuildSystem"
Type "StaticLibrary"
}
Property
{
MalterlibNoShortcuts false
}
Compile
{
!!CompileDialect "C"
PrefixHeader "Source/Malterlib_BuildSystem.h"->MakeAbsolute()
{
|
{
Compile.Type "C++"
!GeneratorFamily "VisualStudio"
}
}
}
%Group "BuildSystem"
{
%Group "Include"
{
Compile.Type "C++"
%File "Include/Mib/BuildSystem/^*"
}
%File "Source/^*"
}
%Dependency "Lib_Malterlib_Core"
}
%Workspace "BuildSystem"
{
Workspace
{
Name "BuildSystem"
}
%Target "Lib_Malterlib_BuildSystem"
%Target "Test_Malterlib_BuildSystem"
{
!!MalterlibEnableInternalTests true
}
}
Property
{
MalterlibBuildSystemEmbedCMake: bool?
BuildOutputDirectory: string = "/opt/Deploy"
IncludePaths: [string] = []
CompilerFlags: [string] = ["-Wall", "-Werror"] // Default only used if CompilerFlags is undefined
}
Property
{
!!Configuration "Debug"
CompilerFlags =+ ["-g", "-O0"] // This appends, so default ["-Wall", "-Werror"] won't apply
}
The DSL provides numerous built-in functions for path manipulation, string operations, and more:
MakeAbsolute(path)- Convert to absolute pathMakeRelative(path, base)- Convert to relative pathGetFile(path)- Extract filename from pathGetPath(path)- Extract directory from pathGetExtension(path)- Extract file extensionGetFileNoExt(path)- Get filename without extensionGetDrive(path)- Get drive letter (Windows)AppendPath(path, ...)- Append path componentsIsAbsolute(path)- Check if path is absoluteWindowsPath(path)- Convert to Windows path formatUnixPath(path)- Convert to Unix path formatNativePath(path)- Convert to native OS path formatShortenPath(path)- Shorten long paths (Windows)RelativeBase(path)- Get path relative to build system baseGetLastPaths(path, n)- Get last n path componentsRemoveStartPaths(path, n)- Remove first n path components
ToString(...)- Convert values to stringToStringCompact(...)- Convert to compact stringEJsonToString(value, indent?)- Convert to EJSON stringJsonToString(value, indent?)- Convert to JSON stringParseEJson(string, filename?)- Parse EJSON stringParseJson(string, filename?)- Parse JSON stringSplit(source, splitBy)- Split string into arrayJoin(strings, joinBy)- Join array into stringReplace(source, searchFor, replaceWith)- Replace string occurrencesReplaceChars(string, searchForChars, replaceWith)- Replace charactersTrim(source)- Trim whitespaceEscape(source)- Escape special charactersEscapeHost(source...)- Escape for host OSEscapeWindows(source...)- Escape for WindowsEscapeBash(source...)- Escape for BashEscapeMSBuild(string)- Escape for MSBuild
ForEach(array, function, properties?)- Apply function to each elementContainsListElement(array, element)- Check if array contains elementLength(array)- Get length of array or stringIsEmpty(array)- Check if array or string is emptyUnique(array)- Remove duplicate elementsRemoveDuplicates(array, value)- Remove duplicates of specific valueSort(array)- Sort array elementsConcat(arrays...)- Concatenate multiple arrays
GeneratedFiles(wildcard)- Get list of generated files matching wildcardSourceFiles(wildcard)- Get list of source files matching wildcardReadFile(filename, byDigest?)- Read file contentsFileExists(filename)- Check if file existsLinkExists(filename)- Check if symbolic link existsResolveSymbolicLink(filename)- Resolve symbolic linkDirectoryExists(filename)- Check if directory existsFileOrDirectoryExists(filename)- Check if file or directory existsFindFilesIn(path, wildcard, excludeWildcards?)- Find files in directoryFindDirectoriesIn(path, wildcard, excludeWildcards?)- Find directoriesFindFilesRecursiveIn(path, wildcard, excludeWildcards?)- Find files recursivelyFindDirectoriesRecursiveIn(path, wildcard, excludeWildcards?)- Find directories recursively
- Xcode - macOS/iOS development
- Visual Studio - Windows development
Generators can be configured through .MSettings files:
GeneratorSetting
{
XcodeVersion "14.0"
VisualStudioVersion "2022"
CMakeMinimumVersion "3.20"
}
The BuildSystem includes integrated repository management:
%Repository "Malterlib"
{
Repository
{
Path "."
Type "git"
Remote "origin"
DefaultBranch "master"
}
}
- Status checking
- Branch management
- Synchronized operations across multiple repos
- Git LFS support for binary dependencies
Tests are organized in Test/ directory:
Test_Malterlib_BuildSystem_General.cpp- General functionality testsTest_Malterlib_BuildSystem_Generate.cpp- Generation testsTest_Malterlib_BuildSystem_Parse.cpp- Parser testsTest_Malterlib_BuildSystem_Syntax.cpp- Syntax tests
TestFiles/ contains various test configurations demonstrating DSL features:
- Basic configurations (Simple, Empty)
- Advanced features (ForEach, Conditions, Functions)
- Type system (Types, DefaultedTypes, DynamicValue)
- Generation (GenerateFile, Expand)
The BuildSystem module is the engine behind the mib command-line tool. Key integration points:
The BuildSystem uses parallel processing for:
- File parsing
- Dependency resolution
- Project generation
- Repository operations
The module uses CStringCache for efficient string handling:
CStringCache StringCache;
CPropertyKey Key(StringCache, "PropertyName");- Targets:
Lib_,Exe_,Com_,Tool_prefixes - Workspaces: Descriptive names matching module or purpose
- Properties: CamelCase without prefixes in DSL
- Functions: CamelCase for DSL built-ins
- Keep
.MHeaderfiles at module root - Place
.MTargetfiles near their implementation - Group related configurations in subdirectories
- Use conditions sparingly for clarity
- Prefer composition over complex conditions
- Document non-obvious property dependencies
- Use type annotations for custom types
// Proper indentation and spacing in DSL files
%Target "Lib_Malterlib_BuildSystem"
{
Target
{
Name "Lib_Malterlib_BuildSystem"
Type "StaticLibrary"
}
// Group related properties
Property
{
OutputDirectory: string = "/opt/Deploy/BuildSystem"
IntermediateDirectory: string = "/opt/Build/BuildSystem"
}
// Use clear condition grouping
Compile
{
PreprocessorDefines =+ ["DEBUG", "ASSERTIONS"]
{
!!Configuration "Debug"
}
PreprocessorDefines =+ ["NDEBUG", "OPTIMIZE"]
{
!!Configuration "Release"
}
}
// Organize files logically
%Group "Public"
{
%File "Include/^*"
}
%Group "Implementation"
{
%File "Source/^*"
}
// Clear dependency declarations
%Dependency "Lib_Malterlib_Core"
}
Property
{
TestProperty "Value"
{
#Debug "TraceEval,TraceCondition"
}
}
%File "platform_specific.cpp"
{
!!PlatformFamily "Windows"
}
%File "platform_specific.mm"
{
!!PlatformFamily "macOS"
}
- The BuildSystem is the foundation of Malterlib's build infrastructure
- Changes to this module can affect the entire build process
- Always test generator changes on all supported platforms
- The DSL parser is recursive descent with backtracking
- String interpolation uses
`backticks with@()for expressions - Property evaluation is lazy and cached for performance
- The module supports distributed builds through NConcurrency
- File patterns use
^for recursive matching - Conditions are evaluated at generation time, not build time
- The build system maintains a dependency graph for incremental builds