Vectem Build Tool is a customizable, module-based C++ build system designed to provide flexible project organization and fine-grained compilation control.
Document sections :
It is built around four core concepts:
All configuration files are written in Lua, allowing dynamic and programmable build logic.
VectemBuildTool [--config <BuildConfigFile> --platform <PlatformName> --dependancy <ProjectRootDir> <UnitName> <UnitType> <build-target>...] <ProjectRootDir> <UnitName> <UnitType> <Target>Can have multiple --dependency-projects
VectemBuildTool Project/ Project ProjectUnit DebugVectemBuildTool --config GlobalBuildConfig.lua --dependency-projects Engine/ Engine EnginUnit Release Project/ Project ProjectUnit DebugA project requires four types of configuration scripts:
- Build Configuration Script
- Target Rules Script
- Unit Rules Script
- Module Rules Script
All scripts are Lua files and are executed in the following order for units and modules:
- Build configuration script
- Unit rules script
- Module rules script
And for target:
- Build configuration script
- Target rules script
Unit rules are executed before module rules.
The system is highly customizable. You can modify folder structures, naming conventions, and rule behaviors.
A module is a code container.
- Modules can depend on other modules.
- Modules may override compilation settings such as optimization level or language version.
- A module cannot be compiled alone; it must belong to a unit.
Units (or build units) contain modules.
A unit can be compiled as:
- An executable
- A static library
- A dynamic library
Units may contain sub-units depending on the build configuration.
Units can depend on other units.
External unit dependencies are specified in the build command and are compiled separately. Their configuration may differ from the main project.
Sub-units can optionally be built together with the main unit.
A project may define multiple targets (e.g., Debug, Release).
Targets define:
- Compilation options
- Optimization level
- Debug information
- Platform support
Modules may override some target settings.
Sub-units always use the same target as their parent unit.
The build configuration define units structure and some units rules. It defines possible units types, them folder structure, them sub-units and some defaults rules.
See
Note : You can add every fields you want
By default, the build system uses:
BuildConfig.lua
located at the project root.
You can override it using:
--config
The script must define a table named:
BuildConfig
BuildConfig defines unit types and their structure.
Each unit type must define:
UnitFileNameThe unit file name.UnitClassNameThe unit rules table name.ModulesDirs(array, cannot be empty)ModuleRootNameThe module root folder name.ModuleFileNameThe module rules script file name.ModuleClassNameThe modules rules table name.BuildDirThe output build directory.SubUnits(array, can be empty)
Supported macro:
${ModuleName}(ForModuleRootName,ModuleFileNameandModuleClassName.)${UnitName}(ForUnitFileName.)
Each sub-unit entry must define:
DirThe directory containing these sub-units.bRecursiveBoolean, recursive path search.UnitTypeThe unit type.UnitRootNameThe unit root folder name.
Supported macro:
${UnitName}(ForUnitRootNameandUnitFileName)
TargetsDirThe target rules directory.TargetFileNameThe target rules script file name.TargetClassNameThe target rules table name.
Supported macro:
${TargetName}(ForTargetFileNameandTargetClassName.)
BuildConfig = {
Program = {
UnitFileName = "${UnitName}.Program.lua",
ModulesDir = { "Modules" },
ModuleRootName = "${ModuleName}Module",
ModuleFileName = "${ModuleName}.Module.lua",
ModuleClassName = "${ModuleName}Rules",
TargetsDir = "Targets",
TargetFileName = "${TargetName}.Target.lua",
TargetClassName = "${TargetName}TagetRules",
BuildDir = "Build",
SubUnits = {
{
Dir = "Plugins",
UnitType = "Plugin",
UnitRootName = "${UnitName}",
bRecursive=true
}
}
},
Plugin = {
UnitFileName = "${UnitName}.Plugin.lua",
ModulesDir = { "Modules" },
ModuleRootName = "${ModuleName}",
ModuleFileName = "${ModuleName.Build.lua}",
ModuleClassName = "${ModuleName}Rules",
BuildDir = "Build",
SubUnits = {}
}
}A target rules script must define:
bAddDebugInfoCVersionCppVersionSupportedPlatformsOptimisationTypeFloatingPointType
- C90
- C99
- C11
- C17
- C23
- CPP98
- CPP03
- CPP11
- CPP14
- CPP17
- CPP20
- CPP23
- CPP26
Lua code :
Platforms = {
Windows = 1,
MacOS = 2,
Linux = 4,
Android = 8,
IOS = 16,
FreeBSD = 32,
OpenBSD = 64,
NetBSD = 128,
All = 0xFF
}- None
- Standard
- Aggressive
- Fast
- MinSize
- Strict (Strict IEEE-754 compliance)
- Precise (Optimized but safe)
- Fast (Maximum optimization, reduced precision guarantees)
ReleaseTarget = {
bAddDebugInfo = false,
CVersion = "C17",
CppVersion = "C++20",
SupportedPlatforms = Platforms.Windows | Platforms.Linux,
OptimisationType = "Fast",
FloatingPointType = "Precise"
}The unit rules table name must be the unit name
Required fields:
CompilationTypeModulesA map containing the module name as key and a table containing additional data as valueSubUnitsA map containing the unit name as key and a table containing additional data as value
- Executable : Create an executable for the unit.
- StaticLibrary : Compile the unit as a static library
- DynamicLibrary : Compile the unit as a dynamic library
Possible fields for both Modules and SubUnits:
PlatformsCompile only on some platforms. See Platforms
ProjectUnit = {
Modules = {
ModuleTest = {
-- Module additional data
},
ModuleTest2 = {
-- Module additional data
}
},
SubUnits = {
PluginTest = {
-- Unit additional data
},
PluginTest2 = {
-- Unit additional data
}
}
}A module rules script must define:
PublicIncludeDirectoriesPrivateIncludeDirectoriesPublicModuleDependenciesPrivateModuleDependenciesAdditionalStaticLibDirectoryRelative to module rootAdditionalStaticLibCan be system libsCodeDirThe code directory
Note: The module root directory is always added as a private include directory.
ModuleRules = {
PublicIncludeDirectories = { "Public", "Interface" },
PrivateIncludeDirectories = { "Private" },
PublicDependencies = { "Utils" },
PrivateDependencies = { "InternalHelpers" },
AdditionalStaticLibDirectory = { "libs" },
AdditionalStaticLib = { "examplea" }
CodeDir = "Source"
}