Skip to content

.clh / .clp / .clpp files

Everything the compiler reads is CL++. The extension only separates role.

ExtensionRoleC++ analogEmitted?
.clhHeader: struct, constants, prototypes.h / .hppTypes (export type) and constants; no bodies
.clpImplementation (modules).c / .cpp without a tagYes — ModuleScript by default
.clppCL++ implementation (scripts and methods).cppYes — Script / LocalScript / ModuleScript from the tag

.clp and .clpp accept the same tags. Prefer .clh + .clpp in C++ style (declare in the header, define in the script).

The key in the filename chooses the Roblox instance (same idea as roblox-ts / Rojo).

SourceInstanceRunContext
LeaderstatsServer.server.clppScriptServer
Hud.client.clppLocalScriptClient
Tools.plugin.clppScriptPlugin
Boot.legacy.clppScriptLegacy
Boot.legacy.server.clppScriptLegacy
Boot.legacy.client.clppLocalScriptLegacy
Damage.clp / Damage.clpp (no tag)ModuleScript
LeaderstatsServer.clhtype ModuleScript

One input file, one output file:

src/server/leaderstats/LeaderstatsServer.server.clpp → out/server/leaderstats/LeaderstatsServer.server.luau
src/client/hud/Hud.client.clpp → out/client/hud/Hud.client.luau
src/shared/config.clp → out/shared/Config.luau
src/shared/PlayerData.clh → out/shared/PlayerData.luau
#include <clpp/roblox.clh>
#include <clpp/libs/janitor.clh>
#include "LeaderstatsServer.clh"
#include "../shared/PlayerData.clh"
FormEffect
#include <clpp/roblox.clh>IntelliSense only. No Luau emit
#include <clpp/generated/instances.clh>IntelliSense for Roblox classes
#include <clpp/datatypes.clh>IntelliSense for Vector3, string_concat, …
#include <clpp/libs/janitor.clh>IntelliSense and a require of the lib
#include "Stem.clh" with the same stem as the .clppInlined (class body)
#include "Other.clh" / "Other.clp"require (Rojo path)
#pragma onceInclude guard; stripped before parse
#pragma strictEmits --!strict
#pragma nostrictEmits --!nonstrict (nstrict / nonstrict aliases)
#pragma nativeEmits --!native
#pragma optimize / #pragma optimize 2Emits --!optimize 2

using …; is skipped. namespace { } is flattened. enum / template / typedef / extern declarations are skipped. // and /* */ comments are stripped.

If the file defines void init(), emit places init() at the end of Scripts and LocalScripts. There is no int main().

Shared modules must not define init() unless they should run on require.