west 使用指南
west 是 Zephyr 常用的工作区管理工具,也是构建、烧录、调试命令的统一入口。学习时不必先背完所有命令,但要知道它从哪里读取配置、操作哪个仓库,以及什么时候会改变依赖版本。
本页基于本机 west 1.5.0 与 Zephyr 52b48529aec。先读概念,再用现有环境执行只读检查;首次安装流程仍在 工作区与工具链。
工具分工
| 工具 | 职责 | 例子 |
|---|---|---|
| Git | 管理单个仓库的提交、分支、远程同步 | 提交自己的应用,推送 GitHub |
| west | 根据清单管理多个仓库,并加载扩展命令 | 取得与 Zephyr 配套的 HAL、LVGL |
| CMake | 读取应用、板卡和配置,生成构建规则 | 处理 CMakeLists、Kconfig、设备树 |
| Ninja | 根据规则执行编译、链接任务 | 增量编译修改过的文件 |
| SDK 编译器 | 生成目标 CPU 的指令 | 把 C 代码编译成 ESP32-S3 可执行代码 |
| runner / 烧录工具 | 使用板卡对应协议写入镜像 | esp32 runner 调用 esptool |
west build 本身不是 C 编译器,west flash 也不直接实现所有芯片的下载协议。它把这些工具连接起来,减少每次手工指定参数的工作。可以不用 west 手动配置 CMake,但需要自己管理路径和依赖;入门与本项目日常开发都使用 west。
工作区与清单
当前电脑的布局是:
~/Projects/
├── esp32-zephyr/ # 自己的应用仓库,位于工作区外
│ ├── apps/
│ └── west.yml # 供未来新工作区初始化使用
└── zephyr-main-workspace/ # west topdir
├── .west/config # 当前实际生效的工作区配置
├── zephyr/ # 当前 manifest 仓库
│ ├── .git/
│ └── west.yml # 当前实际读取的清单
└── modules/
├── hal/espressif/ # 独立 Git 仓库
└── lib/gui/lvgl/ # 独立 Git 仓库
一个 west 工作区有一个入口 manifest 仓库。.west/config 中的 manifest.path 指向它,manifest.file 指定清单文件,默认名为 west.yml。清单列出其他 project 的仓库 URL、目录与版本。
自己的目录里有 west.yml,不意味着它已经接管当前工作区。 本机现有工作区仍以 zephyr/west.yml 为入口;esp32-zephyr 的构建脚本只是复用它。这个区别决定了 west update 到底按哪一份清单操作。
west 的 project 是仓库管理概念,Zephyr module 是构建集成概念。许多 project 同时提供模块,但两者不能一概等同;构建系统还要读取模块元数据来接入源码、Kconfig 等。
定位当前环境
在任何更新操作前,先确认位置:
source ~/Projects/zephyr-main-workspace/.venv-py312-main/bin/activate
cd ~/Projects/zephyr-main-workspace/zephyr
west --version
west topdir
west config manifest.path
west manifest --path
west list manifest lvgl hal_espressif
本机应分别看到 main 工作区、manifest.path 为 zephyr,以及 zephyr/west.yml 的完整路径。list 展示名称、目录、清单指定的修订和 URL;它不是在显示每个仓库当前 HEAD。
这里 Zephyr 本身是 manifest 仓库,在 west list 中用特殊名称 manifest 查询。执行 west list zephyr 在这个布局中会报 unknown project;若未来使用自己的应用仓库作为 manifest,而 Zephyr 列在 projects 中,才可以用项目名 zephyr 查询。
west 通常从当前目录向上寻找 .west;找不到时还可能通过 ZEPHYR_BASE 回退定位。激活虚拟环境只选中了 Python 工具,不会自动切换工作区。遇到目录错乱时先看 topdir,不要盲目设置环境变量掩盖问题。
init 与 update
初始化
下面是原教程首次取得官方源码的形式,已经有工作区时不再执行:
west init -m https://github.com/zephyrproject-rtos/zephyr \
--mr 52b48529aecc3ad0ef9b159996bdb5d2b3e5b794 \
~/Projects/zephyr-main-workspace
-m 指定 manifest 仓库,--mr 指定它的初始修订,最后是工作区位置。init 创建 .west 并准备入口仓库,其他模块由 update 取得。
同步依赖
cd ~/Projects/zephyr-main-workspace
west update
update 按当前清单取得项目与修订,不等于把所有库升级到最新 main。它不会替你更新 manifest 仓库本身。在当前布局中,想改变 Zephyr 版本要先用 Git 处理 zephyr 仓库的修订,再运行 west update 同步配套模块。
只处理指定模块可以运行 west update lvgl。但切换了 Zephyr 版本后通常应整体同步,不能只更新一个库然后假设其他依赖仍然匹配。update 可能检出不同提交,在修改过模块源码的工作区里操作前先查看差异;不要为排错直接丢弃改动。
每天只修改自己的 main.c,不需要每天 west update。依赖更新是独立操作,应记录版本并重新验证固件。
内置命令与扩展命令
| 类别 | 常见命令 | 来源 |
|---|---|---|
| 内置 | init、update、list、topdir、manifest、config、status、diff | Python 环境中安装的 west |
| Zephyr 扩展 | build、flash、debug、boards、zephyr-export、packages、sdk、blobs | 当前工作区提供的扩展代码 |
| 芯片相关扩展 | espressif monitor | 当前依赖仓库提供的扩展 |
扩展随所用源码变化,不能只看 west 版本判断某个子命令是否存在。在没有工作区或模块不完整的目录,可能出现 west 已安装、却找不到 build 或 espressif 的情况。
查看帮助:
west --help
west build --help
west flash --help
west espressif --help
packages 安装 Python 依赖,sdk 安装工具链,blobs 取得模块声明的二进制组件,zephyr-export 注册 CMake 包。它们与 update 的仓库同步分别负责不同事情,不应把一个失败当成需要全部重装。
构建命令
理解仓库脚本之前,先看它最终调用的形式。下面编译独立仓库的周期打印应用:
export ZEPHYR_SDK_INSTALL_DIR=~/.local/opt/zephyr-sdk-1.0.1
cd ~/Projects/zephyr-main-workspace/zephyr
west build -p always \
-b esp32s3_touch_lcd_1_28/esp32s3/procpu \
~/Projects/esp32-zephyr/apps/learning \
-d ../build/esp32-zephyr/waveshare-s3-touch-128/learning
- 应用路径决定读取哪份 CMakeLists、prj.conf 和源码。
-b决定板卡目标,不是应用名称。-d决定输出目录,不是源码目录。-p always清理指定输出目录后重新配置;它不会清理应用源码。
初始化完成后,仅修改 C 文件可以执行:
west build -d ../build/esp32-zephyr/waveshare-s3-touch-128/learning
已有构建目录会保存应用、板卡等配置。换板、换应用或排查缓存影响时,使用独立目录或 pristine 构建,不把旧缓存当成默认值。
额外 CMake 参数放在 -- 后面,例如 -DEXTRA_CONF_FILE=backlight.conf 和 -DDTC_OVERLAY_FILE=boards/waveshare.overlay,具体示例见 Kconfig 配置。相对路径的含义取决于参数:应用配置文件按 Zephyr 规则相对应用目录解析,构建目录参数相对于调用命令的位置。
独立仓库中的 python scripts/build.py learning 封装了应用、目标和目录选择,并显式设置 Zephyr 源码位置;它仍然调用 west,不是另外一套编译器。
烧录与监视
cd ~/Projects/zephyr-main-workspace/zephyr
west flash -d ../build/esp32-zephyr/waveshare-s3-touch-128/learning \
--esp-device /dev/ttyACM0
构建目录的 zephyr/runners.yaml 记录可用 runner 和产物。west flash 默认会先尝试重新构建,再调用该板 runner。端口参数属于当前 esp32 runner;其他厂商的板不能照搬该参数。
只查看烧录上下文、不烧录,可以执行:
west flash -d ../build/esp32-zephyr/waveshare-s3-touch-128/learning --context
这个检查仍可能触发一次重建。烧录和串口监视是两个操作:
cd ~/Projects/zephyr-main-workspace/build/esp32-zephyr/waveshare-s3-touch-128/learning
west espressif monitor -p /dev/ttyACM0 -b 115200
不要进入构建目录后又把 -d 写成从源码根目录计算的相对路径。拿不准时使用绝对路径。
自己的 manifest
独立固件仓库的 west.yml 是:
manifest:
remotes:
- name: zephyrproject
url-base: https://github.com/zephyrproject-rtos
projects:
- name: zephyr
remote: zephyrproject
revision: 52b48529aecc3ad0ef9b159996bdb5d2b3e5b794
import: true
self:
path: esp32-zephyr
这里 remote 名称与 Git 的 origin 是不同的配置入口;url-base 用于拼出下载地址。revision 固定 Zephyr 提交,import 引入它的模块清单,self.path 给出 manifest 仓库的预期位置。
新电脑将仓库克隆到 ~/Projects/esp32-workspace/esp32-zephyr 后,可以在已激活的环境中执行:
cd ~/Projects/esp32-workspace
west init -l esp32-zephyr
west update
此时 manifest 仓库才变成 esp32-zephyr,Zephyr 变成受清单管理的 project。新布局中更新自己的 west.yml 再执行 update,才会按该文件改变 Zephyr 版本。当前已有工作区无需为学习这一点立刻迁移。
版本检查与冻结
cd ~/Projects/zephyr-main-workspace/zephyr
west manifest --validate
west list lvgl hal_espressif
git rev-parse HEAD
west status
west diff
validate 检查清单合法性,不验证每块硬件能运行;status/diff 用于查看修改,也不代替在自己的应用仓库执行 Git 检查。本机 esp32-zephyr 在工作区外,所以还要单独运行 git -C ~/Projects/esp32-zephyr status。
需要依赖快照时:
west manifest --freeze --active-only -o ../west-manifest-frozen.yml
本机 west 1.5.0 对普通 project 冻结的是 manifest-rev 对应提交,不能把它当作任意本地 HEAD、未提交修改和自定义补丁的备份。另行保存入口仓库/应用提交及必要补丁。
active-only 用于跳过未启用的可选项目;不加时可能遇到可选 canopennode 未克隆的错误。若缺失的是启用项目,应先完成其同步。west.yml 的固定 revision、冻结快照和源码提交各有作用,不能只写“我用 main”。
常见问题
| 现象 | 优先检查 |
|---|---|
| west: command not found | 是否激活正确虚拟环境,west 是否安装其中 |
| 找不到工作区 | 当前路径、.west/config、ZEPHYR_BASE |
| unknown command build | 工作区是否正确,Zephyr 扩展是否已取得 |
| update 后 Zephyr 没变 | Zephyr 是否就是 manifest 仓库;update 不更新入口仓库 |
| 应用仓库的 west.yml 修改无效 | 当前 manifest --path 是否仍指向上游 Zephyr |
| 构建了旧应用或旧板 | CMakeCache、-d、-b 与应用路径 |
| list zephyr 报错 | 当前布局里 Zephyr 是否应以 manifest 特殊名称查询 |
| 烧录成功但无输出 | 端口、复位、BOOT、固件功能;不是重跑 west init |
练习与验证
不修改依赖,完成三项检查:找出当前 manifest 的路径;查出 LVGL 的清单修订和实际仓库 HEAD;解释独立仓库 west.yml 为什么还没有接管现有工作区。
2026-09-24 已在本机执行版本、topdir、manifest 路径、指定项目 list、manifest validate 和 flash context 检查。context 未烧录设备;本章未执行更新操作,也未改变现有工作区布局。
参考:west 基础、manifest、构建与烧录。冻结行为同时核对了本机 west 1.5.0 的 manifest.py 实现。