West в Zephyr: восемь приёмов, которые экономят часы и гигабайты
Перевод статьи Zephyr West Tips and Tricks — Noah Pendleton, Interrupt (Memfault), апрель 2026 года.
Инструмент Zephyr west — мощный менеджер воркспейсов, но, надо признать, довольно перегруженный функционалом: внутри него скрыто много возможностей!
Я подумал, что будет интересно поделиться несколькими приёмами, которые я использую с west, чтобы сделать мой рабочий процесс разработки под Zephyr немного плавнее.
Управление SDK с помощью west sdk#
West имеет встроенную команду для управления Zephyr SDK:
# установить конкретную версию SDK и целевой тулчейн
west sdk install --version 0.17.4 -t arm-zephyr-eabi
Вы можете установить только те тулчейны, которые действительно нужны, вместо загрузки полного пакета SDK. Некоторые другие полезные цели:
riscv64-zephyr-elfxtensa-espressif_esp32_zephyr-elf
Запустите west sdk list, чтобы увидеть, что доступно, и west sdk install --help для полного набора опций.
Что замечательно: если запустить это из воркспейса west, содержащего проект zephyr, west sdk install подхватит значение zephyr/SDK_VERSION, так что вы получите соответствующую версию SDK — проще простого!
--version [SDK_VER] version of the Zephyr SDK to install. If not specified,
the install version is detected from
${ZEPHYR_BASE}/SDK_VERSION file.
Это подробно рассмотрено в Practical Zephyr - West workspaces (Part 6), определённо стоит прочитать, если ещё не читали.
Ограничение глубины клона с clone-depth#
Если вы работаете с большими репозиториями или часто инициализируете новые воркспейсы, вы можете добавить clone-depth к проектам в вашем манифесте west, чтобы значительно ускорить процесс:
# west.yml
manifest:
projects:
- name: some-large-repo
url: https://github.com/example/some-large-repo
clone-depth: 1
Полная справка по манифесту: https://docs.zephyrproject.org/latest/develop/west/manifest.html#projects
Примечание: Я не уверен, учитывается ли clone-depth для проектов, которые подтягиваются транзитивно через import. Стоит проверить для вашей конкретной конфигурации воркспейса.
Ограничение того, что импортирует west update#
По умолчанию, если вы импортируете манифест проекта (например, west.yml Zephyr), west склонирует все его перечисленные зависимости рекурсивно. У Zephyr их много, и наивный west update может легко скачать гигабайты репозиториев, которые вам не нужны.
Два параметра манифеста, которые здесь очень помогают:
name-allowlist — Импортировать только названные проекты из вышестоящего манифеста:
# west.yml
manifest:
projects:
- name: zephyr
url: https://github.com/zephyrproject-rtos/zephyr
revision: v4.3.0
import:
name-allowlist:
- cmsis
- hal_nordic
- mbedtls
Это Option 3 в документации по манифесту и, вероятно, самое полезное, что вы можете сделать для быстрой инициализации воркспейса.
path-prefix — Поместить все импортированные проекты в общий подкаталог вместо корня воркспейса. Держит всё в порядке:
import:
path-prefix: deps
name-allowlist:
- cmsis
- hal_nordic
С вышеуказанным импортированные репозитории попадают в deps/, а не разбросаны по верхнему уровню. Статья Practical Zephyr - West workspaces проходит через полный рабочий пример обоих вместе.
Кеширование загрузок west update#
Если вы часто клонируете воркспейсы west (например, при тестировании незнакомых проектов), трафик git fetch может быстро накапливаться. West поддерживает reference cache для общего хранилища объектов между воркспейсами:
west config --global update.auto-cache ~/.cache/west
С auto-cache west автоматически заполняет и использует директорию кеша, так что последующие вызовы west update в новых воркспейсах могут разрешать большинство объектов локально вместо обращения к сети.
Есть несколько других полезных опций конфигурации update.*, которые стоит посмотреть в справке:
https://docs.zephyrproject.org/latest/develop/west/config.html#built-in-configuration-options
Алиасы#
West поддерживает пользовательские алиасы команд, похожие на алиасы git. Они отлично подходят для сокращения рабочих процессов, которые вы запускаете постоянно. Из документации:
west config --global alias.run "build --pristine=never --target run"
west config --global alias.menuconfig "build --pristine=never --target menuconfig"
После этого west run и west menuconfig просто работают. В документации по алиасам есть больше примеров:
https://docs.zephyrproject.org/latest/develop/west/alias.html#examples
Расширения West#
Расширения West позволяют проектам (или вашему собственному локальному инструментарию) добавлять пользовательские подкоманды к west. Это полезно, когда вы хотите, чтобы проектно-специфичный инструментарий ощущался как первоклассный гражданин в вашем рабочем процессе, а не как отдельный скрипт (особенно приятно для discoverability, поскольку всё доступно из west --help).
Это полезно, когда нужные вам команды не вписываются в обычный рабочий процесс build/flash/debug/attach, предоставляемый собственными командами расширений Zephyr SDK, и алиасов недостаточно.
Быстрый пример: мы добавляем следующие файлы/фрагменты в наш репозиторий манифеста:
west.yml:
manifest:
self:
# register this repo's west extensions
west-commands: scripts/west-commands.yml
scripts/west-commands.yml:
west-commands:
- file: scripts/west_extensions.py
commands:
- name: project-hello
class: ProjectHello
help: sample Project west extension command
scripts/west_extensions.py:
from textwrap import dedent
from west.commands import WestCommand
class ProjectHello(WestCommand):
def __init__(self):
super().__init__(
"project-hello", # gets stored as self.name
"", # ignored self.help, will not be required by future west versions
description=dedent(
"""
Sample Project west extension command.
"""
),
)
def do_add_parser(self, parser_adder):
parser = parser_adder.add_parser(self.name, description=self.description)
levels = ["dbg", "inf", "wrn", "err"]
parser.add_argument(
"-l",
"--level",
default="inf",
choices=levels,
help="log level for the message (default: %(default)s)",
)
parser.add_argument("message", help="message to print")
return parser # gets stored as self.parser
def do_run(self, args, unknown):
log_fn = {
"dbg": self.dbg,
"inf": self.inf,
"wrn": self.wrn,
"err": self.err,
}[args.level]
self.inf(f"[{self.name}] log level: {args.level}")
log_fn(f"[{self.name}] message: {args.message}")
Теперь новое расширение появляется в west --help:
extension commands from project manifest (path: blahblah):
project-hello: sample Project west extension command
И мы можем запустить его:
❯ west project-hello --level err 'Hello!'
[project-hello] log level: err
ERROR: [project-hello] message: Hello!
Справка Zephyr подробно описывает, как это сделать: https://docs.zephyrproject.org/latest/develop/west/extensions.html#west-extensions
Сокращение того, что скачивает west update#
Для повседневной разработки вам часто не нужна полная история каждой зависимости. Вы можете значительно ускорить west update с помощью пары флагов:
west update --narrow --fetch-opt=--depth=1
--narrowуказывает west скачивать только конкретную ревизию, указанную в манифесте, а не все refs с удалённого сервера.--fetch-opt=--depth=1передаёт--depth=1в underlyinggit fetch, давая вам shallow clone только с tip-коммитом.
Вместе они могут dramatically сократить сетевой трафик и использование диска, особенно при первой инициализации большого воркспейса.
Используйте git fetch --unshallow на модуле, чтобы позже преобразовать shallow clone в полный — это полезно, если вам нужна полная история (например, для bisecting) или вы хотите внести вклад в upstream!
Разрешение манифеста в точные SHA#
Манифесты West обычно ссылаются на ветки или теги, которые могут drift со временем. Чтобы захватить полностью разрешённый снимок с точными SHA коммитов — полезно для воспроизводимых сборок или аудита — используйте:
west manifest --resolve
Вывод — валидный манифест west с каждым проектом, прибитым к конкретной ревизии:
manifest:
group-filter:
- -babblesim
- -optional
- -testing
projects:
- name: canopennode
url: https://github.com/zephyrproject-rtos/canopennode
revision: dec12fa3f0d790cafa8414a4c2930ea71ab72ffd
path: modules/lib/canopennode
groups:
- optional
- name: chre
url: https://github.com/zephyrproject-rtos/chre
revision: c4c2f49fdcaa2fed49eb1db027696a5734a010d2
path: modules/lib/chre
groups:
- optional
# ...
Вы можете перенаправить это в west.lock.yml (или аналогичный) и закоммитить рядом с вашим манифестом, чтобы любой, клонирующий воркспейс, получил точно такое же дерево.