name: luamake
description: Luamake 构建系统指南——用于当前项目的 luamake / make.lua / Ninja 生成流程。当用户需要编写、修改、排查或理解 make.lua、目标定义、lm:conf、deps / objdeps、代码生成、Lua C 模块、Bee 运行时集成,或需要解决当前项目中由 luamake 驱动的构建问题时,使用此 skill。即使用户没有明确提到 luamake,但上下文明显是在处理本项目的构建脚本、构建目录、目标依赖或 luamake 生成的 Ninja 流程,也应使用此 skill。不要把它用于纯通用的 C/C++ 编译知识、与本项目无关的 CMake / xmake / Bazel / Meson 问题,或仅讨论编译器理论而未涉及 luamake / make.lua 的请求。
Luamake Build System
基于 Lua 的构建系统,生成 Ninja 构建文件。
快速开始
local lm = require "luamake"
lm:exe "myapp" {
sources = { "src/*.c", "!src/test.c" },
includes = "include",
defines = { "DEBUG", "VERSION=1.0" },
}
luamake # 构建
luamake clean # 清理
luamake rebuild # 重建
目标类型
| API | 说明 | 输出 |
|---|---|---|
lm:exe | 可执行文件 | app.exe / app |
lm:dll | 动态库 | lib.dll / lib.so / lib.dylib |
lm:lib | 静态库 | lib.lib / lib.a |
lm:source_set | 源码集(不链接,用于复用,通过 deps 引用) | 无 |
lm:lua_src | Lua C 模块(静态嵌入到 lm:lua_exe) | 无 |
lm:lua_dll | Lua C 模块(动态加载) | module.dll / module.so |
lm:lua_exe | 内嵌 Lua 的可执行文件 | app.exe / app |
lm:lua_embed | Lua 嵌入资源(按命名组嵌入 Lua 文件,生成 source_set;自动导出 includes/objdeps) | 无(source_set) |
lm:phony | 伪目标(聚合依赖) | 无 |
目标属性
源文件
| 属性 | 说明 | 示例 |
|---|---|---|
sources | 源文件 | "src/*.cpp", { "a.cpp", "b.cpp" } |
includes | 包含目录 | "include", { "include", "3rd" } |
sysincludes | 系统包含目录(抑制警告) | "/usr/local/include" |
defines | 预处理器定义 | { "DEBUG", "VER=1" } |
objdeps | 对象依赖(编译前必须生成) | "generated_header" |
objdeps用法:当源文件依赖代码生成产物(如生成的头文件)时,需用objdeps声明依赖的目标名,确保生成步骤在编译前完成。deps只控制链接顺序,不能保证编译前生成文件。lm:rule "gen_header" { ... } -- 生成头文件的规则 lm:exe "app" { sources = "src/*.cpp", objdeps = "gen_header", -- 编译 src/*.cpp 前先执行 gen_header }注意:
lm:lua_embed目标会自动导出includes和objdeps,通过deps依赖它的目标无需手动声明这两项。详见下方lm:lua_embed用法。
链接
| 属性 | 说明 | 示例 |
|---|---|---|
links | 链接库 | { "pthread", "ws2_32" } |
linkdirs | 库搜索目录 | "lib", { "lib", "/usr/lib" } |
ldflags | 链接器标志 | "-Wl,--as-needed" |
frameworks | macOS/iOS 框架 | { "Foundation", "Cocoa" } |
deps | 目标依赖 | "lib1", { "lib1", "lib2" } |
编译
| 属性 | 说明 | 示例 |
|---|---|---|
flags | 编译器标志 | { "-Wall", "-O2" } |
cflags | C 编译器标志 | "-std=c11" |
cxxflags | C++ 编译器标志 | "-std=c++20" |
confs | 引用命名配置 | "myconfig" |
注意:
cflags/cxxflags直接传递给编译器命令行。在lm:conf中可用c = "c11"/cxx = "c++20"作为简写,luamake 会自动转换为对应编译器的标准标志(如 MSVC 的/std:c11)。
特殊目标用法
lm:source_set — 将源文件组织为可复用的源码集,通过 deps 引用,不单独链接:
-- 定义共享源码集
lm:source_set "common" {
includes = "include",
sources = { "src/common/*.cpp" },
}
-- 多个目标复用同一组源文件
lm:exe "app1" { deps = "common", sources = "src/app1.cpp" }
lm:exe "app2" { deps = "common", sources = "src/app2.cpp" }
lm:lua_src — 将 Lua C 模块静态嵌入到 lm:lua_exe 中:
lm:lua_src "mymodule" {
sources = "src/mymodule.c",
}
lm:lua_exe "app" {
deps = "mymodule",
sources = "src/main.cpp",
}
lm:lua_embed — 将 Lua 文件按命名组嵌入到 C 源码中,生成一个 source_set 供其他目标依赖。data 下每个 key 是一个组,组名直接成为生成的 lua_embed_bundle 结构体的字段名。每组可独立设置 bytecode = true。bee_glue = true 启用 bee 胶水层,约定 data.preload 注入 _PRELOAD、data.main[1] 作为入口。自动向依赖方导出 includes 和 objdeps,通过 deps 依赖时无需手动声明。完整规则(分组语义、pattern 语法、字节码取舍、bee_glue 契约、无胶水时的接入姿势)见 references/advanced/lua_embed.md:
lm:lua_embed "myembed" {
bee_glue = true,
data = {
main = { bytecode = true, "src/main.lua" },
preload = { bytecode = true, { dir = "lualib" } },
data = { { name = "config.json", file = "assets/config.json" } },
},
}
lm:lua_src "glue" {
deps = "myembed", -- 自动获取 includes 和 objdeps
includes = "3rd/bee.lua",
sources = "src/glue.cpp",
}
lm:lua_exe "app" { deps = { "glue", "myembed" }, sources = "src/main.cpp", }
**`lm:phony`** — 聚合多个目标为一个命名依赖,方便统一引用:
```lua
lm:phony "all_libs" {
deps = { "libfoo", "libbar", "libqux" },
}
lm:exe "app" {
deps = "all_libs",
sources = "main.cpp",
}
配置 (lm:conf)
lm:conf 有两种用法,行为完全不同,不要混淆:
匿名配置:lm:conf { ... } — 立即生效,影响全局
不带名称调用时,属性立即应用到当前工作区的所有后续目标,相当于设置全局默认值。
-- 所有参数均为可选,按项目实际需要填写
lm:conf {
c = "c11", -- C 标准:"c89", "c99", "c11", "c17"
cxx = "c++20", -- C++ 标准:"c++11", "c++14", "c++17", "c++20"
visibility = "hidden", -- 符号可见性:"hidden"(默认隐藏)或 "default"(默认可见)
}
-- 以下目标自动继承上面的配置
lm:exe "app1" { sources = "src/app1.cpp" }
lm:exe "app2" { sources = "src/app2.cpp" }
适用场景:项目中大部分目标共享相同的编译标准、模式等基础配置时使用。
命名配置:lm:conf "name" { ... } — 按需引用,不自动生效
带名称调用时,属性不会立即生效,仅存储起来,需要目标通过 confs 属性显式引用。
-- 定义命名配置(不会自动应用到任何目标)
lm:conf "mylib" {
defines = "MYLIB_API",
includes = "3rd/mylib",
}
-- 通过 confs 引用,只有这个目标会使用该配置
lm:exe "app" {
confs = "mylib",
sources = "main.cpp",
}
适用场景:多个目标需要共享同一组特定配置(如第三方库的头文件路径和宏定义),但不希望污染全局时使用。
如何选择
| 场景 | 用法 |
|---|---|
| 设置项目范围的 C/C++ 标准、构建模式等 | lm:conf { ... } |
| 为特定的几个目标共享一组 includes/defines | lm:conf "name" { ... } + confs = "name" |
| 只有一个目标需要特定配置 | 直接写在目标属性里,无需 conf |
内置变量
路径变量
| 变量 | 说明 | 示例 |
|---|---|---|
$builddir | 构建目录(默认 build,可自定义) | build |
$bindir | 二进制输出目录 | build/bin |
$objdir | 对象文件目录 | build/obj |
$bin | $bindir 别名 | |
$obj | $objdir 别名 | |
$in | 输入文件 (规则中) | |
$out | 输出文件 (规则中) |
自定义构建目录:当项目已使用
build目录时,可在脚本开头修改构建目录:lm.builddir = "_build" -- 构建产物将输出到 _build/ 目录
$bindir和$objdir默认基于$builddir,修改后会自动跟随变化。
全局变量
| 变量 | 说明 | 示例值 |
|---|---|---|
lm.os | 目标 OS | "windows", "linux", "macos", "ios", "android" |
lm.compiler | 编译器 | "msvc", "gcc", "clang" |
lm.arch | 架构 | "x86_64", "x86", "arm64" |
lm.mode | 构建模式 | "debug", "release" |
lm.workdir | 工作目录 | 项目根目录 |
开发工作流
编写或修改 make.lua 构建脚本后,必须运行构建命令验证脚本的正确性:
# 1. 运行构建,验证脚本是否有语法错误或配置问题
luamake
# 2. 如果构建失败,根据错误信息修复脚本后重新运行
luamake
# 3. 如果需要从干净状态重建(排除增量构建的干扰)
luamake rebuild
注意事项
- Windows 平台:必须使用 PowerShell 运行
luamake命令,不要使用 Git Bash。 - 每次修改
make.lua后都要运行luamake确认构建成功,不要只写脚本不验证。 - 关注构建输出中的警告和错误信息,它们通常指向配置问题(如路径错误、缺少依赖等)。
- 如果构建失败,优先分析错误信息,修复后再次运行验证,直到构建通过。
最佳实践
| 主题 | 文档 | 包含内容 |
|---|---|---|
| 依赖管理 | references/best_practices/bp_dependency.md | deps 定义顺序、源码集复用、增量源码集、动态模块发现 |
| 条件编译与静态分析 | references/best_practices/bp_compilation.md | 条件编译、静态分析集成 |
| 代码生成与 objdeps | references/best_practices/bp_codegen.md | 代码生成管道、objdeps 用法 |
| Lua 模块与测试 | references/best_practices/bp_lua_and_test.md | Lua C 模块、内置测试框架 |
其他详细文档
| 主题 | 文档 |
|---|---|
| Bee 运行时库(API 参考来源、模块列表、Meta 文件用法) | references/advanced/bee_runtime.md |
lm:lua_embed 权威参考(分组 / pattern / bytecode / bee_glue / 自定义接入) | references/advanced/lua_embed.md |
Bee 运行时库
luamake lua script.lua 运行脚本时预加载 bee 库。API 参考来源及模块列表详见 references/advanced/bee_runtime.md。
适用边界
优先在以下场景使用本 skill:
- 当前仓库明确使用
luamake或通过make.lua定义构建目标。 - 用户正在修改
make.lua、排查luamake报错,或理解deps、objdeps、lm:conf、目标类型、构建目录等机制。 - 用户讨论的问题与当前项目的 Ninja 生成流程、Bee 集成或 Lua C 模块构建直接相关。
以下场景通常不应使用本 skill:
- 与当前项目无关的通用 C/C++ 编译、链接、优化理论问题。
- 纯
CMake、xmake、Bazel、Meson等其他构建系统的问题。 - 只是在问编译器语法、语言标准或平台 API,而没有落到
luamake/make.lua的构建脚本上。
故障排除
| 问题 | 解决方案 |
|---|---|
| "no source files found" | 检查 glob 模式,确认 rootdir,检查文件扩展名 |
| Windows 链接错误 | 添加系统库:links = { "ws2_32", "iphlpapi", "user32" } |
| 交叉编译问题 | 使用平台特定配置,检查 lm.compiler |
| 缺少生成文件 | 添加 objdeps 确保生成后再编译 |
build 目录冲突 | 项目已使用 build 目录时,用 lm.builddir = "_build" 修改构建目录 |
| 找不到头文件 | 检查 includes 路径,使用绝对路径或 $builddir |
| Ninja 构建失败 | 删除 build/ 目录重新构建 |