Water-Run/luainstaller
GitHub: Water-Run/luainstaller
将 Lua 项目及其依赖(含原生 C 模块)打包为跨平台独立可执行文件的分发工具。
Stars: 5 | Forks: 0
# Lua installer
*[中文](README-zh.md)*
`luainstaller` 是一个将 Lua 项目打包为**可分发执行文件**的工具。它为同平台或特定配置的构建实现了 Linux、macOS 和 Windows 的 `--onedir` 输出,并将 `--onefile` 构建实现为遵循相同运行时契约的自解压包装器。目前的本地和实验脚本验证了所选示例矩阵中的 Linux、macOS 和 Windows 的 `--onedir` 和 `--onefile` 打包结果。该项目已在 [GitHub](https://github.com/Water-Run/luainstaller) 上开源,并采用 **LGPL** 授权。
`luainstaller` 提供了依赖分析和同平台目录打包功能,
并能在包装器程序中打包非纯 Lua 内容。
需要注意的是,`luainstaller` 保证打包后的二进制文件
能够在与您相同的**系统环境**中运行。经过验证的 Linux、macOS 或 Windows
打包结果不需要单独的 `lua` 命令,但系统
ABI 和原生库的兼容性仍然非常重要。
## 安装
通过 `luarocks` 安装:
```
luarocks install luainstaller
```
当 LuaRocks 不可用时,从源码检出版本安装:
```
sh tools/install-source.sh --prefix "$HOME/.local"
export PATH="$HOME/.local/bin:$PATH"
luai --help
```
此源码安装程序只需要 `lua` 命令。构建 `--onedir` 或 `--onefile` 包
仍然需要本地 C 工具链和 Lua 开发元数据。Linux 使用
`cc`、Lua 头文件以及用于 Lua 的 `pkg-config` 数据。macOS 使用
`cc` 以及一个提供 Lua 头文件和 `liblua.a` 的匹配 Lua 前缀。Windows 包
是在 Linux 主机上使用 MinGW 和包含 Lua 头文件以及 `lua54.dll` 的 Windows Lua 前缀构建的。
## 用法
`luainstaller` 可作为 CLI 工具使用,也可直接从 Lua 脚本中调用。
### 命令行工具 (CLI)
CLI 命令名称:`luai`。
```
luai --help
luai -a test/student_management_system/main.lua
luai -t test/student_management_system/main.lua
luai -c --onedir test/student_management_system/main.lua -o build/student-manager
luai -c --onefile test/runtime_bundle/main.lua -o build/runtime-onefile
```
当前命令状态:
| 命令 | 状态 | 描述 |
|---------|--------|-------------|
| `luai -a ` | 已实现 | 分析 Lua 和原生模块依赖。 |
| `luai -t ` | 已实现 | 打印分析器跟踪记录,以及针对相同 OS、架构、ABI 和 Lua ABI 边界的兼容性诊断。 |
| `luai -c ` | 已在经验证的示例矩阵中实现 Linux、macOS 和 Windows 的 `--onedir` 和 `--onefile` | 构建带有启动器、清单、内嵌 Lua payload 和所拷贝的原生 Lua C 模块的目录包或自解压单文件包。 |
常用选项:
| 选项 | 描述 |
|--------|-------------|
| `--onedir` | 目录打包模式。这是默认的输出模式。 |
| `--onefile` | 自解压单文件打包模式。 |
| `-o, --out ` | 打包操作的输出路径。 |
| `--include ` | 手动包含一个依赖;可重复使用。 |
| `--exclude ` | 按路径或 basename 排除依赖;可重复使用。 |
| `--target-os ` | 选择目标 profile:`linux`、`macos` 或 `windows`。 |
| `--lua-prefix ` | 需要显式指定头文件/运行时文件的目标所使用的 Lua 前缀。 |
| `--require-engine ` | 依赖发现引擎:`static`、`manual` 或 `runtime`。 |
| `--no-depscan` | 禁用自动依赖扫描。 |
| `--max-deps ` | 最大依赖数量,默认为 `36`。 |
| `--verbose` | 在可用时请求更详细的输出。 |
### Lua API
Lua API 使用与 CLI 相同的参数语义。默认启用依赖扫描;设置 `depscan = false` 以禁用它。
```
local luainstaller = require("luainstaller")
```
#### 结构化结果
公共 API 返回结果表,而不是在遇到普通用户错误时抛出异常。
```
local analyzed = luainstaller.analyze({
entry = "test/student_management_system/main.lua",
max_deps = 250,
})
if analyzed.ok then
print(#analyzed.dependencies.scripts)
else
io.stderr:write(analyzed.error.type .. ": " .. analyzed.error.message .. "\n")
end
```
可用函数:
| 函数 | 状态 | 返回结构 |
|----------|--------|--------------|
| `luainstaller.analyze(opts)` | 已实现 | `{ ok = true, action = "analyze", dependencies = { scripts = {}, libraries = {} } }` |
| `luainstaller.trace(opts)` | 已实现 | 包含发起文件、源码行号、候选项、分类、原因以及 `compatibility` 摘要的真实分析器跟踪记录。 |
| `luainstaller.compatibility(opts)` | 已实现 | 针对目标 profile、Lua ABI、启动器 profile 以及已知原生库风险的兼容性诊断。 |
| `luainstaller.bundle(opts)` | 已在经验证的示例矩阵中实现 Linux、macOS 和 Windows 的 `mode = "onedir"` 和 `mode = "onefile"` | 返回 `{ ok = true, action = "bundle", executable = "...", manifest = { ... } }`。 |
常用 `opts` 字段:
| 字段 | 类型 | 默认值 | 描述 |
|-------|------|---------|-------------|
| `entry` | string | 必填 | 入口脚本路径。 |
| `mode` | string | `"onedir"` | `onedir` 或 `onefile`。 |
| `out` | string | nil | `onedir` 的输出目录路径;`onefile` 的输出可执行文件路径。 |
| `max_deps` | number | `36` | 最大依赖数量。 |
| `include` | string[] | `{}` | 要额外包含的文件。 |
| `exclude` | string[] | `{}` | 要排除的路径或 basename。 |
| `depscan` | boolean | `true` | 设置为 `false` 则仅使用手动依赖。 |
| `require_engine` | string | `"static"` | 依赖引擎:`static`、`manual` 或 `runtime`;`depscan = false` 相当于 `manual`。 |
| `run_args` | string[] | `{}` | 在 `require_engine = "runtime"` 发现阶段传递给入口脚本的参数。 |
| `target_os` | string | 主机 OS | 目标 profile:`linux`、`macos` 或 `windows`。 |
| `lua_prefix` | string | `LUAI_LUA_PREFIX` | 用于 macOS 和 Windows profile 的 Lua 头文件/运行时前缀。 |
## 工作原理
目前的工作流程是:**分析入口脚本 → 收集依赖 → 跟踪
解析决策 → 构建同平台 onedir 或 onefile 包**。
Linux、macOS 和 Windows 的 `--onedir` 和 `--onefile` 输出已在验证过的
示例矩阵中实现。打包器生成一个 C 启动器,写入
`.luai/manifest.lua`,将 Lua payload 嵌入到启动器中,并将检测到的
原生 Lua C 模块拷贝到 `.luai/native/` 中。Linux 使用共享 Lua 启动器并
拷贝链接的 Lua 共享运行时。macOS 将启动器与来自所选 Lua 前缀的静态
`liblua.a` 进行链接。Windows 使用
`x86_64-w64-mingw32-gcc`,生成一个 `.exe`,并将 `lua54.dll` 拷贝到启动器旁边以及 `.luai/native/` 中。兼容性边界为:相同的 OS、相同的
架构、相同的 ABI 以及相同的 Lua ABI。
`--onefile` 首先会暂存相同的 onedir 布局,将这些文件嵌入到原生
提取器中,并在运行用户代码之前,在启动内部可执行文件之前将它们写入到内容寻址的缓存目录中。
这保留了原生 Lua C 模块和 Lua 运行时的行为,因为 `.so`、`.dylib` 和 `.dll` 文件在用户代码运行之前就已经存在于磁盘上了。如果现有解压文件的大小和内容哈希与内嵌的 payload 匹配,则会复用这些文件。
通用的交叉构建和自动外部共享库依赖闭包仍然是后续路线图的工作。
依赖发现是可选的。`static` 使用分析器,`manual` 仅使用显式包含项,而 `runtime` 在跟踪实际 `require` 调用的同时运行一次入口脚本。运行时发现仅涵盖在该构建期运行期间执行的代码路径。
有关详细的实现说明、非纯 Lua 行为、验证命令和当前限制,请参阅
[`docs/LINUX-ONEDIR-BUNDLING.md`](docs/LINUX-ONEDIR-BUNDLING.md)。
有关跨 Linux、macOS 和 Windows 主机的实验结果,请参阅
[`docs/CROSS-PLATFORM-TEST-MATRIX.md`](docs/CROSS-PLATFORM-TEST-MATRIX.md)。
纯 Lua 运行时里程碑已实现:`luainstaller.runtime` 可以安装
打包好的模块搜索器,并且 `luainstaller.cgen` 可以为纯 Lua payload 生成 Lua bootstrap chunk。这个 bootstrap 被生成的 C 启动器嵌入。
C 启动器模板里程碑已实现:`luainstaller.launcher` 可以生成嵌入 Lua bootstrap 并通过 Lua C API 执行它的共享 Lua C 源码。
打包器使用此生成器在输出目录中生成可执行文件。
整个过程可概括为:
```
[entry.lua]
|
v
[Dependency Analysis: static / manual / runtime]
|
v
[Collect Lua files / manual --include / --exclude]
|
v
[Generate C launcher / copy native modules / write manifest]
|
v
[Linux, macOS, or Windows onedir or onefile bundle]
```
标签:Gophish, Lua, rizin, SOC Prime, 开发工具, 打包工具, 编译器