Skip to content

Commit 58a4ea5

Browse files
author
Sindicato Roleplay
committed
feat(cli): add standalone verification CLI with cross-platform release support
1 parent 2927a4b commit 58a4ea5

15 files changed

Lines changed: 3938 additions & 0 deletions

README_CFXLUA.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# CfxLua CLI Toolchain
2+
3+
A standalone verification toolchain for FiveM Lua scripts, powered by the Polaris-patched **LuaGLM 5.4** VM.
4+
5+
## Features
6+
7+
- **Polaris Patches**: Custom optimizations and fixes for FiveM script verification.
8+
- **MagicMock System**: Automatically handles missing globals (like `lib`, `ox_inventory`, or client-only natives) by returning indexable/callable stubs instead of crashing.
9+
- **Lazy Resource Discovery**: Dynamically scans your `resources/` folder to discover exports from other resources, allowing for deep static analysis across resource boundaries.
10+
- **Infinite Loop Protection**: Integrated execution timeout (default 5s) to prevent CI/CD pipelines from hanging on infinite `Wait(0)` loops.
11+
- **Full Lua 5.4 Support**: Supports all CitizenFX Lua 5.4 features including `each` iterators, `defer`, and callable vectors.
12+
13+
## Installation
14+
15+
### 🚀 Quick Install (Download Release)
16+
17+
Download the latest package for your platform from the [Releases](https://github.com/USER/cfxlua-cli/releases) page.
18+
19+
#### Linux
20+
1. Extract the `.tar.gz`.
21+
2. Run `sudo ./install.sh`.
22+
23+
#### Windows
24+
1. Extract the `.zip`.
25+
2. Run `install.bat` (Admin may be required to update PATH).
26+
27+
### 🛠️ Build from Source
28+
29+
```bash
30+
git clone https://github.com/USER/cfxlua-cli.git
31+
cd cfxlua-cli
32+
make -j$(nproc)
33+
sudo ./install.sh
34+
```
35+
36+
## Usage
37+
38+
Verify any Lua script:
39+
40+
```bash
41+
cfxlua path/to/script.lua
42+
```
43+
44+
### Environment Variables
45+
46+
- `CFXLUA_TIMEOUT`: Execution timeout in milliseconds (default: `5000`).
47+
- `CFXLUA_VM`: Path to a custom Lua VM binary.
48+
- `CFXLUA_RUNTIME`: Path to the runtime mock directory.
49+
50+
## Contributing
51+
52+
This tool is based on the [citizenfx/lua](https://github.com/citizenfx/lua) VM but adds a standalone verification layer. Contributions to mocks and resource discovery logic are welcome!
53+
54+
## Credits
55+
56+
- **Polaris Naz**: Patches, Advanced Mocks, and CLI logic.
57+
- **Cfx.re**: Original LuaGLM 5.4 runtime.

bin/cfxlua

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
#!/usr/bin/env bash
2+
# =============================================================================
3+
# bin/cfxlua — CfxLua Standalone Interpreter Wrapper
4+
# =============================================================================
5+
# Install: copy or symlink this file into a directory on your PATH.
6+
# sudo ln -s "$(pwd)/bin/cfxlua" /usr/local/bin/cfxlua
7+
#
8+
# Usage:
9+
# cfxlua <script.lua> [arg1 arg2 ...]
10+
# cfxlua --version
11+
# cfxlua --help
12+
#
13+
# Environment variables:
14+
# CFXLUA_VM Override path to the cfxlua-vm binary (default: auto-detect)
15+
# CFXLUA_RUNTIME Override path to the runtime/ directory
16+
# CFXLUA_RESOURCE Override the resource name (default: script basename)
17+
# =============================================================================
18+
19+
set -euo pipefail
20+
21+
# ---------------------------------------------------------------------------
22+
# Resolve the directory this script lives in, following symlinks.
23+
# This is the canonical way to locate co-installed files in POSIX sh.
24+
# ---------------------------------------------------------------------------
25+
_self_dir() {
26+
local source="${BASH_SOURCE[0]}"
27+
while [ -L "$source" ]; do
28+
local dir
29+
dir="$(cd -P "$(dirname "$source")" && pwd)"
30+
source="$(readlink "$source")"
31+
[[ "$source" != /* ]] && source="$dir/$source"
32+
done
33+
cd -P "$(dirname "$source")" && pwd
34+
}
35+
36+
SCRIPT_DIR="$(_self_dir)"
37+
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
38+
39+
# ---------------------------------------------------------------------------
40+
# Locate the cfxlua-vm binary.
41+
# Build system places it at: vm/build/lua (renamed via Makefile install target)
42+
# We check several locations in priority order.
43+
# ---------------------------------------------------------------------------
44+
if [ -n "${CFXLUA_VM:-}" ]; then
45+
VM_BIN="$CFXLUA_VM"
46+
elif [ -x "$PROJECT_DIR/vm/build/cfxlua-vm" ]; then
47+
VM_BIN="$PROJECT_DIR/vm/build/cfxlua-vm"
48+
elif [ -x "$PROJECT_DIR/vm/build/lua" ]; then
49+
VM_BIN="$PROJECT_DIR/vm/build/lua"
50+
elif command -v cfxlua-vm &>/dev/null; then
51+
VM_BIN="$(command -v cfxlua-vm)"
52+
else
53+
# Fall back to the system Lua 5.4 for development/testing without a built VM.
54+
# NOTE: Without LuaGLM, vector types and power-patches won't be available.
55+
if command -v lua5.4 &>/dev/null; then
56+
VM_BIN="$(command -v lua5.4)"
57+
echo "[cfxlua] WARNING: cfxlua-vm not found; using system lua5.4 (no LuaGLM extensions)" >&2
58+
elif command -v lua &>/dev/null; then
59+
VM_BIN="$(command -v lua)"
60+
echo "[cfxlua] WARNING: cfxlua-vm not found; using system lua (no LuaGLM extensions)" >&2
61+
else
62+
echo "[cfxlua] FATAL: no Lua interpreter found." >&2
63+
echo " Build the VM: cd $PROJECT_DIR && make" >&2
64+
echo " Or set: export CFXLUA_VM=/path/to/lua" >&2
65+
exit 1
66+
fi
67+
fi
68+
69+
# ---------------------------------------------------------------------------
70+
# Locate the runtime directory.
71+
# ---------------------------------------------------------------------------
72+
RUNTIME_DIR="${CFXLUA_RUNTIME:-$PROJECT_DIR/runtime}"
73+
BOOTSTRAP="$RUNTIME_DIR/bootstrap.lua"
74+
75+
if [ ! -f "$BOOTSTRAP" ]; then
76+
echo "[cfxlua] FATAL: bootstrap.lua not found at '$BOOTSTRAP'" >&2
77+
echo " Set CFXLUA_RUNTIME to the correct runtime directory." >&2
78+
exit 1
79+
fi
80+
81+
# ---------------------------------------------------------------------------
82+
# Handle special flags.
83+
# ---------------------------------------------------------------------------
84+
if [ "${1:-}" = "--version" ] || [ "${1:-}" = "-v" ]; then
85+
case "${LC_ALL:-${LC_CTYPE:-${LANG:-}}}" in
86+
*[Uu][Tt][Ff]-8*|*[Uu][Tt][Ff]8*)
87+
printf "CfxLua 1.0.1 · © 2026 Polaris Naz\nLuaGLM 5.4 · Cfx.re"
88+
;;
89+
*)
90+
printf "CfxLua 1.0.1 - (c) 2026 Polaris Naz\nLuaGLM 5.4 - Cfx.re"
91+
;;
92+
esac
93+
exit 0
94+
fi
95+
96+
if [ "${1:-}" = "--help" ] || [ "${1:-}" = "-h" ] || [ $# -eq 0 ]; then
97+
case "${LC_ALL:-${LC_CTYPE:-${LANG:-}}}" in
98+
*[Uu][Tt][Ff]-8*|*[Uu][Tt][Ff]8*)
99+
printf "CfxLua 1.0.1 · © 2026 Polaris Naz\nLuaGLM 5.4 · Cfx.re\n\n"
100+
;;
101+
*)
102+
printf "CfxLua 1.0.1 - (c) 2026 Polaris Naz\nLuaGLM 5.4 - Cfx.re\n\n"
103+
;;
104+
esac
105+
cat <<EOF
106+
Usage:
107+
cfxlua <script.lua> [arg1 arg2 ...]
108+
cfxlua --version
109+
cfxlua -v
110+
cfxlua --help
111+
cfxlua -h
112+
113+
Arguments:
114+
<script.lua> Run a Lua script via runtime/bootstrap.lua
115+
[arg1 arg2 ...] Passed through to the script as arg[1..n]
116+
--version, -v Print interpreter and VM version banner
117+
--help, -h Print this help message
118+
119+
Environment:
120+
CFXLUA_VM Path to the cfxlua-vm binary (default: auto-detect)
121+
CFXLUA_RUNTIME Path to the runtime/ directory (default: $PROJECT_DIR/runtime)
122+
CFXLUA_RESOURCE Resource name override (default: script basename)
123+
124+
Examples:
125+
cfxlua my_resource/server.lua
126+
cfxlua tests/run_tests.lua
127+
CFXLUA_RESOURCE=my-resource cfxlua server.lua
128+
129+
Build the VM:
130+
cd $PROJECT_DIR && make
131+
EOF
132+
exit 0
133+
fi
134+
135+
# ---------------------------------------------------------------------------
136+
# Derive resource name from the script path (strip directory and extension).
137+
# Resources that use GetCurrentResourceName() get a sensible value.
138+
# ---------------------------------------------------------------------------
139+
SCRIPT_PATH="$1"
140+
SCRIPT_BASENAME="$(basename "$SCRIPT_PATH")"
141+
SCRIPT_RESOURCE="${SCRIPT_BASENAME%.*}" # strip extension
142+
143+
export CFXLUA_RESOURCE_NAME="${CFXLUA_RESOURCE:-$SCRIPT_RESOURCE}"
144+
export CFXLUA_BOOTSTRAP_PATH="$PROJECT_DIR"
145+
146+
# ---------------------------------------------------------------------------
147+
# Inject the bootstrap path into Lua via a synthetic global.
148+
# We prepend a tiny chunk that sets __cfx_bootstrapPath before bootstrap.lua
149+
# runs, using Lua's -e flag.
150+
# ---------------------------------------------------------------------------
151+
INJECT="__cfx_bootstrapPath = '$(echo "$PROJECT_DIR" | sed "s/'/\\\\'/g")'"
152+
153+
# Execute.
154+
# The `--` separator ensures script args aren't consumed by the Lua interpreter.
155+
exec "$VM_BIN" \
156+
-e "$INJECT" \
157+
"$BOOTSTRAP" \
158+
"$@"

bin/cfxlua.bat

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
@echo off
2+
setlocal
3+
4+
:: =============================================================================
5+
:: bin/cfxlua.bat — CfxLua Standalone Interpreter Wrapper (Windows)
6+
:: =============================================================================
7+
8+
:: ---------------------------------------------------------------------------
9+
:: Resolve directories
10+
:: ---------------------------------------------------------------------------
11+
set "SCRIPT_DIR=%~dp0"
12+
for %%i in ("%SCRIPT_DIR%..") do set "PROJECT_DIR=%%~fi"
13+
14+
:: ---------------------------------------------------------------------------
15+
:: Locate the cfxlua-vm binary
16+
:: ---------------------------------------------------------------------------
17+
if defined CFXLUA_VM (
18+
set "VM_BIN=%CFXLUA_VM%"
19+
) else if exist "%PROJECT_DIR%\vm\build\cfxlua-vm.exe" (
20+
set "VM_BIN=%PROJECT_DIR%\vm\build\cfxlua-vm.exe"
21+
) else if exist "%PROJECT_DIR%\vm\build\lua.exe" (
22+
set "VM_BIN=%PROJECT_DIR%\vm\build\lua.exe"
23+
) else (
24+
where cfxlua-vm >nul 2>nul
25+
if %errorlevel% equ 0 (
26+
for /f "delims=" %%i in ('where cfxlua-vm') do set "VM_BIN=%%i"
27+
) else (
28+
where lua5.4 >nul 2>nul
29+
if %errorlevel% equ 0 (
30+
for /f "delims=" %%i in ('where lua5.4') do set "VM_BIN=%%i"
31+
echo [cfxlua] WARNING: cfxlua-vm.exe not found; using system lua5.4 (no LuaGLM extensions) >&2
32+
) else (
33+
where lua >nul 2>nul
34+
if %errorlevel% equ 0 (
35+
for /f "delims=" %%i in ('where lua') do set "VM_BIN=%%i"
36+
echo [cfxlua] WARNING: cfxlua-vm.exe not found; using system lua (no LuaGLM extensions) >&2
37+
) else (
38+
echo [cfxlua] FATAL: no Lua interpreter found. >&2
39+
exit /b 1
40+
)
41+
)
42+
)
43+
)
44+
45+
:: ---------------------------------------------------------------------------
46+
:: Locate the runtime directory
47+
:: ---------------------------------------------------------------------------
48+
if defined CFXLUA_RUNTIME (
49+
set "RUNTIME_DIR=%CFXLUA_RUNTIME%"
50+
) else (
51+
set "RUNTIME_DIR=%PROJECT_DIR%\runtime"
52+
)
53+
54+
set "BOOTSTRAP=%RUNTIME_DIR%\bootstrap.lua"
55+
56+
if not exist "%BOOTSTRAP%" (
57+
echo [cfxlua] FATAL: bootstrap.lua not found at "%BOOTSTRAP%" >&2
58+
exit /b 1
59+
)
60+
61+
:: ---------------------------------------------------------------------------
62+
:: Handle special flags
63+
:: ---------------------------------------------------------------------------
64+
if "%~1"=="--version" (
65+
echo CfxLua 1.1.0 - (c) 2026 Polaris Naz
66+
echo LuaGLM 5.4 - Cfx.re
67+
exit /b 0
68+
)
69+
if "%~1"=="-v" (
70+
echo CfxLua 1.1.0 - (c) 2026 Polaris Naz
71+
echo LuaGLM 5.4 - Cfx.re
72+
exit /b 0
73+
)
74+
75+
if "%~1"=="--help" goto :usage
76+
if "%~1"=="-h" goto :usage
77+
if "%~1"=="" goto :usage
78+
79+
:: ---------------------------------------------------------------------------
80+
:: Execute the VM
81+
:: ---------------------------------------------------------------------------
82+
:: Set the bootstrap path for the VM
83+
set "__cfx_bootstrapPath=%RUNTIME_DIR:\=/%"
84+
85+
"%VM_BIN%" "%BOOTSTRAP:\=/%" %*
86+
exit /b %errorlevel%
87+
88+
:usage
89+
echo Usage: cfxlua ^<script.lua^> [arg1 arg2 ...]
90+
echo cfxlua --version
91+
echo cfxlua --help
92+
exit /b 0

build_release.sh

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#!/usr/bin/env bash
2+
set -e
3+
4+
# =============================================================================
5+
# build_release.sh — CfxLua CLI Maintainer Release Builder
6+
# =============================================================================
7+
8+
VERSION="1.1.0"
9+
DIST_DIR="dist"
10+
LINUX_PKG="cfxlua-cli-linux.tar.gz"
11+
WIN_PKG="cfxlua-cli-windows.zip"
12+
13+
echo "Building CfxLua CLI v$VERSION Release..."
14+
15+
# 1. Clean and Prepare
16+
rm -rf "$DIST_DIR"
17+
mkdir -p "$DIST_DIR/linux" "$DIST_DIR/windows/bin" "$DIST_DIR/windows/runtime"
18+
19+
# 2. Build Linux VM
20+
echo "Building Linux VM..."
21+
make -j$(nproc)
22+
cp build/lua "$DIST_DIR/linux/cfxlua-vm"
23+
24+
# 3. Build Windows VM (Cross-compile)
25+
if command -v x86_64-w64-mingw32-gcc &> /dev/null; then
26+
echo "Building Windows VM (Cross-compiling)..."
27+
make clean
28+
make CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ PLAT=mingw -j$(nproc)
29+
cp build/lua.exe "$DIST_DIR/windows/cfxlua-vm.exe"
30+
else
31+
echo "WARNING: x86_64-w64-mingw32-gcc not found. Skipping Windows build."
32+
fi
33+
34+
# 4. Package Linux
35+
echo "Packaging Linux..."
36+
cp -r bin runtime install.sh "$DIST_DIR/linux/"
37+
tar -czvf "$LINUX_PKG" -C "$DIST_DIR/linux" .
38+
39+
# 5. Package Windows
40+
if [ -f "$DIST_DIR/windows/cfxlua-vm.exe" ]; then
41+
echo "Packaging Windows..."
42+
cp -r bin/cfxlua.bat "$DIST_DIR/windows/bin/"
43+
cp -r runtime/* "$DIST_DIR/windows/runtime/"
44+
cp install.bat "$DIST_DIR/windows/"
45+
46+
cd "$DIST_DIR/windows"
47+
zip -r "../../$WIN_PKG" .
48+
cd ../..
49+
fi
50+
51+
echo "-----------------------------------------------------------------------"
52+
echo "Release build complete!"
53+
echo "Assets generated:"
54+
[ -f "$LINUX_PKG" ] && echo " - $LINUX_PKG"
55+
[ -f "$WIN_PKG" ] && echo " - $WIN_PKG"
56+
echo "-----------------------------------------------------------------------"

0 commit comments

Comments
 (0)