Frames and Composer Markers
Frames are Luau files that contain composer markers, which are build-time macros to replace chunks of code with build data.
Built-in markers
| Marker | Replaced with | Type |
|---|---|---|
__COMPOSER.Insert(__COMPOSER.build) |
Full compiled source code | string |
__COMPOSER.Insert(__COMPOSER.genDate) |
ISO 8601 build date (quoted) | "YYYY-MM-DD" |
__COMPOSER.Insert(__COMPOSER.cfg) |
Build config name (quoted) | "Release" |
__COMPOSER.Insert(__COMPOSER.vers) |
Version string (quoted) | "v1.2.3" |
Writing a frame
A frame is a plain .luau file. Use markers as expressions — they are replaced with raw Luau values (strings are already quoted with %q).
pipeline/frames/release.luau
--!nolint
--!nocheck
--!native
--!optimize 2
--[[
Generated by ProCMP — do not edit manually.
]]
_P = {
genDate = __COMPOSER.Insert(__COMPOSER.genDate),
cfg = __COMPOSER.Insert(__COMPOSER.cfg),
vers = __COMPOSER.Insert(__COMPOSER.vers),
}
__COMPOSER.Insert(__COMPOSER.build)
After composition, __COMPOSER.Insert(__COMPOSER.vers) becomes "v1.2.3".
Runtime access
The _P table is available at runtime in your built script:
if _P.cfg == "Debug" then
warn("[DEBUG BUILD]")
end
print("Version:", _P.vers)
print("Built:", _P.genDate)
You can rename _P to anything. If you use luau-lsp, add type definitions to silence warnings:
.globals/pcmp.d.luau
declare __COMPOSER: {
Insert: (text: string) -> string,
genDate: string,
build: string,
cfg: string,
vers: string,
}
declare _P: { [any]: any }
Multiple frames
You can have different frames for different configs. The frame field is per-config in .pcmp.json:
{
"buildConfigs": [
{
"name": "Debug",
"frame": "pipeline/frames/debug.luau",
...
},
{
"name": "Release",
"frame": "pipeline/frames/release.luau",
...
}
]
}
A common pattern is a debug frame with no optimisation flags and extra logging headers, and a release frame with --!native --!optimize 2 and a clean header.