feat(runtime): embed platform modules as bytecode
ui.lua and hints.lua are compiled to LUA_32BITS bytecode (matching the firmware's Lua build) and linked into the binary. A new package.searchers entry checks them as the fallback after the SD card, so a local /.lua/lib/ui.lua still shadows the packaged one for debugging. Bytecode is ~40% smaller than source and loads without parsing. A fresh SD card with no make sdcard now has the platform available.
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace esp32lua {
|
||||
|
||||
// A platform module compiled to bytecode and linked into the firmware. The module searcher
|
||||
// tries the SD card first, so a local copy shadows the packaged one.
|
||||
struct EmbeddedModule {
|
||||
const char* name;
|
||||
const unsigned char* data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
extern const EmbeddedModule embedded_modules[];
|
||||
extern const size_t embedded_modules_count;
|
||||
|
||||
} // namespace esp32lua
|
||||
@@ -128,6 +128,7 @@ class Runtime {
|
||||
bool loadScript(const std::string& path);
|
||||
void installLoader(const std::string& appDir);
|
||||
static int searchModule(lua_State* state);
|
||||
static int searchEmbedded(lua_State* state);
|
||||
static int loadFile(lua_State* state);
|
||||
|
||||
// A batch is one visit to the app, however many callbacks it fans out into: a tap fires
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -2,6 +2,9 @@
|
||||
// mount, so every path into the filesystem goes through FsProvider instead.
|
||||
|
||||
#include <lua/runtime.h>
|
||||
#include <lua/embedded_modules.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
extern "C" {
|
||||
#include "lauxlib.h"
|
||||
@@ -82,6 +85,22 @@ int Runtime::searchModule(lua_State* state) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Runtime::searchEmbedded(lua_State* state) {
|
||||
const char* name = luaL_checkstring(state, 1);
|
||||
for (size_t i = 0; i < embedded_modules_count; i++) {
|
||||
if (std::strcmp(name, embedded_modules[i].name) != 0) continue;
|
||||
const std::string chunkname = std::string("=") + name;
|
||||
if (luaL_loadbuffer(state, reinterpret_cast<const char*>(embedded_modules[i].data),
|
||||
embedded_modules[i].size, chunkname.c_str()) != LUA_OK) {
|
||||
return luaL_error(state, "error loading embedded module '%s': %s", name, lua_tostring(state, -1));
|
||||
}
|
||||
lua_pushstring(state, name);
|
||||
return 2;
|
||||
}
|
||||
lua_pushfstring(state, "\n\tno embedded module '%s'", name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Runtime::loadFile(lua_State* state) {
|
||||
Runtime* runtime = Runtime::from(state);
|
||||
if (load(state, *runtime->providers_.fs, luaL_checkstring(state, 1)) == LUA_OK) return 1;
|
||||
@@ -102,10 +121,12 @@ void Runtime::installLoader(const std::string& appDir) {
|
||||
lua_getfield(state_, -1, "searchers");
|
||||
lua_pushcfunction(state_, searchModule);
|
||||
lua_rawseti(state_, -2, 2);
|
||||
for (int at = 3; at <= 4; at++) {
|
||||
lua_pushnil(state_);
|
||||
lua_rawseti(state_, -2, at);
|
||||
}
|
||||
// Embedded bytecode is the fallback after the SD card, so a local /.lua/lib/ui.lua shadows
|
||||
// the packaged one without reflashing.
|
||||
lua_pushcfunction(state_, searchEmbedded);
|
||||
lua_rawseti(state_, -2, 3);
|
||||
lua_pushnil(state_);
|
||||
lua_rawseti(state_, -2, 4);
|
||||
lua_pop(state_, 2);
|
||||
|
||||
lua_pushcfunction(state_, loadFile);
|
||||
|
||||
Reference in New Issue
Block a user