Введение
В данной серии статей я хочу рассмотреть систему сборки дистрибутива buildroot и поделиться опытом её кастомизации. Здесь будет практический опыт создания небольшой ОС с графическим интерфейсом и минимальным функционалом.
Прежде всего, не следует путать систему сборки и дистрибутив. Buildroot может собрать систему из набора пакетов, которые ему предложили. Buildroot построен на make-файлах и поэтому имеет огромные возможности по кастомизации. Заменить пакет на другую версию, добавить свой пакет, поменять правила сборки пакета, кастомизировать файловую систему после установки всех пакетов? Всё это умеет buildroot.
В России buildroot используется, но на мой взгляд мало русскоязычной информации для новичков.
Цель работы — собрать дистрибутив с live-загрузкой, интерфейсом icewm и браузером. Целевая платформа — virtualbox.
Зачем собирать свой дистрибутив? Зачастую нужен ограниченный функционал при ограниченных ресурсах. Ещё чаще в автоматизации нужно создавать прошивки. Приспосабливать дистрибутив общего назначения, вычищая лишние пакеты и превращать его в прошивку путь более трудоёмкий, чем собрать новый дистриб. Использование Gentoo тоже имеет свои ограничения.
Buildroot система очень мощная, но она ничего не сделает за вас. Она может лишь дать возможности и автоматизировать процесс сборки.
Альтернативные системы сборки (yocto, open build system и прочие) не рассматриваются и не сравниваются.
Где взять и как начать
Сайт проекта — buildroot.org. Здесь можно скачать актуальную версию и прочитать руководство. Там же можно обратиться к сообществу, есть багтрекер, mail-lists и irc-канал.
Buildroot оперирует defconfig’aми для целевой платы сборки. Defconfig — это конфигурационный файл, хранящий в себе только опции, не имеющими значения по умолчанию. Именно он определяет, что и как будет собрано. При этом можно отдельно настроить конфиги busybox, linux-kernel, uClibc, загрузчиков u-boot и barebox, но все они будут привязаны к целевой плате.
После распаковки скачанного архива или клонировании из git получаем готовый к работе buildroot. Подробно о структуре каталогов можно прочитать в руководстве, расскажу о самых важных:
board — каталог с файлами, специфичными для каждой платы. Это могут быть скрипты формирования образов системы(iso, sdcart, cpio и прочие), каталог overlay, конфиг ядер и прочее
configs — собственно defconfig платы. Defconfig — это неполная конфигурация платы. В нем хранится только отличные от дефолтных настроек параметры
dl — каталог со скачанными исходными кодами/файлами для сборки
output/target — собранная файловая система полученной ОС. В дальнейшем из нее создаются образы для загрузки/установки
output/host — host-утилиты для сборки
output/build — собранные пакеты
Конфигурирование сборки осуществляется через KConfig. Эта же система используется для сборки ядра linux. Список самых часто используемых команд (выполнять в каталоге buildroot):
- make menuconfig — вызвать настройку сборки. Так же можно с использование графического интерфейса (make nconfig,make xconfig,make gconfig)
- make linux-menuconfig — вызвать конфигурацию ядра.
- make clean — очистить результаты сборки (всё что храниться в output)
- make — собрать систему. При этом не выполняется пересборка уже собранных процессов
- make defconfig_name — переключить конфигурацию на определенный defconfig
- make list-defconfigs — показать список defconfig’ов
- make source — только скачать установочный файлы, без сборки.
- make help — вывести список возможных команд
Важные замечания и полезные советы
Buildroot не пересобирает уже собранные пакеты! Поэтому может создаться ситуация, когда потребуется полная пересборка.
Можно пересобрать отдельный пакет командой make packagename-rebuild. Например, можно пересобрать ядро linux:
make linux-rebuild
Buildroot хранит состояние любого пакета созданием .stamp-файлов в каталоге output/build/$packagename:
Следовательно, можно пересобрать root-fs и образы без пересборки пакетов:
rm output/build/host-gcc-final-*/.stamp_host_installed;rm -rf output/target;find output/ -name ".stamp_target_installed" |xargs rm -rf ; make
Полезные переменные
В buildroot есть набор переменных для удобного конфигурирования
- $TOPDIR — корневой каталог buildroot
- $BASEDIR — каталог OUTPUT
- $HOST_DIR, $STAGING_DIR, $TARGET_DIR — каталоги сборки host fs, staging fs, target fs.
- $BUILD_DIR — каталог c распакованными и собранными пакетами
Визуализация
В buildroot есть возможность по визуализации.Можно построить схему зависимостей, график времени сборки, график размера пакетов в итоговой системе. Результаты в виде pdf файлов( на выбор есть svn,png) в каталоге output/graph.
Примеры команд визуализации:
make graph-depends
построить дерево зависимостейmake <pkg>-graph-depends
построить дерево зависимостей конкретного пакетаBR2_GRAPH_OUT=png make graph-build
построить график времени сборки с выводом в PNGmake graph-size
построить график размера пакетов
Полезные скрипты
В каталоге buildroot есть подкаталог utils c полезными скриптами. Например, там есть скрипт, проверяющий корректность описания пакетов. Это может быть полезно при добавлении своих пакетов (я это сделаю позже). В файле utils/readme.txt есть описание этих скриптов.
Соберем cтоковый дистрибутив
Важно напомнить, что все операции ведутся от лица обычного пользователя, не root.
Все команды выполняются в корне buildroot. В поставке buildroot уже есть набор конфигураций под многие распространённые платы и виртуализацию.
Смотрим список конфигураций:
Переключаемся на конфиг qemu_x86_64_defconfig
make qemu_x86_64_defconfig
И запускаем сборку
make
Сборка завершается успешно, смотрим на результаты:
Buildroot собрал образы, которые можно запустить в Qemu и убедиться, что они работают.
qemu-system-x86_64 -kernel output/images/bzImage -hda output/images/rootfs.ext2 -append "root=/dev/sda rw" -s -S
Результат — запущенная в qemu система:
Создание конфигурации собственной платы
Добавление файлов платы
Смотрим список конфигураций:
В списке видим pc_x86_64_efi_defconfig. Мы создадим свою плату, скопировав её с конфигурации:
cp configs/pc_x86_64_bios_defconfig configs/my_x86_board_defconfig
Сразу же создадим каталог платы для хранения своих скриптов, rootfs-overlay и прочих нужных файлов:
mkdir board/my_x86_board
Переключаемся на этот defconfig:
make my_x86_board_defconfig
Таким образом, теперь конфиг сборки (хранится в .config в корне каталога buildroot’а) соответствует целевой машине x86-64 legacy(bios) загрузкой.
Скопируем конфигурацию linux-kernel (пригодится в дальнейшем):
cp board/pc/linux.config board/my_x86_board/
Настройка параметров сборки через KConfig
Запускаем настройку:
make menuconfig
Откроется окно KConfig. Есть возможность конфигурировать с графическим интерфейсом (make nconfig, make xconfig, make gconfig):
Входим в первый раздел Target Options. Здесь можно выбрать целевую архитектуру, под которую будет вестись сборка.
Build options — здесь есть различные настройки сборки. Можно указать каталоги с исходными кодами, количество потоков сборки, зеркала для скачивания исходных кодов и прочие настройки. Оставим настройки по-умолчанию.
Toolchain – здесь настраивается сам инструментарий сборки. О нем подробнее.
Toolchain type – тип используемого тулчейна. Это может быть встроенный в buildroot или внешний тулчейн (можно указать каталог с уже собранным или url для скачивания). Для разных архитектур есть дополнительные опции. Например, для arm можно просто выбрать версию внешнего тулчейна Linaro.
C library – выбор библиотеки С. От этого зависит работа всей системы. Обычно используется glibc, поддерживающая весь возможный функционал. Но она может оказаться слишком большой для встроенной системы, поэтому часто выбирают uClibc или musl. Мы выберем glibc (в дальнейшем это потребуется для использования systemd).
Kernel Headers и Custom Kernel Headers series – должно совпадать с версией ядра, которое будет в собираемой системе. Для kernel headers можно так же указать путь к тарболу или git-репозиторий.
GCC COMPILER VERSIONS – выбор версии компилятора, которая будет использована для сборки
Enable C++ support – выберем для сборки с поддержкой библиотек c++ в системе. В дальнейшем нам это пригодится.
Additional gcc options – можно задать дополнительные опции компилятора. Нам без надобности пока что.
System configuration позволяет задать будущие параметры созданной системы:
Большинство пунктов понятны из названия. Обратим внимание на следующие пункты:
Path to the users tables — таблица с создаваемыми пользователями (https://buildroot.org/downloads/manual/manual.html#makeuser-syntax).
Пример файла. Будет создан пользователь user с паролем admin, автоматически gid/uid, /bin/sh шеллом, группой по-умолчанию user, член группы root, комментарием Foo user
[alexey@alexey-pc buildroot ]$ cat board/my_x86_board/users.txt
user -1 user -1 =admin /home/user /bin/sh root Foo user
Root filesystem overlay directories — каталог, накладываемый поверх собранной target-fs. Добавляет новые файлы и заменяет имеющиеся.
Custom scripts to run before creating filesystem images — Скрипты, выполняемые непосредственно перед сворачиванием файловой системы в образы. Сам скрипт пока оставим пустым
Перейдём в раздел Kernel
Здесь задаются настройки ядра. Само ядро конфигурируется через make linux-menuconfig.
Задать версию ядра можно по-разному: выбрать из предложенных, ввести версию вручную, указать репозиторий или готовый tarball.
Kernel configuration — путь к конфигу ядра. Можно выбрать конфигурацию по-умолчанию для выбранной архитектуры или defocnfig из Linux. В исходниках Linux есть набор defconfig’ов для разных целевых систем. НАйти нужный можно, глянув напрямую в исходники здесь. Например, для платы beagle bone black можно выбрать конфиг.
Раздел Target packages позволяет выбрать, какие пакеты будут установлены в собираемую систему. Пока оставим без изменений. Позже мы добавим свои пакеты в этот список.
Filesystem images — список образов файловых систем, которые будут собраны. Добавим iso-образ
Bootloaders — выбор собираемых загрузчиков. Выберем isolinix
Конфигурирование Systemd
Systemd становится одним из столбов linux, наравне с kernel и glibc. Поэтому вынес его настройку в отдельный пункт.
Настраивается через make menuconfig, далее Target packages → System tools → systemd. Здесь можно указать, какие службы systemd будут установлены и запущены при старте системы.
Сохранение конфигурации системы
Сохраняем этот конфиг через KConfig.
После чего сохраним наш defconfig:
make savedefconfig
Конфигурирование ядра Linux
Конфигурирование ядра linux вызывается следующей командой:
make linux-menuconfig
Добавим поддержку видеокарты Virtualbox
Добавим Virtualbox Guest integration support
Сохраняем и выходим. ВАЖНО: конфигурация сохранится в output/build/linux-$version/config, но не в board/my_x86_board/linux.config
Поэтому нужно вручную скопировать конфиг в место хранения:
cp output/build/linux-4.19.25/.config board/my_x86_board/linux.config
Этой командой я копирую ПОЛНЫЙ конфиг ядра, что нужно не всегда. Более правильный путь — сохранять defconfig ядра:
linux-update-defconfig
После чего выполним полную пересборку всей системы.Т.к. buildroot не пересобирает уже собранное, то надо вручную указать пакеты для пересборки. Чтобы не терять время и нервы, небольшую систему проще пересобрать целиком):
make clean;make
По завершении сборки запускаем VirtualBox(проверялось на версии 5.2 и 6.0) с загрузкой с cd-диска.Параметры системы:
Запуск с собранного iso:
Список использованных материалов
- Buildroot manual
Автор: Boozlachu