From 65f135c25a3694545a441ea5a2de00a4d5365bbe Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 7 Jun 2026 05:09:08 +0200 Subject: [PATCH] feat(lua): standalone EdgeTX Lua compiler (#7275) Co-authored-by: Claude Opus 4.6 (1M context) --- radio/src/thirdparty/Lua/CMakeLists.txt | 61 ++++ radio/src/thirdparty/Lua/build-wasm.sh | 82 +++++ radio/src/thirdparty/Lua/src/luac.c | 5 +- radio/src/thirdparty/Lua/src/luac_wasm.c | 120 ++++++ radio/src/thirdparty/Lua/src/luaconf.h | 2 + radio/src/thirdparty/Lua/wasm/.gitignore | 2 + radio/src/thirdparty/Lua/wasm/edgetx-logo.png | Bin 0 -> 33881 bytes radio/src/thirdparty/Lua/wasm/index.html | 342 ++++++++++++++++++ 8 files changed, 612 insertions(+), 2 deletions(-) create mode 100644 radio/src/thirdparty/Lua/CMakeLists.txt create mode 100755 radio/src/thirdparty/Lua/build-wasm.sh create mode 100644 radio/src/thirdparty/Lua/src/luac_wasm.c create mode 100644 radio/src/thirdparty/Lua/wasm/.gitignore create mode 100644 radio/src/thirdparty/Lua/wasm/edgetx-logo.png create mode 100644 radio/src/thirdparty/Lua/wasm/index.html diff --git a/radio/src/thirdparty/Lua/CMakeLists.txt b/radio/src/thirdparty/Lua/CMakeLists.txt new file mode 100644 index 000000000..ffb3d67bb --- /dev/null +++ b/radio/src/thirdparty/Lua/CMakeLists.txt @@ -0,0 +1,61 @@ +cmake_minimum_required(VERSION 3.10) +project(edgetx-luac C) + +# Native host build of luac that produces bytecode compatible with +# EdgeTX's 32-bit Lua 5.3 configuration (float numbers, int integers). +# +# Usage: +# cmake -S radio/src/thirdparty/Lua -B build-luac +# cmake --build build-luac +# +# The resulting 'edgetx-luac' binary can compile scripts for any EdgeTX radio: +# edgetx-luac -s -o script.luac script.lua + +set(LUA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src) + +set(LUA_CORE_SRC + ${LUA_DIR}/lapi.c + ${LUA_DIR}/lcode.c + ${LUA_DIR}/lctype.c + ${LUA_DIR}/ldebug.c + ${LUA_DIR}/ldo.c + ${LUA_DIR}/ldump.c + ${LUA_DIR}/lfunc.c + ${LUA_DIR}/lgc.c + ${LUA_DIR}/llex.c + ${LUA_DIR}/lmem.c + ${LUA_DIR}/lobject.c + ${LUA_DIR}/lopcodes.c + ${LUA_DIR}/lparser.c + ${LUA_DIR}/lstate.c + ${LUA_DIR}/lstring.c + ${LUA_DIR}/ltable.c + ${LUA_DIR}/ltm.c + ${LUA_DIR}/lundump.c + ${LUA_DIR}/lvm.c + ${LUA_DIR}/lzio.c + ${LUA_DIR}/lauxlib.c +) + +add_executable(edgetx-luac + ${LUA_DIR}/luac.c + ${LUA_CORE_SRC} +) + +target_compile_definitions(edgetx-luac PRIVATE + LUA_HOST_BUILD + LUA_CROSS_COMPILER + LUA_COMPAT_5_2 +) + +target_include_directories(edgetx-luac PRIVATE ${LUA_DIR}) + +# Link math library on Unix +if(UNIX) + target_link_libraries(edgetx-luac m) +endif() + +set_target_properties(edgetx-luac PROPERTIES + OUTPUT_NAME edgetx-luac + C_STANDARD 99 +) diff --git a/radio/src/thirdparty/Lua/build-wasm.sh b/radio/src/thirdparty/Lua/build-wasm.sh new file mode 100755 index 000000000..c2f77fc7d --- /dev/null +++ b/radio/src/thirdparty/Lua/build-wasm.sh @@ -0,0 +1,82 @@ +#!/bin/bash +# +# Build edgetx-luac.wasm — a browser-ready WASM module that compiles +# Lua source to EdgeTX-compatible bytecode entirely in memory. +# +# Requirements: wasi-sdk (default /opt/wasi-sdk) +# +# Usage: +# cd radio/src/thirdparty/Lua +# ./build-wasm.sh +# +# The output edgetx-luac.wasm is placed in the current directory. + +set -euo pipefail + +WASI_SDK="${WASI_SDK:-/opt/wasi-sdk}" +CC="${WASI_SDK}/bin/clang" + +if [ ! -x "$CC" ]; then + echo "Error: wasi-sdk clang not found at $CC" >&2 + echo "Set WASI_SDK to your wasi-sdk installation path." >&2 + exit 1 +fi + +SRCDIR="$(cd "$(dirname "$0")/src" && pwd)" + +LUA_CORE_SRC=( + "$SRCDIR/lapi.c" + "$SRCDIR/lcode.c" + "$SRCDIR/lctype.c" + "$SRCDIR/ldebug.c" + "$SRCDIR/ldo.c" + "$SRCDIR/ldump.c" + "$SRCDIR/lfunc.c" + "$SRCDIR/lgc.c" + "$SRCDIR/llex.c" + "$SRCDIR/lmem.c" + "$SRCDIR/lobject.c" + "$SRCDIR/lopcodes.c" + "$SRCDIR/lparser.c" + "$SRCDIR/lstate.c" + "$SRCDIR/lstring.c" + "$SRCDIR/ltable.c" + "$SRCDIR/ltm.c" + "$SRCDIR/lundump.c" + "$SRCDIR/lvm.c" + "$SRCDIR/lzio.c" + "$SRCDIR/lauxlib.c" +) + +echo "Building edgetx-luac.wasm..." + +"$CC" \ + --target=wasm32-wasi \ + --sysroot="${WASI_SDK}/share/wasi-sysroot" \ + -Os \ + -ffunction-sections \ + -fdata-sections \ + -mllvm -wasm-enable-sjlj \ + -DLUA_HOST_BUILD \ + -DLUA_CROSS_COMPILER \ + -DLUA_COMPAT_5_2 \ + -I"$SRCDIR" \ + -mexec-model=reactor \ + -Wl,--gc-sections \ + -Wl,--strip-debug \ + -Wl,--export-dynamic \ + -Wl,-mllvm,-wasm-enable-sjlj \ + -nodefaultlibs -lc -lsetjmp \ + -o edgetx-luac.wasm \ + "$SRCDIR/luac_wasm.c" \ + "${LUA_CORE_SRC[@]}" + +SIZE=$(wc -c < edgetx-luac.wasm | tr -d ' ') +echo "Done: edgetx-luac.wasm (${SIZE} bytes)" + +# Show WASI imports (ideally very few / none needed at runtime) +if command -v wasm-objdump &>/dev/null; then + echo "" + echo "WASI imports:" + wasm-objdump -j Import -x edgetx-luac.wasm 2>/dev/null | grep wasi || echo " (none)" +fi diff --git a/radio/src/thirdparty/Lua/src/luac.c b/radio/src/thirdparty/Lua/src/luac.c index 67309d07a..388e96772 100644 --- a/radio/src/thirdparty/Lua/src/luac.c +++ b/radio/src/thirdparty/Lua/src/luac.c @@ -9,7 +9,9 @@ #include "lprefix.h" +#if defined(__GNUC__) || defined(__clang__) #include +#endif #include #include #include @@ -21,7 +23,6 @@ #include "lualib.h" #include "lauxlib.h" #include "ldebug.h" -#include "lnodemcu.h" #include "lobject.h" #include "lstate.h" #include "lstring.h" @@ -163,7 +164,7 @@ static int pmain(lua_State *L) { if (argc == 0) return 0; for (i = 0; i < argc; i++) { - const char *filename = IS("-") ? NULL : filelist[i]; + const char *filename = IS("-") ? NULL : argv[i]; if (luaL_loadfile(L, filename) != LUA_OK) fatal(lua_tostring(L, -1)); } diff --git a/radio/src/thirdparty/Lua/src/luac_wasm.c b/radio/src/thirdparty/Lua/src/luac_wasm.c new file mode 100644 index 000000000..14d16633e --- /dev/null +++ b/radio/src/thirdparty/Lua/src/luac_wasm.c @@ -0,0 +1,120 @@ +/* +** EdgeTX Lua cross-compiler — WASM entry point +** +** Exposes a minimal API for compiling Lua source to bytecode entirely +** in memory, suitable for running in a browser via WebAssembly. +** +** Exported functions: +** compile(src_ptr, src_len, strip) → positive length on success, negative on error +** get_output_ptr() → pointer to compiled bytecode +** get_error_ptr() → pointer to error message string +** get_error_len() → length of error message +** wasm_malloc(size) → allocate memory (for JS to write source into) +** wasm_free(ptr) → free allocated memory +*/ + +#define luac_c +#define LUA_CORE + +#include "lprefix.h" + +#include +#include + +#include "lua.h" +#include "lauxlib.h" + +/* --------------- output buffer --------------- */ + +static unsigned char *out_buf; +static size_t out_len; +static size_t out_cap; + +static int writer(lua_State *L, const void *p, size_t size, void *ud) { + (void)L; (void)ud; + if (out_len + size > out_cap) { + size_t new_cap = out_cap ? out_cap * 2 : 4096; + while (new_cap < out_len + size) + new_cap *= 2; + unsigned char *nb = realloc(out_buf, new_cap); + if (!nb) return 1; + out_buf = nb; + out_cap = new_cap; + } + memcpy(out_buf + out_len, p, size); + out_len += size; + return 0; +} + +/* --------------- error message --------------- */ + +static char error_msg[512]; +static int error_len; + +/* --------------- exported API --------------- */ + +#define EXPORT __attribute__((export_name(#name))) +/* clang wasm export attribute helper */ +#define WASM_EXPORT(name) __attribute__((export_name(#name))) name + +/* +** Compile Lua source to bytecode. +** Returns the bytecode length (>0) on success, or a negative error code: +** -1 could not create Lua state +** -2 syntax / compile error (call get_error_ptr/len for message) +** -3 bytecode dump failed +*/ +int WASM_EXPORT(compile)(const char *source, int source_len, int strip) { + error_msg[0] = '\0'; + error_len = 0; + + /* reset output */ + free(out_buf); + out_buf = NULL; + out_len = 0; + out_cap = 0; + + lua_State *L = luaL_newstate(); + if (!L) return -1; + + int status = luaL_loadbuffer(L, source, (size_t)source_len, "input"); + if (status != LUA_OK) { + const char *err = lua_tostring(L, -1); + if (err) { + size_t n = strlen(err); + if (n >= sizeof(error_msg)) n = sizeof(error_msg) - 1; + memcpy(error_msg, err, n); + error_msg[n] = '\0'; + error_len = (int)n; + } + lua_close(L); + return -2; + } + + /* The compiled chunk is a function at the top of the stack. + * lua_dump serialises it via the writer callback. */ + status = lua_dump(L, writer, NULL, strip); + lua_close(L); + + return status == 0 ? (int)out_len : -3; +} + +unsigned char *WASM_EXPORT(get_output_ptr)(void) { + return out_buf; +} + +char *WASM_EXPORT(get_error_ptr)(void) { + return error_msg; +} + +int WASM_EXPORT(get_error_len)(void) { + return error_len; +} + +void *WASM_EXPORT(wasm_malloc)(int size) { + return malloc((size_t)size); +} + +void WASM_EXPORT(wasm_free)(void *ptr) { + free(ptr); +} diff --git a/radio/src/thirdparty/Lua/src/luaconf.h b/radio/src/thirdparty/Lua/src/luaconf.h index 4f679b032..15c53762d 100644 --- a/radio/src/thirdparty/Lua/src/luaconf.h +++ b/radio/src/thirdparty/Lua/src/luaconf.h @@ -462,10 +462,12 @@ #undef lua_str2number #define lua_str2number(s,p) ((lua_Number)strtod((s), (p))) +#if !defined(LUA_HOST_BUILD) // For print #include "debug.h" #define lua_writestring(s,l) TRACE_DEBUG_WP("%s", s); #define lua_writeline() TRACE_DEBUG_WP("\n"); #define lua_writestringerror(s,p) TRACE_DEBUG_WP(s, p); +#endif #endif diff --git a/radio/src/thirdparty/Lua/wasm/.gitignore b/radio/src/thirdparty/Lua/wasm/.gitignore new file mode 100644 index 000000000..b9f02c05d --- /dev/null +++ b/radio/src/thirdparty/Lua/wasm/.gitignore @@ -0,0 +1,2 @@ +.wrangler +*.wasm diff --git a/radio/src/thirdparty/Lua/wasm/edgetx-logo.png b/radio/src/thirdparty/Lua/wasm/edgetx-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..9c5aca4af7940fe78ce69a985496c590ecfcdbe1 GIT binary patch literal 33881 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 G!T$%70q2zf literal 0 HcmV?d00001 diff --git a/radio/src/thirdparty/Lua/wasm/index.html b/radio/src/thirdparty/Lua/wasm/index.html new file mode 100644 index 000000000..1238b779d --- /dev/null +++ b/radio/src/thirdparty/Lua/wasm/index.html @@ -0,0 +1,342 @@ + + + + + +EdgeTX Lua Compiler + + + + + + +
+ EdgeTX +

Lua Compiler

+
+

Compile Lua scripts to EdgeTX bytecode — runs entirely in your browser

+ +
+ + +
+ + +
+ + +
+
+ +
+
+ +
+ + + +