Xmake v3.1.1 发布,Addons 扩展 Xmake 自身
在此版本中,我们新增了 addons 扩展支持。上个版本我们重构了 xmake plugin,让插件可以像包一样分发,而 addons 把这件事做得更彻底:一个 addon 不仅可以携带插件,还能携带规则、工具链、工程模板、lua 模块和 includes 文件,相当于一整套开发工具包,一条命令就能装好,也可以由工程声明后自动安装。
此外,我们还新增了 package.host.install_locally 策略和一批新的交叉编译架构,重构了模板的分发方式,并且新增了 BSD 上的 pkg 包管理器支持。
新特性介绍
Addons 扩展支持
我们平时用的包,提供的是程序要链接的库,而 addon 扩展的是 xmake 本身,给构建工具增加新的能力。
一个 addon 可以提供什么
下面这几类扩展内容都是可选的,addon 提供哪些就带哪些:
| 目录 | 提供的能力 | 使用方式 |
|---|---|---|
plugins/ | 新的 xmake 命令 | xmake hello |
rules/ | 构建规则 | add_rules("@addon/my-addon/app") |
toolchains/ | 工具链 | set_toolchains("@addon/my-addon/mycc") |
templates/ | 工程模板 | xmake create -t myapp |
modules/ | 可导入的 lua 模块 | import("@addon.my-addon.utils") |
includes/ | 可包含的配置片段 | includes("@addon/my-addon/board") |
这些扩展内容都是带命名空间的,统一通过 @addon/<name>/... 来引用,所以两个 addon 即使提供了同名的规则也不会冲突。只有插件和模板是例外,因为命令名和模板 id 是全局的,如果安装的 addon 会覆盖掉别的 addon 的命令,xmake 会直接拒绝。
addon 的管理
$ xmake addon --install my-addon # 从仓库索引安装
$ xmake addon --install github:myrepo/my-addon # 从 github 安装,支持 `#branch`
$ xmake addon --install https://github.com/user/repo.git # 从任意 git url 安装
$ xmake addon --install /path/to/my-addon # 从本地目录安装
$ xmake addon --list
$ xmake addon --search my
$ xmake addon --remove my-addon
$ xmake addon --upgrade在工程里声明
工程也可以直接声明自己需要哪些 addon,这样别人克隆下来就不用手动安装了,加载工程的时候,xmake 会自动把缺失的 addon 拉下来:
add_addons("my-addon 1.0.x")
includes("@addon/my-addon/board")
target("hello")
add_rules("@addon/my-addon/app")
add_files("src/*.c")最终解析出来的版本会记录到 xmake.lua 同级目录下的 xmake-addons.lock 中,保证团队里每个人构建时用的都是同一批版本。
编写 addon
一个 addon 其实就是一个目录,一份 manifest 加上若干扩展目录,不需要编译,也不需要注册:
my-addon/
├── addon.lua
└── src/
├── plugins/hello/
├── rules/app/
├── toolchains/mycc/
├── modules/
├── includes/board/
└── templates/c/foo/-- addon.lua
addon("my-addon")
set_homepage("https://github.com/me/my-addon")
set_description("这个 addon 的功能描述")
set_license("Apache-2.0")
set_sourcedir("src")
add_deps("serial-tools")addon 的名字是在 manifest 里自己定的,跟仓库名、跟分发它的包名都没有关系。而在 addon 内部,引用自己的东西统一用 @self:
import("@self.private.board")开发的时候,可以直接从本地目录安装来测试,走的是和用户完全一样的安装流程:
$ xmake addon --install .
$ xmake addon --remove my-addon提交到 xmake-repo
addon 放在 addons/<首字母>/<name>/xmake.lua 下,和 C/C++ 包平级,版本管理、sha256 校验、依赖、镜像下载这些包已有的能力,addon 都可以直接复用:
package("my-addon")
set_kind("addon")
set_homepage("https://github.com/me/my-addon")
set_description("这个 addon 的功能描述")
set_license("Apache-2.0")
add_urls("https://github.com/me/my-addon/archive/refs/tags/$(version).tar.gz",
"https://github.com/me/my-addon.git")
add_versions("v1.0.0", "<sha256>")
add_deps("serial-tools", {kind = "addon"})
on_test(function (package)
assert(package:has_addon({rules = "app", toolchains = "mycc"}))
end)相关接口
addon 相关的接口不多,主要就是下面三个地方:
-- 1. 在 xmake.lua 中,声明工程需要哪些 addon
add_addons("my-addon 1.0.x")-- 2. 在 addon.lua 中,声明这个 addon 自身的信息
addon("my-addon")
set_description("...") -- `xmake addon --list` 会显示
set_homepage("...")
set_license("Apache-2.0")
set_sourcedir("src") -- 仓库内存放扩展目录的根目录
add_deps("serial-tools") -- 依赖的其他 addon
add_globalmodules("detect.tools.find_mytool") -- 只有需要被 xmake 按名字查找的模块才用得上-- 3. 在 xmake-repo 的包配置中,声明它如何分发
package("my-addon")
set_kind("addon")
add_versions("v1.0.0", "<sha256>")
add_deps("serial-tools", {kind = "addon"})
on_test(function (package)
assert(package:has_addon({rules = "app", toolchains = "mycc"}))
end)如果要在脚本里查询运行期的信息,可以用 core.package.addon 模块:
import("core.package.addon")
addon.owner() -- 当前脚本属于哪个 addon
addon.addons() -- 已安装的 addon 及其提供的扩展
addon.versions("yaml") -- 某个 addon 已安装的版本
addon.installdir() -- ~/.xmake/addons为什么要带命名空间
addon 提供的所有东西,都要通过 @addon/<name>/... 或者 @addon.<name>.<module> 来访问,不存在直接用裸名字引用的情况。这样一来,两个 addon 各自提供一个叫 app 的规则也不会有任何问题。真正全局的只有命令名和模板 id,所以我们在安装时也只检查这两类的冲突。
而在 addon 自己的代码里,一律用 @self 引用自身,addon 就不用把自己的名字硬编码进去,以后换个仓库、改个名字,内部代码都不用动。
addon 可以自带包定义
工具链类的 addon 通常还需要对应的二进制工具,与其让用户自己去装,不如让 addon 把包定义一起带上,再通过 includes 文件暴露给工程:
-- src/includes/packages/xmake.lua
package("mycc")
set_kind("toolchain")
add_urls("https://.../mycc-$(version).tar.gz")
add_versions("1.0.0", "<sha256>")
on_install(function (package)
os.cp("*", package:installdir())
end)
package_end()-- src/includes/board/xmake.lua
includes("../packages")
option("board", {default = "myboard", description = "Set the target board."})
add_requires("mycc", "myflasher")工程里只需要 includes("@addon/my-addon/board") 一行,配置选项、工具链和烧写工具就都齐了。
目前提供的官方 addon
第一批 addon 已经进了 xmake-repo:
| Addon | 说明 |
|---|---|
esp32-devel | ESP32 的工具链、构建规则、烧写和 blink 模板 |
avr-devel | 8 位 AVR 板子(uno / nano / mega2560)的工具链、规则和模板 |
serial-tools | xmake monitor 命令,以及可供其他 addon 复用的串口模块 |
yaml | 纯 lua 实现的 yaml 解析和生成模块,另外还提供了命令行工具 |
xmake-harness | xmake ai,用 xmake lua 写的终端编码助手 |
format-plugin / doxygen-plugin / macro-plugin | 原来的几个内置命令 |
basic-templates | 依赖外部 SDK 的工程模板(sdl、qt、verilator) |
以 esp32-devel 为例,交叉工具链、构建规则、烧写逻辑和工程模板都由它提供,所以整个 ESP32 的开发流程就这么几行,用户不需要再单独去装什么东西:
$ xmake addon --install esp32-devel
$ xmake create -t esp32.blink -l c blink
$ cd blink
$ xmake f --board=esp32c3
$ xmake
$ xmake install # 烧写到板子xmake ai,用 xmake lua 写的 AI 助手
xmake-harness 这个 addon 算是把 addon 的能力用到了极致,它是一个完整的 AI Agent 框架,会话记录、agent 主循环、工具管线、权限策略、沙箱、skills、子 agent、斜杠命令和终端 UI,全部用 xmake lua 实现,没有任何第三方依赖。装上之后就多了一个 xmake ai 命令:
$ xmake addon --install xmake-harness
$ xmake ai --setup # 选服务商、填 api key、选模型
$ xmake ai # 交互式界面
$ xmake ai "给 foo 加个单元测试"
$ xmake ai --print "这个工程构建出什么?" # 非交互模式,适合脚本和 CI因为它本身就是一个 xmake addon,所以对所在的工程是了解的,而且让它执行构建时,输出会直接打到终端,不会占用模型的上下文:
/xmake build 直接执行 xmake 构建,输出打到终端
/xmakedocs 拉取 xmake 文档,方便它查接口
/skills install xmake 加载 xmake-skills
/model deepseek-reasoner 切换模型
/context 查看上下文的占用情况另外还可以用权限模式来控制它的自由度:
$ xmake ai --mode=plan # 只读,先规划
$ xmake ai --mode=acceptedits # 自动接受文件修改,执行命令仍然询问
$ xmake ai --sandbox # 在沙箱里执行命令
web 界面
除了终端,同一个 agent 也可以跑在浏览器里:
$ xmake ai --web
$ xmake ai --web --port=9800 --cwd=/path/to/project它会在本地回环地址上起一个 http 服务,打印一个带 token 的 url(每次运行都会重新生成),然后打开浏览器。后面跑的是同一个 harness,工具、skills、权限模式和会话文件都是同一套,所以它只是换了个前端,并不是另一个 agent。打开时进入的也是这个工程上一次的会话,而不是空会话。

刚打开时是一个占满整屏的对话界面,当你去看它改了哪些文件时,界面会展开成一个工作区,左边是对话,中间是文件内容,这次对话改过的地方会标注在上面,右边则是工程的文件树。中间的文件可以直接编辑,页面里写文件和 agent 写文件走的是同一套流程:

配置
配置是分层合并的,一共五层,依次是内置默认值、~/.xmake/harness/config.json、工程配置、XMAKE_HARNESS_* 环境变量和命令行参数。写入时只会写用户那一层,所以 api key 不会被误提交到工程仓库里:
$ xmake ai --config=providers.deepseek.apikey=sk-xxxxxx
$ xmake ai --provider=deepseek --model=deepseek-chat
$ xmake ai --smallmodel=deepseek-chat # 用于标题、摘要和轻量子 agent
$ xmake ai --showconfig
$ xmake ai --doctor # 检查当前配置缺了什么内置支持的服务商有 deepseek(默认)、anthropic、openai、moonshot、dashscope、siliconflow、openrouter 和 zhipu,其他 OpenAI 接口兼容的服务,配置一下 baseurl 也可以直接用。
会话和 skills
$ xmake ai -c # 继续当前目录的上一次会话
$ xmake ai -r # 交互式选择要恢复的会话
$ xmake ai --new # 强制开新会话
$ xmake ai --list=skills # 还可以是 agents、tools、commands、providers、sessions
$ xmake ai --command=doctor # 不进 TUI 直接执行一条斜杠命令skills 不会自动拉取,只有你主动装了才会加载。其中 xmake-skills 就是专门教它怎么用 xmake 的:
/skills install xmake更完整的配置说明、服务商列表和命令列表,可以看 xmake-harness 文档。
format / doxygen / macro 插件迁移为 addon
这三个命令原本是内置在 xmake 里的,但大部分用户其实用不到,现在把它们拆成了独立的 addon:
$ xmake addon --install format-plugin
$ xmake addon --install doxygen-plugin
$ xmake addon --install macro-plugin内置的版本暂时还保留着,只是会打印一个废弃提示。装了对应 addon 之后,命令就由 addon 接管了,因为任务的搜索路径中,addon 目录现在排在内置插件前面。
package.host.install_locally 策略
package.install_locally 可以把工程用到的包装到 build/.packages 下,而不是全局的 ~/.xmake/packages。但之前它对所有包都生效,包括交叉工具链在内,而工具链这类包体积大、可以跨工程复用,又和工程配置无关,装到本地并不合适。
现在这个策略只影响平台侧的包了,主机侧的包(也就是 xmake 判定的 host 包,比如工具链)仍然装在全局,如果确实需要,可以用新加的策略单独控制:
set_policy("package.install_locally", true) -- 库包 -> build/.packages
set_policy("package.host.install_locally", true) -- 如果你确实想让工具链也进本地这样嵌入式开发中最常见的那个需求就能直接表达了:源码包跟着工程走,交叉工具链下载一次到处复用。
新增交叉编译架构
为 cross 和 linux 平台新增了一批架构支持,比如 SPARC64。
重构模板分发
我们重新组织了模板目录,也重构了模板的分发方式,addon 的 templates/ 目录正是基于这个改动才能实现,xmake create -t 用到的模板现在可以由 addon 提供,而不必内置在 xmake 安装包里。
BSD 的 pkg 包管理器
新增了 pkg 系统包管理器支持,FreeBSD 及其衍生系统上安装缺失的系统库时会走它。
改进
包的向量扩展传递给使用者
包里声明的向量扩展(add_vectorexts)现在会传递给使用它的目标,通过组件引入的也一样。比如链接了一个用 avx2 构建的包,目标就能自动拿到对应的编译选项。
hlsl2spv / glsl2spv 提前到模块扫描之前
着色器规则现在会在 C++ 模块扫描之前执行,这样扫描器读取的时候,生成的头文件已经准备好了。
核心改进
这个版本对 interpreter 的 includes 解析、工程加载、搜索缓存和 semver 都做了一轮改进。另外还收紧了 addon 导出全局模块时的冲突检查,addon 不能再覆盖 xmake 自身的模块。
更新日志
新特性
- #7696: 添加 addons 支持,可以用插件、规则、工具链、模板、模块和 includes 文件扩展 xmake
- #7702: 自动安装工程声明的 addon,并用
xmake-addons.lock锁定版本 - #7714: 支持在
xmake.lua中使用add_addons(...) - #7706: 添加 addon 测试
- #7707: 添加 addon 分发 package 定义的测试
- #7717: 将
format/doxygen/macro插件迁移为 addon - #7723: 添加新的交叉编译架构,例如 SPARC64
- #7721: 添加
package.host.install_locally策略 - #7699: 重构模板目录和模板分发
- 添加 BSD 的
pkg包管理器支持
改进
- #7719: 将包的向量扩展配置传递给使用它的目标
- #7713: 让
hlsl2spv/glsl2spv在 C++ 模块扫描之前执行 - #7722: 改进 interpreter、工程加载、搜索缓存和 semver
- #7733: 检查 addon 全局模块的命名冲突
- #7726: 改进 mingw 工具链对 clang 和 libc++ 的支持