GMod Backend

luxc gmod build turns Lux source modules into Garry's Mod Lua artifacts. The backend is responsible for discovery, realm splitting, the Lux loader tree, optional autorun forwarding, AddCSLuaFile routing, source maps, and package integration.

What the Backend Does

The GMod backend performs these steps:

1. Read lux.toml.
2. Discover modules under source_root.
3. Discover Lux packages from `lux.lock` and configured `package_roots`.
4. Infer part realms from cl_/sv_/sh_ prefixes and realm directories.
5. Resolve imports, exports, macros, and host transforms.
6. Check realm availability and unknown extern policy.
7. Emit server, client, and shared Lua artifacts.
8. Emit module artifacts, source maps, Lux loaders, and optional autorun forwarder.

The result is a relative-path-safe Lua output tree. Addon projects normally put that tree under generated/lua; gamemodes or framework integrations can point out somewhere else and include the loaders manually.

The backend does not assume every project owns lua/autorun. Plain init defaults to addon-friendly output, but autorun = false is enough when another entry point should own startup.

Minimal Configuration

package_id = "my_addon"
bundle_id = "my_addon"

[target.gmod]
source_root = "src"
out = "generated/lua"
runtime_base = "lux/my-addon"
autorun = true
source_comments = "readable"

package_id identifies the current project package. bundle_id is used in generated registry names and default paths. out is the physical output root. runtime_base is the GMod-relative path used by generated include and AddCSLuaFile calls. autorun = true writes an addon-style forwarder under out/autorun; set it to false when another entry point owns startup.

Generated Layout

Typical output:

generated/
  lua/
    autorun/
      my_addon.lua
    lux/
      my-addon/
        loader_shared.lua
        loader_client.lua
        loader_server.lua
        client/
          my_addon/
            hud.lua
        server/
          my_addon/
            inventory.lua
        shared/
          my_addon/
            items.lua

The exact file density may change as module merging improves, but the generated root remains build output. Source files stay under src/.

Build Commands

Build through the manifest:

luxc gmod build --manifest lux.toml

Build with explicit paths:

luxc gmod build src --out generated/lua

For production-sized source comments, set this in lux.toml:

[target.gmod]
source_comments = "none"

Use source maps to map runtime Lua stack traces back to Lux source:

generated/lua/lux/my-addon/client/my_addon/hud.lua:42:9 -> src/hud/cl_paint.lux:18:3

Realm Artifacts

Realm blocks and realm declarations control which artifact receives code.

server block only enters server artifact
fn ENT:Initialize() {
  self:SetCustomCollisionCheck(true)

  server {
    self:PhysicsInitBox(Vector(-20, -20, 0), Vector(20, 20, 86))
  }
}

The checker uses the inner active realm for PhysicsInitBox, so server-only uses inside the block are accepted even when the surrounding function is shared.

Package as GMA

After building, package the addon with GMod tools from the addon root. If out = "generated/lua", the package root is usually generated:

gmad.exe create -folder generated -out my_addon.gma

Keep generated output under the package root if it should be included in the GMA. out itself is not necessarily the package root.

Development Recommendations

  • Keep src/ and generated/ separate.
  • Put complete part order in the module entry part when initialization order matters.
  • Prefer cl_, sv_, and sh_ prefixes for files that map naturally to GMod convention.
  • Use realm blocks for fine-grained server/client code inside shared hooks.
  • Treat unknown external warnings as work items; add extern declarations for third-party APIs you rely on.
  • Do not hand-write AddCSLuaFile for Lux modules. The generated Lux loader owns client file routing. If autorun = false, include the generated loaders from your own entry point.