Yocto Project Development Tasks Manual
Scott Rifenbark
Scotty’s Documentation Services, INC
Copyright © 2010-2019 Linux Foundation
Разрешается копирование, распространение и изменение документа на условиях лицензии Creative Commons Attribution-Share Alike 2.0 UK: England & Wales, опубликованной Creative Commons.
Этот документ основан на переводе Yocto Project Development Tasks Manual для выпуска 2.7.1. Свежие версии оригинальных документов можно найти на странице Yocto Project documentation. Размещенные там материалы более актуальны, нежели включенные в архивы пакета Yocto Project.
Глава 1. Руководство по разработке проектов в Yocto Project
1.1. Введение
В этом руководстве описаны процедуры разработки в среде Yocto Project (YP) образов Linux для встраиваемых систем и пользовательских приложений для работы на таких системах. Документ разбит на несколько разделов, описывающих связанные между собой процедуры.
Документ включает приведенные ниже описания.
- Процедуры, помогающие начать работу с YP, например, процедуры организации хоста для сборки и работы с репозиториями YP.
- Процедуры фиксации изменений в YP (улучшения, новые функции, исправления ошибок).
- Процедуры общего назначения при разработке образов и приложений с использованием YP, например, процедуры создания уровней, настройки образов, создания новых заданий (recipe) и т. п.
Глава 2. Настройка YP
В этой главе описаны процедуры подготовки к работе с YP, включая создание среды командной работы с использованием YP, настройку хоста для сборки, поиск репозиториев YP создание локального репозитория Git.
2.1. Создание среды для командной работы
Использование YP для командной работы на первый взгляд может показаться не очевидным. Одной из сильных сторон YP является гибкость системы. Вы можете настроить ее для множества вариантов использования. Однако эта гибкость может вызывать сложности при настройке системы для работы большой команды.
В этом параграфе описана организация среды коллективной разработки и представлена процедура для решения этой задачи. Эта процедура реализуется на верхнем уровне и проверена на практике. Следует учитывать, что описанная процедура обеспечивает лишь стартовую точку и вам в любом случае придется приложить усилия по настройке системы в соответствии со своими реальными потребностями и задачами.
- Определение состава команды разработчиков. Определение участников разработки с использованием YP и их ролей. Это важно для выполнения пп. 2 и 3 при выборе оборудования и топологии. Ниже перечислены возможные роли участников процесса.
- Разработчик приложений создает программы, работающие на базе имеющегося программного стека.
- Разработчик ядра системы создает образы операционной системы.
- Инженер сборки управляет автоматическими сборщиками (Autobuilder) и выпусками. Эта роль присутствует не всегда.
- Инженер тестирования создает автоматизированные тесты и управляет ими для проверки качества приложений и операционной системы, а также соответствия стандартам.
- Подбор оборудования. Соберите оборудование с учетом размера и состава команды. В идеальном варианте всем членам команды лучше работать в среде на основе поддерживаемого дистрибутива Linux. Рабочие станции должны быть достаточно производительными (например, два 6-ядерных процессора Xeon с 24 Гбайт ОЗУ и достаточным пространством на диске). Для тестирования производительности и использования Autobuilder потребуются высокопроизводительные компьютеры.
- Анализ аппаратной топологии оборудования. После выбора оборудования для работы команды нужно разобраться с топологией среды разработки.
- Использование Git в качестве менеджера исходных кодов (SCM1). Рекомендуется хранить метаданные (задания, файлы конфигурации, классы и т. п.) и все разрабатываемые программы под контролем системы SCM, совместимой с системой сборки OpenEmbedded (OE). Из числа SCM, поддерживаемых BitBake, команда YP настоятельно рекомендует выбрать Git. Это распределенная система с простым резервированием, позволяющая работать удаленно, а затем возвращаться в инфраструктуру. Дополнительная информация о BitBake представлена в [6].Сравнительно просто организовать службы Git и создать инфраструктуру похожую на http://git.yoctoproject.org, которая основана на серверной программе gitolite с использованием cgit для генерации web-интерфейса, позволяющего просматривать репозитории. Программа gitolite идентифицирует пользователей с помощью ключей SSH и обеспечивает управление доступом по ветвям для репозиториев. Организация этих служб выходит за рамки документа, но ниже приведены ссылки на документы, описывающие эти процессы.
- Документация Git с описанием установки gitolite на сервере.
- Описание Gitolite.
- Интерфейсы и инструменты для Git.
- Организация машин для разработки приложений. Как отмечено выше, разработчики приложений создают программы для работы на имеющемся программном стеке. Ниже приведены рекомендации по организации машин для такой работы.
- Используйте собранный набор инструментов с нужным стеком программ и создавайте приложения для работы в этом стеке. Этот метод хорош для небольшого числа сравнительно изолированных приложений.
- Поддерживайте инструменты кросс-разработки в актуальном состоянии. Это можно делать путем загрузки новых версий инструментальных пакетов или обновления с помощью механизма opkg. Выбор варианта зависит от ваших потребностей и принятой политики.
- Используйте множество инструментальных пакетов, установленных локально в разных местах для работы с разными версиями.
- Организация машин для разработки ядра системы. Как отмечено выше, разработчики ядра системы работают непосредственно с образами операционных систем. Ниже приведены рекомендации по организации машин для такой работы.
-
- Настройте систему сборки OE [3] на рабочих станциях разработчиков, чтобы они могли создавать свои сборки и напрямую пересобирать образы.
-
- Сохраняйте систему сборки неизменной и вносите свои изменения в своих уровнях на основе этой системы. Это обеспечит переносимость работы при обновлении системы или пакетов BSP2.
- Созданные уровни следует местно использовать всем разработчикам в соответствии с политикой настройки, определенной для проекта.
- Установка системы Autobuilder. Средства автоматической сборки зачастую являются ядром среды разработки. Именно здесь собираются вместе и тестируются результаты отдельных разработчиков. На базе этой автоматизированной среды сборки и тестирования принимается решение о выпуске. Autobuilder также позволяет тестировать программные компоненты в стиле «непрерывной интеграции» с обнаружением и отслеживанием регрессии.На странице YP Autobuilder представлена подробная информация и ссылка на buildbot, который команда YP сочла подходящим для автоматического тестирования. Общедоступным примером является YP Autobuilder, используемый командой YP для тестирования проекта в целом. Свойства системы приведены ниже.
- Указание фиксаций (commit), нарушающих сборку.
-
- Заполнение кэша sstate [1], из которого разработчики могут извлекать данные ,ез локальной сборки.
-
- Поддержка триггеров фиксаций, включающих сборки при новом представлении (commit).
- Возможность включать автоматизированную загрузку и тестирование образов в QEMU3.
- Поддержка пошагового тестирования сборки и сборок «с нуля».
- Общий доступ к выводу сборки, позволяющий разработчикам выполнять тестирование и искать проблемы.
- Создание вывода, который можно использовать в выпусках системы.
- Возможность сборки по расписанию для эффективного использования ресурсов.
- Установка машин для тестов. Используйте несколько высокопроизводительных систем для тестирования. Разработчики могут применять эти машины для масштабного тестирования, продолжая работу на своих системах.
- Правила документирования и поток изменений. YP использует иерархическую структуру и модель извлечения. Имеются сценарии для создания и отправки pull-запросов (create-pull-request и send-pull-request). Эта модель соответствует другим проектам с открытым кодом, где сопровождающие отвечают за определенные области проекта, а один обрабатывает слияния на вершине дерева (top-of-tree). Можно также использовать коллективную модель выталкивания (push), поскольку gitolite одинаково легко поддерживает модели push и pull. Как в любой среде разработки важно документировать используемые правила, а также основные принципы проекта, чтобы они были понятны каждому. Хорошо также структурировать сообщения фиксации (commit), что обычно делается в описании принципов проекта. Четкие сообщения фиксации нужны для понимания внесенных в проект изменений.При необходимости внесения изменений в ядро проекта следует как можно скорее поделиться ими с сообществом. Скорее всего другие члены сообщества также нуждаются в этих изменениях.
- Дополнительные рекомендации.
- Используйте Git в качестве системы управления исходными файлами.
- Поддерживайте метаданные на уровнях, которые имеют смысл для вашей ситуации (см. раздел The Yocto Project Layer Model [1] и параграф 3.1. Уровни и их создание).
- Разделяет метаданные и код проекта, используя разные репозитории Git (см. раздел Yocto Project Source Repositories [1] и параграф 2.3. Доступ к исходным файлам YP.
- Создайте каталог для кэширования общих данных состояния (SSTATE_DIR). Например создайте кэш sstate на системе разработчиков и используйте одинаковые каталоги исходных кодов на их машинах.
- Установите систему Autobuilder и поместите в нее кэш sstate и каталоги с исходными кодами.
- Сообщество YP призывает отправлять исправления (patch) в проекте для устранения ошибок и расширения возможностей. Если вы представляете изменения, следуйте правилам фиксации (см. параграф 3.31.2. Представление изменений в YP.
-
- Отправляйте изменения в ядре системы как можно скорей, поскольку с этими же проблемами могут столкнуться другие люди. Рекомендации и списки рассылок приведены в параграфе 3.31.2. Представление изменений в YP и разделе Mailing Lists [3].
2.2. Подготовка сборочного хоста
В этом параграфе описана настройка системы, которая будет служить сборочным хостом для разработки с использованием YP. Хост может быть Linux-машиной (рекомендуется) или машиной (Linux, Mac, Windows) с CROPS и контейнерами Docker. Хост с WSL4 не подойдет в качестве сборочного по причине несовместимости YP с WSL.
После установки YP на сборочном хосте дальнейшие шаги зависят от ваших задач. Ниже представлены ссылки на информацию для случаев работы с BSP и ядром Linux.
- Разработка BSP – раздел Preparing Your Build Host to Work With BSP Layers [5].
- Разработка ядра – раздел Preparing the Build Host to Work on the Kernel [7].
2.2.1. Установка сборочного хоста Linux
- Используйте поддерживаемый дистрибутив Linux. Вам следует выбрать хост с текущей версией того или иного дистрибутива Linux. Рекомендуется применять свежий выпуск Fedora, openSUSE, Debian, Ubuntu или CentOS, поскольку эти дистрибутивы тестируются с YP и поддерживаются официально5. Список всех поддерживаемых дистрибутивов и детали работы с ними представлены в разделе Supported Linux Distributions [3] и на странице Distribution Support.
- Обеспечьте достаточный объем свободного пространства на диске. Для работы потребуется не менее 50 Гбайт свободного пространства на диске при сборке образов6.
- Выполните требования к версиям программ на хосте. Система сборки OE может работать с любым современным дистрибутивом, включающим
- Git 1.8.3.1 и выше;
-
- tar 1.27 и выше;
-
- Python 3.4.0 и выше.
Если на сборочном хосте не выполняется какое-либо из этих требований, следует предпринять действия, указанные в разделе Required Git, tar, and Python Versions [3].
- Установка пакетов на хост разработки сильно зависит от операционной системы и задач, которые планируется выполнять в YP. Если вы хотите работать со всеми классами, потребуется установка достаточно большого числа пакетов, как указано в разделе Required Packages for the Build Host [3].
После выполнения перечисленных действий система будет готова к использованию. Работа с рассмотрена в параграфе 2.4.1. Клонирование репозитория poky, использование расширяемого SDK7 описано в разделе Using the Extensible SDK [2]. Работа с ядром Linux описана [7]. При использовании интерфейса управления Toaster следует обратиться к разделу Setting Up and Using Toaster [8].
2.2.2. Настройка CROPS
С CROPS8 и контейнерами Docker можно создать среду разработки YP, независимую от операционной системы хоста. Можно организовать контейнер, который будет работать на машинах Windows, Mac, Linux для разработки в среде YP.
- Определение потребностей сборочного хоста. Docker представляет собой платформу программных контейнеров, которую нужно установить на сборочном хосте. В зависимости от конкретного хоста можно установить разные программы для работы с контейнерами Docker. Информацию о поддерживаемых системах и установке программ для работы с контейнерами можно найти на странице Supported Platforms.
- Выбор устанавливаемых компонент. В зависимости от соответствия сборочного хоста системным требованиям нужно установить пакет Docker CE Stable (в большинстве случаев) или Docker Toolbox.
- Переход на сайт установки для вашей платформы. Воспользуйтесь ссылкой для выпуска Docker, соответствующего программной платформе сборочного хоста. Например, для Microsoft Windows версии 10 следует выбрать Docker CE Stable из списка поддерживаемых платформ.
- Установка программ. После проверки соответствия установочного требованиям можно загрузить и установить программу, следуя инструкциям пакета установки.
- Знакомство с системой Docker. При необходимости ознакомьтесь с Docker и концепцией контейнеров на странице https://docs.docker.com/get-started/.
- Запуск Docker или Docker Toolbox активизирует терминальное окно системы на вашем сборочном хосте.
- Настройка контейнеров для работы с YP. На странице https://github.com/crops/docker-win-mac-docs/wiki приведены инструкции для работы на разных платформах (Linux, Mac или Windows). После выполнения установочных инструкций для вашей машины вы получите контейнеры Poky, eSDK и Toaster. Для знакомства с ними можно воспользоваться ссылками на указанной выше странице.
После установки контейнеров все готово для работы, как будто вы используете естественную машину Linux. Работа с контейнером Poky описана в параграфе 2.4.1. Клонирование репозитория poky. Описание работы с контейнером eSDK дано в разделе Using the Extensible SDK [2], а работа с системой Toaster в разделе Setting Up and Using Toaster [8].
2.3. Доступ к исходным файлам YP
В этом разделе описано как найти исходные файлы YP и работать с ними в проекте. Концепции и рекомендации по использованию Git с YP приведены в разделе Git [1]. Концепции работы с репозиторием YP описаны в разделе Yocto Project Source Repositories [1].
2.3.1. Доступ к репозиториям исходных кодов
Работа с копией репозитория исходных кодов является предпочтительным вариантов получения и использования выпуска YP. Список репозиториев YP можно найти на сайте http://git.yoctoproject.org. В частности, репозиторий poky размещается по ссылке http://git.yoctoproject.org/cgit/cgit.cgi/poky/. Процедура установки свежей версии описана ниже.
- Доступ к репозиториям. Перейдите в браузере по ссылке http://git.yoctoproject.org с интерфейсом к репозиториям исходных кодов YP.
- Выбор репозитория по ссылке (например, poky).
- Определение URL для клонирования репозитория. В нижней части страницы приведен идентификатор URL для клонирования репозитория (например, http://git.yoctoproject.org/poky). Процесс клонирования описан в параграфе 2.4.1. Клонирование репозитория poky.
2.3.2. Доступ к списку выпусков
YP поддерживает список выпусков (Index of Releases), где указаны файлы, включенные в YP. В отличие от репозиториев Git эти файлы являются архивами, соответствующими определенному времени. Рекомендуемым методом доступа к компонентам YP является клонирование репозитория Git и работа с локальной копией. Описанная в этом параграфе процедура относится к установке компонент из архивов.
- Доступ к списку выпусков. Откройте браузер и перейдите по ссылке http://downloads.yoctoproject.org/releases для доступа к Index of Releases, где представлены компоненты выпуска (bitbake, sato и т. д.). Каталог yocto содержит архивы всех выпусков Poky, а каталог poky в Index of Releases применялся лишь для самых первых выпусков и сохранен только для полноты.
- Выберите компоненту по ссылке в списке (например, yocto).
- Выберите архив из списка выпусков. Например, щелчок по ссылке yocto-2.7.1 покажет файлы, связанные с выпуском YP 2.7.1 (например, poky-warrior-21.0.0.tar.bz2 для Poky).
- Загрузка архива. Щелкните по имени нужного архива для его загрузки.
2.3.3. Использование страницы загрузки
На сайте YP страница DOWNLOADS предназначена для выбора и загрузки архивов имеющихся выпусков YP. В отличие от репозиториев Git эти файлы представляют архив, сделанный в определенный момент, подобно файлам из Index of Releases, описанным в параграфе 2.3.2. Доступ к списку выпусков. Рекомендуемым методом доступа к компонентам YP является клонирование репозитория Git и работа с локальной копией. Описанная в этом параграфе процедура относится к установке компонент из архивов.
- Откройте сайт YP в браузере по ссылке.
- Перейдите в область загрузки файлов, выбрав опцию DOWNLOADS в раскрывающемся меню SOFTWARE наверху страницы.
- Выберите выпуск YP в меню RELEASE (например, warrior, thud и т. д). Для сопоставления имен выпусков YP с номерами версий используйте страницу Releases. Можно воспользоваться ссылкой RELEASE ARCHIVE для получения меню выбора из всех выпусков YP.
- Загрузите инструменты или BSP со страницы DOWNLOADS.
2.3.4. Доступ к «ночным сборкам»
YP поддерживает область «ночных сборок» в архивами на странице https://autobuilder.yocto.io//pub/nightly/. Эти архивы включают выпуски YP (poky), инструменты и сборки для поддерживаемых машин. Процедура получения ночных сборок описана ниже.
- Перейдите к списку ночных сборок, открыв в браузере ссылку https://autobuilder.yocto.io//pub/nightly/.
- Выберите дату, щелкнув по нужной ссылке. Для получения последней сборки используйте CURRENT.
- Выберите сборку. Например, для получения наиболее свежих инструментов служит ссылка toolchain.
- Выберите архив, прокручивая список.
- Загрузите архив, соответствующий выбранной дате и компоненте.
2.4. Клонирование и выбор ветвей
Для использования YP при разработке нужно установить выпуск пакета на хосте разработки. Этот набор локально установленных файлов называется в документации YP деревом (каталогом) исходных кодов (Source Directory).
Предпочтительным методом создания дерева кодов является использование Git для клонирования репозитория poky. Работа с клонированной копией репозитория позволяет включить ваши результаты в YP или просто использовать последние версии программ из ветви разработки. Поскольку Git клонирует и поддерживает репозиторий с полной историей изменений, а вы работаете с локальной копией репозитория, вы получаете доступ ко всем разрабатываемым ветвям YP и тегам, применяемым в репозитории.
2.4.1. Клонирование репозитория poky
Ниже перечислены этапы создания локальной копии репозитория Git poky.
- Организация локального каталога. Создайте каталог для локального репозитория poky и перейдите в него.
- Клонирование репозитория. Ниже приведен пример команды клонирования репозитория poky и ее вывод.
$ git clone git://git.yoctoproject.org/poky Cloning into 'poky'... remote: Counting objects: 432160, done. remote: Compressing objects: 100% (102056/102056), done. remote: Total 432160 (delta 323116), reused 432037 (delta 323000) Receiving objects: 100% (432160/432160), 153.81 MiB | 8.54 MiB/s, done. Resolving deltas: 100% (323116/323116), done. Checking connectivity... done.
Если не задана конкретная ветвь репозитория или тег, Git клонирует ветвь master в ее текущем состоянии. Информация о выборе ветви или указании тега приведена в параграфах 2.4.2. Выбор ветви в Poky и 2.4.3. Выбор в Poky по тегу, соответственно.
После создания локального репозитория можно проверить его состояние. В примере показана 1 ветвь master.
$ git status On branch master Your branch is up-to-date with 'origin/master'. nothing to commit, working directory clean $ git branch * master
Это говорит об идентичности локальной копии репозитория poky и его оригинала. При работе с локальной копией можно периодически использовать команду git pull ‐‐rebase для поддержки актуальности копии.
2.4.2. Выбор ветви в Poky
После клонирования репозитория poky вы получаете доступ ко всем его ветвям, каждая из которых уникальна и начинается от ветви master. Для просмотра и использования файлов той или иной ветви нужно узнать ее имя, а затем переключиться (check out) на эту ветвь. Переключение на определенную ветвь по имени предоставляет доступ к текущему состоянию файлов этой ветви. Дальнейшая разработка будет выполняться применительно к файлам выбранной ветви.
- Переход в каталог Poky. При наличии локальной копии репозитория poky Git, перейдите в соответствующий каталог. Создание локальной копии репозитория описано в параграфе 2.4.1. Клонирование репозитория poky.
- Определение ветвей репозитория.
$ git branch -a * master remotes/origin/1.1_M1 remotes/origin/1.1_M2 remotes/origin/1.1_M3 remotes/origin/1.1_M4 remotes/origin/1.2_M1 remotes/origin/1.2_M2 remotes/origin/1.2_M3 ... remotes/origin/pyro remotes/origin/pyro-next remotes/origin/rocko remotes/origin/rocko-next remotes/origin/sumo remotes/origin/sumo-next remotes/origin/thud remotes/origin/thud-next remotes/origin/warrior
- Выбор ветви. Выберите интересующую ветвь и перейдите в нее. Например, для доступа к файлам выпуска YP 2.7.1 (Warrior) используется приведенная ниже команда.
$ git checkout -b warrior origin/warrior Branch warrior set up to track remote branch warrior from origin. Switched to a new branch 'warrior'
Команда переключает ваш репозиторий на ветвь warrior и сообщает об отслеживании восходящей ветви origin/warrior.
Ниже приведена команда, отображающая ветви вашего текущего локального репозитория. Выбранная для работы ветвь помечена звездочкой (*).
$ git branch master * warrior
2.4.3. Выбор в Poky по тегу
Подобно ветвям, восходящий репозиторий использует теги для маркировки определенных фиксаций (commit), связанных со значимыми изменениями ветвей (например, точка официального выпуска). Можно связать локальный репозиторий с таким тегом, используя процедуру, похожую на выбор ветви. Переход на ветвь по тегу обеспечивает стабильный набор файлов, на которые не влияют изменения ветви, к которой относится этот тег.
- Переход в каталог Poky. При наличии локальной копии репозитория poky Git, перейдите в соответствующий каталог. Создание локальной копии репозитория описано в параграфе 2.4.1. Клонирование репозитория poky.
- Получение тегов. Для выбора ветви по имени тега нужно извлечь теги из восходящего репозитория в локальную копию с помощью приведенной ниже команды.
$ git fetch --tags
- Список имен тегов с помощью команды git tag.
$ git tag 1.1_M1.final 1.1_M1.rc1 1.1_M1.rc2 1.1_M2.final 1.1_M2.rc1 ... yocto-2.5 yocto-2.5.1 yocto-2.5.2 yocto-2.5.3 yocto-2.6 yocto-2.6.1 yocto-2.6.2 yocto-2.7 yocto_1.5_M5.rc8
- Выбор ветви.
$ git checkout tags/yocto-2.7.1 -b my_yocto_2.7.1 Switched to a new branch 'my_yocto_2.7.1' $ git branch master * my_yocto_2.7.1
Команда создает локальную ветвь my_yocto_2.7.1 (основанную на фиксации в восходящем репозитории с указанным тегом) и переключается на нее. В этом примере предоставляются файлы, связанные с выпуском YP 2.7.1 в ветви warrior.
Глава 3. Базовые задачи
В этой главе описаны фундаментальные процедуры, такие как создание уровней, добавление новых программных пакетов, перенос программ на новое оборудование (добавление машины) и т. п. Описанные здесь процедуры часто применяются в процессе работы с YP.
3.1. Уровни и их создание
Система сборки OE поддерживает организацию метаданных с множеством уровней (layer), позволяющих разделить разные типы настроек. Базовая информация об уровнях YP приведена в разделе The Yocto Project Layer Model [1].
3.1.1. Создание своего уровня
Создать свой уровень в OE очень просто. YP поставляется с инструментами для создания уровней. В этом параграфе описаны этапы создания уровней для лучшего понимания процесса. Средства для создания уровней описаны в разделе Creating a New BSP Layer Using the bitbake-layers Script [5] и параграфе 3.1.8. Создание базового уровня с помощью сценария bitbake-layers.
Ниже описаны этапы создания уровня без использования специальных инструментов
- Просмотр имеющихся уровней. Перед созданием нового уровня нужно убедиться, что кто-либо уже не создал уровень с нужными вам метаданными. Можно просмотреть список OpenEmbedded Metadata Index, где указаны уровни, созданные сообществом OE, которые можно использовать в YP. Там может оказаться нужный или близкий к желаемому уровень.
- Создание каталога. Создайте каталог для нового уровня в области, не связанной каталогом исходных кодов YP (например, клонированным репозиторием poky). Хотя это не требуется, лучше использовать имена каталогов с префиксом meta-, например, meta-mylayer, meta-GUI_xyz, meta-mymachine.За редкими исключениями для имен уровней используют форму meta-root_name. Соблюдение этих соглашений об именах поможет предотвратить возникновение проблем, когда инструменты, компоненты или переменные «предполагают» имена уровней с префиксом meta-. Ярким примером служат файлы конфигурации, описанные на следующем этапе, где имена без префикса meta- добавляются в некоторые переменные, используемые в конфигурации.
- Создание файла конфигурации уровня. В новом каталоге уровня нужно создать файл conf/layer.conf. Проще всего для этого взять файл конфигурации имеющегося уровня, скопировать его и внести требуемые изменения.Файл meta-yocto-bsp/conf/layer.conf в YP Source Repositories демонстрирует синтаксис конфигурационного файла. Следует заменить yoctobsp идентификатором своего уровня (например, machinexyz для уровня с именем meta-machinexyz).
# We have a conf and classes directory, add to BBPATH BBPATH .= ":${LAYERDIR}" # We have recipes-* directories, add to BBFILES BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \ ${LAYERDIR}/recipes-*/*/*.bbappend" BBFILE_COLLECTIONS += "yoctobsp" BBFILE_PATTERN_yoctobsp = "^${LAYERDIR}/" BBFILE_PRIORITY_yoctobsp = "5" LAYERVERSION_yoctobsp = "4" LAYERSERIES_COMPAT_yoctobsp = "warrior"
- BBPATH – добавляет корневой каталог уровня в путь поиска BitBake. С помощью этой переменной BitBake находит файлы классов (.bbclass), конфигурационные файлы и файлы, включенные операторами include и require. BitBake в этих случаях использует первый файл, найденный по пути из переменной BBPATH. Это похоже на использование системной переменной PATH для поиска двоичных файлов. Поэтому рекомендуется применять для классов и конфигурации уникальные имена.
- BBFILES – определяет местоположение всех заданий уровня.
- BBFILE_COLLECTIONS – организует текущий уровень с помощью уникального идентификатора, используемого в системе сборки OE для указания этого уровня. В нашем примере идентификатор yoctobsp представляет контейнерный уровень meta-yocto-bsp.
- BBFILE_PATTERN – преобразуется в процессе разбора для представления имени каталога уровня.
- BBFILE_PRIORITY – задает приоритет для использования заданий уровня при поиске системой сборки OE заданий с одним именем из разных уровней.
- LAYERVERSION – задает номер версии для уровня. Этот номер можно применять для указания точной версии уровня в качестве зависимости при использовании переменной LAYERDEPENDS.
- LAYERSERIES_COMPAT – содержит список выпусков YP с которыми совместима данная версия. Это хороший способ указать, является ли ваш уровень текущим.
- Добавление содержимого в зависимости от типа уровня. Если уровень добавляет поддержку машины, добавляется ее конфигурация в каталог conf/machine/ внутри уровня. Если уровень добавляет правила distro указывается конфигурация дистрибутива в каталоге conf/distro/. При добавлении заданий их нужно помещать в подкаталоги recipes-* внутри уровня. Описание совместимой с YP иерархии уровней приведено в разделе Example Filesystem Layout [5].
- Необязательная проверка на совместимость. Если вы хотите получить разрешение на использование логотипа YP Compatibility для уровня или приложения, использующего ваш уровень, нужно выполнить этот этап. Подробная информация приведена в параграфе 3.1.3. Подтверждение совместимости уровня с YP.
3.1.2. Рекомендации по организации уровней
Для создания уровней, которые будут просты в поддержке и не станут мешать другим уровням, следуйте приведенным ниже рекомендациям.
- Избегайте полного перекрытия с заданиями из других уровней. Избегайте копирования задания целиком на свой уровень с последующим изменением задания. Лучше использовать файл добавления (.bbappend) для переопределения лишь тех частей исходного задания, которые требуют этого.
- Избегайте дублирования включаемых файлов. Применяйте файлы добавления (.bbappend) для каждого задания, которое использует включаемый файл. Для нового задания, которому нужны включаемые файлы, используйте путь относительно каталога исходного уровня для ссылки на файл. Например, следует указывать require recipes-core/package/file.inc, а не просто require file.inc. Если возникает перекрытие включаемых файлов, это может говорить о недостатках включаемого файла на уровне, к которому он изначально относится. В таких случаях следует попытаться устранить недостаток, чтобы включаемые файлы не перекрывались. Например, можно попросить сопровождающего включаемый файл человека добавить в файл нужные переменные, чтобы упростить требуемые переопределения частей.
- Структурируйте свои уровни. Аккуратное использование переопределений в файлах добавления и размещение относящихся к конкретным машинам файлов внутри своего уровня может гарантировать предотвращения использования при сборке ошибочных метаданных и негативного влияния на сборку других машин. Ниже приведено несколько примеров.
-
- Изменяйте переменные для поддержки разных машин. Предположим, что у вас есть уровень meta-one для сборок под машину one, применяется файл добавления base-files.bbappend и создана зависимость от foo в переменной DEPENDS = “foo”Зависимость создается в процессе любой сборки, включающей уровень meta-one. Однако эта зависимость может оказаться нужной не для всех машин. Например, предположим, что собирается образ для машины two и файл bblayers.conf включает уровень meta-one. В процессе сборки base-files для машины two будет добавлять зависимость от foo.Для того, чтобы изменения затрагивали только машину one используется переопределение в операторе DEPENDS_one = “foo”.Аналогичный подход применяется при использовании операций _append и _prepend
DEPENDS_append_one = " foo" DEPENDS_prepend_one = "foo "
В качестве реального примера ниже приведена строка из задания для gnutls, добавляющая зависимость от argp-standalone при сборке с библиотекой musl C.
DEPENDS_append_libc-musl = " argp-standalone"
Избегайте операций += и =+, а также _append и _prepend.
- Размещайте файлы для конкретных машин в каталогах этих машин. При наличии базового задания, такого как base-files.bb, которое содержит оператор SRC_URI, можно использовать файл добавления, заставляющий сборку использовать вашу версию файла. Например, файл добавление на вашем уровне meta-one/recipes-core/base-files/base-files.bbappend может расширять FILESPATH с использованием FILESEXTRAPATHS_prepend := “${THISDIR}/${BPN}:”Сборка для машины one возьмет ваш файл для машины при его наличии в meta-one/recipes-core/base-files/base-files/. Однако, если сборка выполняется для другой машины и файл bblayers.conf включает уровень meta-one, а ваш файл, связанный с машиной, расположен в месте, которое задано первым в FILESPATH, сборка для всех машин будет использовать этот связанный с машиной файл.Можно обеспечить использование машинозависимого файла для конкретной машины путем его размещения в связанном с этой машиной каталоге. Например, вместо размещения в каталоге meta-one/recipes-core/base-files/base-files/, как показано выше, файл помещается в каталог meta-one/recipes-core/base-files/base-files/one/. Это не только гарантирует использование файла при сборке для машины one, но и существенно ускоряет процесс сборки.Таким образом, следует поместить все файлы, указанные в SRC_URI в связанный с машиной каталог внутри вашего уровня, чтобы использовать эти файлы только в сборках для данной машины.
- Изменяйте переменные для поддержки разных машин. Предположим, что у вас есть уровень meta-one для сборок под машину one, применяется файл добавления base-files.bbappend и создана зависимость от foo в переменной DEPENDS = “foo”Зависимость создается в процессе любой сборки, включающей уровень meta-one. Однако эта зависимость может оказаться нужной не для всех машин. Например, предположим, что собирается образ для машины two и файл bblayers.conf включает уровень meta-one. В процессе сборки base-files для машины two будет добавлять зависимость от foo.Для того, чтобы изменения затрагивали только машину one используется переопределение в операторе DEPENDS_one = “foo”.Аналогичный подход применяется при использовании операций _append и _prepend
- Применение этапов YP Compatibility. Если вы хотите получить право использовать логотип Yocto Project Compatibility со своим уровнем или приложением нужно выполнить действия, описанные в параграфе 3.1.3. Подтверждение совместимости уровня с YP.
- Выполнение соглашений по именованию уровней. Сохраняйте свои уровни в репозитории Git, используя формат meta-layer_name.
- Группируйте свои уровни локально. Клонируйте свой репозиторий вместе с другими мета-каталогами из дерева исходных кодов.
3.1.3. Подтверждение совместимости уровня с YP
При создании уровня для использования в YP полезно убедиться, что этот уровень хорошо взаимодействует с имеющимися уровнями YP (т. е. с уровнями, совместимыми с YP). Обеспечение совместимости упрощает использование уровня другими членами сообщества YP и позволяет использовать Yocto Project Compatible Logo. Знак Yocto Project Compatible Logo могут использовать только организации, являющиеся членами YP. Информация о членстве в YP представлена на сайте YP.
Программа совместимости YP включает процесс применения уровня, который запрашивает использование Yocto Project Compatibility Logo для уровня и приложений, состоящий из двух частей.
- Успешное прохождение на уровне сценария (yocto-check-layer), проверяющего соблюдение ограничений, основанных на опыте использования уровней в реальном мире, и прохождение известных ловушек. Результат PASS в конце сценария говорит о совместимости уровня.
- Заполнение заявки (https://www.yoctoproject.org/webform/yocto-project-compatible-registration).
Для получения права использовать логотип, нужно выполнить несколько условий:
- иметь возможность установить флажок, показывающий результат PASS при запуске сценария проверки;
- ответить Yes на вопросы заявки и предоставить приемлемое разъяснение для всех ответов No;
- быть членом Yocto Project Member Organization.
В оставшейся части этого раздела представлена информация о регистрационной форме и сценарии yocto-check-layer.
3.1.3.1. Применение программы Yocto Project Compatible
Используйте форму для подачи заявки на утверждение вашего уровня. После утверждения вы сможете указывать Yocto Project Compatibility Logo для уровня и использующих его приложений. При заполнении заявки следуйте инструкциям.
- Контактные данные. Предоставьте сведения для контактов с вами в требуемых полях. Укажите также версии выпусков YP, с которыми совместим ваш уровень.
- Критерии согласия. Укажите Yes или No для каждой записи в списке вопросов. В конце заявки имеется место для пояснений по всем пунктам, где вы ответили No.
- Рекомендации. Ответьте на вопросы, относящиеся к ядру Linux и результатам сборки.
3.1.3.2. Сценарий yocto-check-layer
Сценарий yocto-check-layer позволяет оценить совместимость вашего уровня с YP. Сценарием следует воспользоваться до подачи заявки, описанной в предыдущем параграфе. Для успешной обработки заявки нужно обеспечить получение результата PASS при работе сценария.
Сценарий включает 3 области проверки – COMMON, BSP и DISTRO. Например, для уровня дистрибутива (DISTRO) должны пройти тесты COMMON и DISTRO. Если ваш уровень является BSP, нужно пройти тесты COMMON и BSP.
Команды для запуска сценария приведены ниже.
$ source oe-init-build-env $ yocto-check-layer your_layer_directory
В качестве your_layer_directory нужно указать реальное имя каталога с вашим уровнем.
Сценарий определяет тип уровня и запускает для него соответствующие тесты. Обзор тестов представлен ниже.
- common.test_readme проверяет наличие файла README на уровне и наличие содержимого в файле.
- common.test_parse проверяет возможность BitBake проанализировать файл без ошибок (bitbake -p).
- common.test_show_environment проверяет наличие ошибок в глобальном окружении и окружении для задания (bitbake -e).
- common.test_signatures проверяет отсутствие на уровнях BSP и DISTRO заданий, меняющих подписи.
- bsp.test_bsp_defines_machines проверяет наличие конфигураций для машин на уровне BSP.
- bsp.test_bsp_no_set_machine проверяет, что уровень BSP не задает машину при его добавлении.
- distro.test_distro_defines_distros проверяет наличие конфигураций на уровне DISTRO.
- distro.test_distro_no_set_distro проверяет, что уровень DISTRO не задает дистрибутив при своем добавлении.
3.1.4. Включение уровня
Перед началом использования уровня системой сборки OE уровень нужно включить, для чего просто добавляется путь к этому уровню в переменную BBLAYERS файла conf/bblayers.conf, хранящегося в каталоге сборки. Ниже приведен пример добавления уровня meta-mylayer.
# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf # changes incompatibly POKY_BBLAYERS_CONF_VERSION = "2" BBPATH = "${TOPDIR}" BBFILES ?= "" BBLAYERS ?= " \ /home/user/poky/meta \ /home/user/poky/meta-poky \ /home/user/poky/meta-yocto-bsp \ /home/user/poky/meta-mylayer \ "
BitBake анализирует каждый файл conf/layer.conf сверху вниз в соответствии с переменной BBLAYERS в файле conf/bblayers.conf. При обработке каждого файла conf/layer.conf программа BitBake добавляет задания, классы и конфигурации, содержащиеся в указанном уровне.
3.1.5. Использование файлов .bbappend на уровне
Задание, добавляющее метаданные в другое задание, называется в BitBake файлом добавления. Эти файлы используют расширение .bbappend, тогда как файлы, в которые метаданные добавляются, – расширение .bb.
Можно применять файл .bbappend на своем уровне или менять содержимое задания на другом уровне без копирования таких заданий на свой уровень. Файлы .bbappend размещаются на вашем уровне, тогда как файл .bb, в который добавляются метаданные, может размещаться на другом уровне.
Возможность добавлять информацию в имеющиеся задания не только избавляет от дублирования, но и автоматически переносит изменения заданий других уровней на ваш уровень. Если бы вы копировали эти задания, пришлось бы вручную вносить изменения.
При создании файла добавления нужно использовать корневое имя соответствующего файла задания. Например, файл добавления someapp_2.7.1.bbappend должен применяться к файлу someapp_2.7.1.bb. Это означает зависимость исходного задания и файла добавления от номера версии. Если задание переименовано с учетом новой версии, нужно будет обновить и, возможно, переименовать соответствующий файл .bbappend. В процессе сборки BitBake выводит сообщения об ошибках при запуске, если обнаруживается, что для файла .bbappend нет задания с соответствующим именем. Обработка таких ошибок рассмотрена в описании переменной BB_DANGLINGAPPENDS_WARNONLY.
Рассмотрим в качестве примера задание formfactor и соответствующий файл добавления formfactor, хранящиеся в дереве исходных кодов. Ниже показан основной файл задания formfactor_0.0.bb, хранящийся на уровне meta в каталоге meta/recipes-bsp/formfactor.
SUMMARY = "Device formfactor information" SECTION = "base" LICENSE = "MIT" LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420" PR = "r45" SRC_URI = "file://config file://machconfig" S = "${WORKDIR}" PACKAGE_ARCH = "${MACHINE_ARCH}" INHIBIT_DEFAULT_DEPS = "1" do_install() { # Install file only if it has contents install -d ${D}${sysconfdir}/formfactor/ install -m 0644 ${S}/config ${D}${sysconfdir}/formfactor/ if [ -s "${S}/machconfig" ]; then install -m 0644 ${S}/machconfig ${D}${sysconfdir}/formfactor/ fi }
Отметим в этом файле переменную SRC_URI, которая указывает системе сборки OE места поиска файлов при сборке.
Ниже показано содержимое файла добавления formfactor_0.0.bbappend с уровня Raspberry Pi BSP Layer называющегося meta-raspberrypi. Файл хранится на этом уровне в каталоге recipes-bsp/formfactor.
FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
По умолчанию система сборки применяет для поиска файлов переменную FILESPATH. Этот файл добавления расширяет сферу поиска путем установки переменной FILESEXTRAPATHS. Задание этой переменной в файле .bbappend является наиболее надежным и рекомендуемым методом добавления каталогов в путь поиска при сборке.
Оператор в этом примере расширяет переменную путем добавления в конце ${THISDIR}/${PN}, преобразуемого в каталог formfactor в том же каталоге, где хранится файл добавления (meta-raspberrypi/recipes-bsp/formfactor). Это предполагает наличие структуры каталогов поддержки для файлов и исправлений (patch), применяемых уровнем.
Использование оператора непосредственного преобразования := в этом случае важно, поскольку указывается текущий каталог THISDIR. Двоеточие в конце обеспечивает отделение последующих элементов.
BitBake автоматически определяет значение переменной THISDIR и вам не следует устанавливать его. Использование _prepend с переменной FILESEXTRAPATHS обеспечивает добавление пути поиска в начало имеющегося списка.
Не все файлы .bbappend добавляют новые файлы, многие просто добавляют опции сборки (например, systemd). В таких случаях файл добавления не будет включать оператора FILESEXTRAPATHS.
3.1.6. Приоритизация уровня
Каждый уровень имеет определенный приоритет, который определяет предпочтительность уровня при наличии одноименных файлов заданий на нескольких уровнях. В таких случаях берется задание уровня с высшим приоритетом. Значения приоритета влияют также на порядок применения файлов .bbappend к одному заданию. Приоритет можно задать вручную или позволить рассчитать его системе сборки на основе зависимостей между уровнями.
Для задания приоритета вручную служит переменная BBFILE_PRIORITY с добавлением корневого файла уровня.
BBFILE_PRIORITY_mylayer = "1"
Возможны ситуации, когда задание с меньшим номером версии PV на уровне будет иметь более высокий приоритет.
Уровень приоритета не влияет на порядок предпочтения файлов .conf и .bbclass, но это может появиться в будущих версиях BitBake.
3.1.7. Управление уровнями
Можно использовать инструмент управления уровнями bitbake-для просмотра структуры заданий в проекте с множеством уровней. Возможность увидеьб отчет о настроенных уровнях с их путями и приоритетами, файлами .bbappend и заданиями, к которым они относятся, может оказать помощь при поиске неполадок.
Информацию о работе с инструментом можно получить по команде
$ bitbake-layers --help NOTE: Starting bitbake server... usage: bitbake-layers [-d] [-q] [-F] [--color COLOR] [-h] <subcommand> ... BitBake layers utility optional arguments: -d, --debug Enable debug output -q, --quiet Print only errors -F, --force Force add without recipe parse verification --color COLOR Colorize output (where COLOR is auto, always, never) -h, --helpshow this help message and exit subcommands: <subcommand> show-layers show current configured layers. show-overlayed list overlayed recipes (where the same recipe exists in another layer) show-recipes list available recipes, showing the layer they are provided by show-appends list bbappend files and recipe files they apply to show-cross-depends Show dependencies between recipes that cross layer boundaries. add-layer Add one or more layers to bblayers.conf. remove-layer Remove one or more layers from bblayers.conf. flatten flatten layer configuration into a separate output directory. layerindex-fetch Fetches a layer from a layer index along with its dependent layers, and adds them to conf/bblayers.conf. layerindex-show-depends Find layer dependencies from layer index. create-layer Create a basic layer Use bitbake-layers <subcommand> --help to get help on a specific command
Краткие описания команд приведены ниже.
help
Выводит общую справку или информацию о конкретной команде.
show-layers
Показывает настроенные в данный момент уровни.
show-overlayed
Показывает перекрывающиеся задания, т. е. одноименные задания на разных уровнях.
show-recipes
Показывает задания и уровни, к которым они относятся.
show-appends
Показывает файлы .bbappend и задания, к которым они относятся.
show-cross-depends
Перечисляет зависимости между заданиями разных уровней.
add-layer
Добавляет уровень в файл bblayers.conf.
remove-layer
Удаляет уровень из файла bblayers.conf.
flatten
Собирает конфигурацию уровня с отельный выходной каталог. При сборке конфигурации создается «плоский» каталог с содержимым всех уровней и удалением всех перекрывающихся заданий и файлов .bbappend для них. Возможно после этого потребуется некоторая очистка вручную, как описано ниже.
- Не являющиеся заданиями файлы (например, исправления) переписываются и команда flatten выдает для них предупреждения.
- Все, что выходит за пределы обычной установки уровня, добавляется в файл layer.conf. Используется лишь файл layer.conf уровня с наименьшим приоритетом.
- Переписанные и добавленные элементы из файлов .bbappend должны быть очищены. Содержимое каждого файла .bbappend в конечном итоге попадает в «плоское» задание. Однако при наличии добавленных или измененных значений переменных потребуется самостоятельно привести их в порядок. Рассмотрим пример, где команда bitbake-layers добавляет строку #### bbappended … (чтобы понять, откуда берутся следующие строки).
... DESCRIPTION = "A useful utility" ... EXTRA_OECONF = "--enable-something" ... #### bbappended from meta-anotherlayer #### DESCRIPTION = "Customized utility" EXTRA_OECONF += "--enable-somethingelse"
В идеальном случае это следует привести к виду, показанному ниже.
... DESCRIPTION = "Customized utility" ... EXTRA_OECONF = "--enable-something --enable-somethingelse" ...
layerindex-fetch
Извлекает уровень из списка уровней вместе с зависимыми уровнями и добавляет их в файл conf/bblayers.conf.
layerindex-show-depends
Определяет зависимости уровня из списка уровней.
create-layer
Создает базовый уровень.
3.1.8. Создание базового уровня с помощью сценария bitbake-layers
Сценарий bitbake-layers с параметром create-layer упрощает создание нового уровня общего назначения. Для использования уровня в системе сборки OE нужно добавить этот уровень в конфигурационный файл bblayers.conf (см. 3.1.9. Добавление уровня с помощью сценария bitbake-layers). По умолчанию bitbake-layers create-layer создает уровень со следующими параметрами:
- приоритет уровня 6;
- каталог conf содержит файл layer.conf;
- создается каталог recipes-example с подкаталогом example, содержащим файл задания example.bb;
- файл COPYING.MIT с лицензией (сценарий предполагает использование лицензии MIT, типичной для большинства уровней), относящейся к содержимому уровня;
- файл README с описанием содержимого нового уровня.
В простейшем случае для создания уровня можно использовать приведенную ниже команду, которая создает в текущем каталоге уровень, имя которого соответствует параметру your_layer_name.
$ bitbake-layers create-layer your_layer_name
Например, приведенная ниже команда создаст уровень meta-scottrif в домашнем каталоге.
$ cd /usr/home $ bitbake-layers create-layer meta-scottrif NOTE: Starting bitbake server... Add your new layer with 'bitbake-layers add-layer meta-scottrif'
Если нужно установить для уровня приоритет, отличный от 6, можно использовать опцию ‐‐priority или отредактировать значение BBFILE_PRIORITY в файле conf/layer.conf после его создания сценарием. Если нужно изменить имя примера файла задания, его можно задать с помощью опции ‐‐example-recipe-name.
Простейшим способом разобраться с командой bitbake-layers create-layer является ее использование. Для получения справки о работе со сценарием введите команду
$ bitbake-layers create-layer --help NOTE: Starting bitbake server... usage: bitbake-layers create-layer [-h] [--priority PRIORITY] [--example-recipe-name EXAMPLERECIPE] layerdir Create a basic layer positional arguments: layerdir Layer directory to create optional arguments: -h, --helpshow this help message and exit --priority PRIORITY, -p PRIORITY Layer directory to create --example-recipe-name EXAMPLERECIPE, -e EXAMPLERECIPE Filename of the example recipe
3.1.9. Добавление уровня с помощью сценария bitbake-layers
Создав уровень, нужно добавить его в свой файл bblayers.conf. Это будет позволяет системе сборки OE узнать об этом уровне, чтобы искать в нем метаданные. Для добавления уровня служит команда bitbake-layers add-layer your_layer_name.
Ниже приведен пример добавления уровня meta-scottrif в файл конфигурации. После команды добавления уровня использована команда, показывающая уровни из вашего файла bblayers.conf.
$ bitbake-layers add-layer meta-scottrif NOTE: Starting bitbake server... Parsing recipes: 100% |##########################################################| Time: 0:00:49 Parsing of 1441 .bb files complete (0 cached, 1441 parsed). 2055 targets, 56 skipped, 0 masked, 0 errors. $ bitbake-layers show-layers NOTE: Starting bitbake server... layer path priority ========================================================================== meta /home/scottrif/poky/meta 5 meta-poky /home/scottrif/poky/meta-poky 5 meta-yocto-bsp /home/scottrif/poky/meta-yocto-bsp 5 workspace /home/scottrif/poky/build/workspace 99 meta-scottrif /home/scottrif/poky/build/meta-scottrif 6
Добавление уровня в этот файлпозволяет системе сборки найти уровень в процессе сборки. Система сборки просматривает уровни от начала списка к концу.
3.2. Настройка образов
Образы можно настраивать с учетом реальных требований, как описано в этом параграфе.
3.2.1. Настройка с помощью local.conf
Одним из простейших способов настройки образа является добавление пакетов через файл local.conf. Поскольку область действия этого файла ограничена, метод обычно позволяет лишь добавлять пакеты и недостаточно гибок для создания своего настраиваемого образа. При добавлении пакетов с использованием локальных переменных нужно отдавать себе отчет в том, что эти изменения влияют на каждую сборку и, следовательно, на все создаваемые образы.
Для добавления пакета с использованием локального файла конфигурации служит переменная IMAGE_INSTALL с оператором _append.
IMAGE_INSTALL_append = " strace"
Важно соблюдать показанный в примере синтаксис, в частности пробел перед именем добавляемого пакета, поскольку оператор _append пробелы (разделители) не добавляет. Кроме того, нужно использовать _append, а не оператор +=, если вы не хотите столкнуться с проблемой упорядочения. Показанный вариант безоговорочно добавляет значение в конец имеющегося списка, что позволяет предотвратить связанные с упорядочением проблемы в результате использования переменной в образах и файлах заданий с операторами вида ?=.
Как было отмечено, IMAGE_INSTALL_append влияет на все образы, но можно расширить синтаксис, задавая применение переменной лишь для конкретного образа в форме IMAGE_INSTALL_append_pn-core-image-minimal = ” strace”.
Можно добавлять пакеты похожим способом через переменную CORE_IMAGE_EXTRA_INSTALL, которая воздействует только на образы core-image-*.
3.2.2. Настройка с помощью IMAGE_FEATURES и EXTRA_IMAGE_FEATURES
Другим вариантом является использование переменных IMAGE_FEATURES и EXTRA_IMAGE_FEATURES. Эти переменные близки по назначению, лучше пользоваться IMAGE_FEATURES из задания и EXTRA_IMAGE_FEATURES из файла local.conf в каталоге сборки.
Разобраться с настройками поможет файл meta/classes/core-image.bbclass. Этот класс указывает доступные свойства IMAGE_FEATURES, большинство которых отображается на группы пакетов, а некоторые (например, debug-tweaks и read-only-rootfs) задают общие настройки конфигурации.
Содержимое IMAGE_FEATURES просматривается а затем свойства отображаются или настраиваются соответствующим образом. На основе этой информации система сборки автоматически добавляет нужные пакеты и конфигурации в переменную IMAGE_INSTALL. Фактически это включает дополнительные функции путем расширения классов или создания собственного класса для использования с файлами образов .bb.
Следует использовать переменную EXTRA_IMAGE_FEATURES из локального файла конфигурации. Использование отдельной области, откуда можно управлять свойствами через эту переменную поможет избежать переопределения свойств в задании для образа, которые указаны в переменной IMAGE_FEATURES. Значение переменной EXTRA_IMAGE_FEATURES добавляется к IMAGE_FEATURES в файле meta/conf/bitbake.conf.
Для иллюстрации этих возможностей рассмотрим пример выбора сервера SSH. YP включает два сервера SSH – Dropbear и OpenSSH. Первый является минимальным сервером SSH подходящим для сред с ограниченными ресурсами, а OpenSSH является широко распространенным стандартным сервером SSH. По умолчанию для образа core-image-sato настроено использование Dropbear, а образы core-image-full-cmdline и core-image-lsb включают OpenSSH. Образ core-image-minimal не поддерживает сервер SSH. Можно настроить свой образ и изменить принятые по умолчанию значения. Для этого следует изменить переменную IMAGE_FEATURES или EXTRA_IMAGE_FEATURES в файле local.conf, указав пакет ssh-server-dropbear или ssh-server-openssh. Полный список свойств образов, включенных в YP, приведен в разделе Images [3].
3.2.3. Настройка с помощью файлов .bb
Можно также настроить образ, создав свое задание, определяющее дополнительные программы для образа
IMAGE_INSTALL = "packagegroup-core-x11-base package1 package2"
inherit core-image
Указание программ через пользовательское задание обеспечивает полный контроль содержимого образа. Важно указывать корректные имена пакетов в переменной IMAGE_INSTALL, используя нотацию OE, а не (например, glibc-dev, а не libc6-dev).
Другим вариантом создания своего образа служит копирование и изменение имеющегося образа. Например, можно создать образ на основе core-image-sato с добавлением пакета strace, скопировав файл meta/recipes-sato/images/core-image-sato.bb и добавив в конце копии строку IMAGE_INSTALL += “strace”.
3.2.4. Настройка с помощью пользовательских групп пакетов
Для комплексных образов лучшим способом настройки является создание группы заданий, которая будет применяться при сборке образов. Примером такой группы служит meta/recipes-core/packagegroups/packagegroup-base.bb. В этом задании переменная PACKAGES указывает группы создаваемых пакетов. Оператор inherit packagegroup задает принятые по умолчанию значения и автоматически добавляет пакеты -dev, -dbg и -ptest для каждого пакета, указанного в PACKAGES. Пакеты с наследованием следует размещать в верхней части задания и обязательно до оператора PACKAGES. Для каждого пакета из PACKAGES можно использовать записи RDEPENDS и RRECOMMENDS для предоставления списков пакетов, которые следует включать в родительский пакет. Примеры этого имеются в задании packagegroup-base.bb.
Ниже приведен краткий пример, иллюстрирующий основные части.
DESCRIPTION = "My Custom Package Groups" inherit packagegroup PACKAGES = "\ packagegroup-custom-apps \ packagegroup-custom-tools \ " RDEPENDS_packagegroup-custom-apps = "\ dropbear \ portmap \ psplash" RDEPENDS_packagegroup-custom-tools = "\ oprofile \ oprofileui-server \ lttng-tools" RRECOMMENDS_packagegroup-custom-tools = "\ kernel-module-oprofile"
В этом примере создается две группы пакетов с указанием действительных и рекомендуемых зависимостей – packagegroup-custom-apps и packagegroup-custom-tools. Для сборки образа с использованием этой группы пакетов нужно добавить packagegroup-custom-apps и/или packagegroup-custom-tools в переменную IMAGE_INSTALL.
3.2.5. Настройка имени хоста для образа
По умолчанию настроенной имя хоста (/etc/hostname) в образе совпадает с именем машины. Например, для MACHINE = qemux86, настроенным именем хоста в файле /etc/hostname будет qemux86.
Можно изменить это имя, указав его в переменной hostname в задании base-files с помощью файла добавления или конфигурационного файла. Ниже приведен пример с файлом добавления.
hostname="myhostname"
В файле конфигурации замена будет иметь вид hostname_pn-base-files = “myhostname”.
Смена принятого по умолчанию значения hostname может быть полезна в нескольких случаях. Например, может потребоваться расширенное тестирования образа, где нужно будет отличать тестируемые варианты от типового. В таком случае можно сменить имя хоста, например, на testme. Если переменная не установлена, у образа не будет заданного по умолчанию в файловой системе имени, как показано ниже.
hostname_pn-base-files = ""
Отсутствие заданного по умолчанию имени удобно в средах с динамическим назначением имен хостов.
3.3. Создание новых заданий
Задания (файлы .bb) являются важнейшими компонентами среды YP. Каждая программная компонента создается системой сборки OE на основе определяющего ее задания. В этом разделе описаны все аспекты работы с заданиями. Дополнительную информацию о работе с заданиями можно найти в разделе Required [3].
3.3.1. Обзор
На рисунке показан базовый процесс создания нового задания.
3.3.2. Нахождение или автоматическое создание базового задания
Всегда можно создать новое задание «с нуля», однако есть 3 варианта, ускоряющие подготовку новых заданий:
- devtool add – команда, помогающая создать задание и среду разработки;
- recipetool create – команда YP для автоматизированного создания заданий на основе файлов исходного кода;
- имеющиеся задания можно скопировать и изменить в соответствии с задачами.
Синтаксис заданий описан в параграфе 3.3.23. Синтаксис заданий.
3.3.2.1. Создание с помощью devtool add
Команда devtool add использует такую же логику автоматического создания заданий, как описанная ниже команда recipetool create. Дополнительно devtool add организует окружение, упрощающее правку (patch) исходных кодов и внесение изменений в задания, которые часто требуются при добавлении заданий для сборки новой части кода. Полное описание команды devtool add приведено в разделе A Closer Look at devtool add [2].
3.3.2.2. Создание с помощью recipetool create
Команда recipetool create автоматизирует создание базового задания на основе набора файлов с исходным кодом. Когда можно извлечь или указать исходные файлы, команда будет создавать задание и автоматически настраивать все параметры сборки в нем. Например, приложение может создаваться с помощью autotools и подготовка базового задания с помощью recipetool приведет к включению в задание зависимостей, лицензионных требований и контрольных сумм.
Запуск команды выполняется из каталога сборки после выполнения сценария настройки окружения (oe-init-build-env). Для получения справки о работе с инструментом служит команда
$ recipetool -h NOTE: Starting bitbake server... usage: recipetool [-d] [-q] [--color COLOR] [-h] <subcommand> ... OpenEmbedded recipe tool options: -d, --debug Enable debug output -q, --quiet Print only errors --color COLOR Colorize output (where COLOR is auto, always, never) -h, --help show this help message and exit subcommands: create Create a new recipe newappend Create a bbappend for the specified target in the specified layer setvar Set a variable within a recipe appendfile Create/update a bbappend to replace a target file appendsrcfiles Create/update a bbappend to add or replace source files appendsrcfile Create/update a bbappend to add or replace a source file Use recipetool <subcommand> --help to get help on a specific command
Команда recipetool create -o OUTFILE создает базовое задание с именем OUTFILE и корректно размещает его на уровне, содержащем исходные файлы.
Ниже приведен синтаксис для подготовки на базе кодов source задания, размещаемого на уровне исходного кода.
recipetool create -o OUTFILE source
Следующая команда создает задание с использованием кода, извлекаемого из source. Этот код помещается на свой уровень, указанный EXTERNALSRC.
recipetool create -o OUTFILE -x EXTERNALSRC source
Еще одна команда создает задание на основе source, указывая recipetool необходимость создания отладочной информации. Задание размещается в имеющемся уровне исходных кодов.
recipetool create -d -o OUTFILE source
3.3.2.3. Нахождение и использование похожего задания
Перед созданием нового задания зачастую полезно ознакомиться с имеющимися и выбрать среди них подходящее в качестве основы. Сообщества YP и OE поддерживают множество заданий, среди которых наверняка найдется подходящий образец. Список имеющихся заданий доступен по ссылке OpenEmbedded Layer Index.
Работа с имеющимся заданием и шаблоном служит логичным началом процесса. Ниже рассмотрены особенности обоих методов.
- Поиск и изменение похожего задания подходит, когда вы хорошо знакомы с имеющимися заданиями, но мало полезен для новичков. Некоторый риск при использовании данного метода связан с возможным наличием в выбранном задании области, которая совсем не связана с вашими задачами и может потребоваться ее создание с нуля. Однако все такие риски связаны с недостаточным знакомством с имеющимися заданиями.
- Использование шаблона задания. Если по какой-то причине вы не хотите использовать recipetool и не нашли подходящего в качестве образца задания, можно воспользоваться приведенной ниже структурой, включающей основные разделы нового задания.
DESCRIPTION = "" HOMEPAGE = "" LICENSE = "" SECTION = "" DEPENDS = "" LIC_FILES_CHKSUM = "" SRC_URI = ""
3.3.3. Сохранение и именование заданий
Базовое задание следует поместить на свой уровень и дать ему подходящее имя. Корректное размещение заданий позволит системе сборки OE находить их при использовании BitBake для обработки.
- Сохранение заданий. Система сборки OE находит задания с помощью файла conf/layer.conf на вашем уровне и переменной BBFILES. Эта переменная задает путь поиска заданий для системы сборки, как показано ниже.
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \ ${LAYERDIR}/recipes-*/*/*.bbappend"
Поэтому следует сохранять задания внутри своего уровня, чтобы их можно было найти. Информация о структуре уровней приведена в разделе 3.1. Уровни и их создание.
- Именование заданий. При выборе имен для заданий используйте формат basename_version.bb.Используйте символы нижнего регистра и не включайте в имена зарезервированные суффиксы -native, -cross, -initial, -dev, пока это не обусловлено применением задания. Ниже приведено несколько примеров.
cups_1.7.0.bb gawk_4.0.2.bb irssi_0.8.16-rc1.bb
3.3.4. Запуск сборки задания
Подготовка нового задания обычно происходит в несколько итераций, требующих использования BitBake для многократной обработки задания с целью нахождения и добавления информации в файл задания. Предположим, что вы воспользовались сценарием настройки среды сборки (oe-init-build-env) и текущим является сборочный каталог, а для обработки задания применяется BitBake. Для запуска достаточно указать базовое имя задания (basename).
$ bitbake basename
В процессе работы система сборки OE создает временный рабочий каталог для каждого задания (${WORKDIR}), в котором хранятся извлеченные файлы исходного кода, журналы работы (log), промежуточные файлы компиляции, файлы пакетов и т. п. Путь к временному рабочему каталогу каждого задания зависит от рабочего контекста. Проще всего узнать этот путь с помощью команды bitbake -e basename | grep ^WORKDIR=.
Предположим, например, что каталогом верхнего уровня для исходных кодов служит poky, сборочным каталогом – poky/build, а целевой системой является qemux86-poky-linux. Пусть задание называется foo_1.3.0.bb. В этом случае рабочим каталогом для сборки пакета будет poky/build/tmp/work/qemux86-poky-linux/foo/1.3.0-r0.
Внутри этого каталога можно найти такие поддкаталоги, как image, packages-split и temp. После завершения сборки можно рассмотреть их содержимое для оценки результатов сборки. Журналы сборки для каждого задания можно найти в каталоге temp этого задания (например, poky/build/tmp/work/qemux86-poky-linux/foo/1.3.0-r0/temp). Файлы журналов будут названы log.taskname (например, log.do_configure, log.do_fetch, log.do_compile).
Дополнительная информация о процессе сборки приведена в разделе The Yocto Project Development Environment [1].
3.3.5. Извлечение кода
Первым делом задание должно указать способ извлечения исходных файлов. Выборка исходного кода определяется в основном переменной SRC_URI. Задание должно включать переменную SRC_URI, указывающую место размещения исходных кодов. Графическое представление мест размещения исходных кодов дано в разделе Sources [1].
Задача do_fetch использует префикс каждого элемента переменной SRC_URI для определения сборщика, применяемого для получения исходных кодов. Задача do_patch использует эту переменную после извлечения исходных кодов для применения правок (patch). Система сборки применяет FILESOVERRIDES для сканирования каталогов с локальными файлами, указанных в SRC_URI.
Переменная SRC_URI в задании должна указывать каждое уникальное место размещения исходного кода. Рекомендуется не задавать жестко пути в URL, указанных в SRC_URI, а пользоваться переменной ${PV}, которая сообщает сборщику версию, указанную именем файла задания. Такое указание версии упрощает обновления задания , сводя его к простому переименованию файла в соответствии с новой версией. Ниже приведен пример из задания meta/recipes-devtools/cdrtools/cdrtools-native_3.01a20.bb, содержащего исходные файлы из архива.
SRC_URI = "ftp://ftp.berlios.de/pub/cdrecord/alpha/cdrtools-${PV}.tar.bz2"
Файлы, указанные в SRC_URI, имена которых имеют типовое расширение (например, .tar, .tar.gz, .tar.bz2, .zip), извлекаются автоматически задачей do_unpack. Другой пример указания файлов приведен в параграфе 3.3.21.2. Пакеты с автоматической настройкой.
Другим способом указания исходных файлов служит SCM. Для репозиториев Git нужно задать SRCREV и следует включить в PV номер выпуска с помощью SRCPV, как показано ниже для meta/recipes-kernel/blktrace/blktrace_git.bb
SRCREV = "d6918c8832793b4205ed3bfede78c2f915c23385" PR = "r6" PV = "1.0.5+git${SRCPV}" SRC_URI = "git://git.kernel.dk/blktrace.git \ file://ldflags.patch"
Если SRC_URI содержит URL, указывающие отдельные файлы, извлеченные с удаленного сервера, который не является системой контроля версий, BitBake пытается проверить файлы по контрольным суммам из задания, чтобы убедиться в отсутствии изменений в файлах с момента подготовки задания. Применяются контрольные суммы SRC_URI[md5sum] и SRC_URI[sha256sum]. Если переменная SRC_URI включает несколько URL (кроме SCM URL), нужно обеспечить проверку md5 и sha256 для каждого URL. В таких случаях подставляется каждый URL как часть SRC_URI, а затем используется при проверке контрольных сумм, как показано ниже
SRC_URI = "${DEBIAN_MIRROR}/main/a/apmd/apmd_3.2.2.orig.tar.gz;name=tarball \ ${DEBIAN_MIRROR}/main/a/apmd/apmd_${PV}.diff.gz;name=patch" SRC_URI[tarball.md5sum] = "b1e6309e8331e0f4e6efd311c2d97fa8" SRC_URI[tarball.sha256sum] = "7f7d9f60b7766b852881d40b8ff91d8e39fccb0d1d913102a5c75a2dbb52332d" SRC_URI[patch.md5sum] = "57e1b689264ea80f78353519eece0c92" SRC_URI[patch.sha256sum] = "7905ff96be93d725544d0040e425c42f9c05580db3c272f11cff75b9aa89d430"
Корректные значения md5 и sha256 могут быть доступны вместе с другими подписями (md5, sha1, sha256, GPG и т. п.) на странице загрузки исходных файлов. Поскольку система сборки OE поддерживает только sha256sum и md5sum, другие контрольные суммы придется проверять вручную.
Если при попытке сборки задания контрольные суммы SRC_URI не указаны или отличаются от указанных, система сборки будет выдавать ошибку для каждой пропущенной или неверной контрольной суммы. В сообщениях будет указываться реальная контрольная сумма файла. После обеспечения корректных контрольных сумм можно скопировать их в задание и запустить сборку снова.
Заключительный пример слегка взят из задания unicode/rxvt-unicode_9.20.bb. Оператор SRC_URI указывает множество файлов для задания – архивы, исправления, файлы рабочего стола и пиктограммы.
SRC_URI = "http://dist.schmorp.de/rxvt-unicode/Attic/rxvt-unicode-${PV}.tar.bz2 \ file://xwc.patch \ file://rxvt.desktop \ file://rxvt.png"
При указании локальных файлов с помощью file:// URI система сборки извлекает файлы с локальной машины. Пути задаются относительно переменной FILESPATH и поиск выполняется в каталогах в порядке ${BP}, ${BPN} и FILES. Каталоги предполагаются расположенными в каталоге, где размещается файл задания или добавления. Пример поиска приведен в параграфе 3.3.21.1. Пакет с одним файлом .c.
В первом примере был указан patch-файл. Такие файлы обычно имеют расширение .patch или .diff, но могут применять и суффиксы сжатых архивов, такие как diff.gz или patch.bz2. Система сборки будет автоматически применять исправления из таких файлов, как описано в параграфе 3.3.7. Применение исправлений для кода.
3.3.6. Распаковка кода
В процессе сборки задача do_unpack распаковывает исходные коды в каталог, указанный переменной ${S}. Если файлы исходных кодов загружались в виде архива, внутренняя структура которого соответствует соглашениям для каталога верхнего уровня ${BPN}-${PV}, установка S не требуется. Однако при указании в SRC_URI архива, не соблюдающего эти соглашения, или выборке файлов из SCM (скажем, Git или Subversion) задание должно указывать S. После извлечения файлов нужно убедиться в том, что каталог, указанный переменной ${S}, соответствует структуре исходных кодов.
3.3.7. Применение исправлений для кода
Иногда требуется после извлечения применить к нему исправления (patch). Все упомянутые в SRC_URI файлы .patch и .diff, а также архивы с такими файлами (например, .diff.gz) считаются исправлениями, которые задача do_patch применяет автоматически. Система сборки должна иметь возможность применять исправления с опцией -p1 (т. е. один уровень каталогов в пути удаляется). Если требуется удалять несколько уровней, их число указывается в опции striplevel для исправления в записи SRC_URI. Если исправление нужно применить в конкретном каталоге, не указанном в patch-файле, используется опция patchdir.
Как и всех локальные файлы, указанные в SRC_URI с помощью file://, patch-файлы следует размещать в каталоге с заданием, имя которого совпадает с базовым именем задания (BP и BPN) или FILES.
3.3.8. Лицензирование
В задании должны быть определены переменные LICENSE и LIC_FILES_CHKSUM.
LICENSE
Указывает лицензию для программ. Если лицензия не известна, следует найти нужную информацию в исходном коде программ. Обычно лицензия указывается в файле COPYING, LICENSE или README. Зачастую лицензия также указывается в начале файлов с исходным кодом. Если программа распространяется по лицензии GNU General Public License version 2, следует установить LICENSE = “GPLv2”.
Имена лицензий в файле LICENSE не должны включать пробелы, поскольку пробелы служат разделителями имен. Для стандартных лицензий используются имена файлов из каталога meta/files/common-licenses/ или имена флагов SPDXLICENSEMAP в файле meta/conf/licenses.conf.
LIC_FILES_CHKSUM
Эту переменную система сборки OE применяет для контроля неизменности текста лицензии. При наличии изменений процесс сборки завершится ошибкой.
Нужно указывать все файлы лицензий, применимых к программе. В конце этапа настройки конфигурации процесс сборки проверяет контрольные суммы файлов с текстами лицензий и выдает ошибку при несоответствии. Дополнительная информация о установке переменной LIC_FILES_CHKSUM приведена в параграфе 3.32.1. Отслеживание изменений в лицензиях.
Для определения корректных контрольных сумм файлов лицензий можно указать эти файлы в переменной LIC_FILES_CHKSUM с произвольными строками md5 и запустить сборку программ. В сообщениях об ошибках будут указаны корректные контрольные суммы md5. Дополнительная информация о контрольных суммах приведена в параграфе 3.3.5. Извлечение кода.
Ниже приведен пример переменной для программы, имеющей файл COPYING.
LIC_FILES_CHKSUM = "file://COPYING;md5=xxx"
При попытке собрать программу система сборки выдаст сообщение об ошибке, содержащее корректную контрольную сумму, которую нужно подставить в показанную в примере строку до следующей сборки.
3.3.9. Зависимости
Большинство программных пакетов имеют короткий список пакетов, которые нужны им. Эти пакеты называют зависимостями и они делятся на две категории – зависимости при сборке и зависимости при работе. В задании зависимости при сборке указываются с помощью переменной DEPENDS, куда следует включать имена других заданий (есть нюансы). Важно задать зависимости при сборке в явном виде. Если этого не сделать, в результате параллельной работы BitBake могут возникать конфликты, когда зависимость будет видна в одной задаче (например, do_configure) и отсутствовать в другой (например, do_compile).
Другое соображение связано с тем, что сценарии настройки могут автоматически проверять дополнительные зависимости и включать при их обнаружении соответствующую функциональность. Это означает, для для получения детерминированных результатов и отсутствия конфликтов нужно явно указать эти зависимости или явно запретить упомянутые добавления конфигурационным сценариям. Если нужно сделать задание более полезным (например, при публикации уровня) вместо жесткого запрета функциональности можно использовать переменную PACKAGECONFIG, позволяющую легко включать или отключать функциональность и соответствующие зависимости другим людям.
Аналогичным способом указываются и зависимости при работе с помощью зависящих от пакета переменных RDEPENDS. Все зависящие от пакета переменные должны иметь имя пакета в качестве суффикса как переопределение. Поскольку имя основного пакета в задании совпадает с именем задания, которое можно узнать из переменной ${PN}, можно указывать зависимости для основного пакета в форме RDEPENDS_${PN}. Если пакет называется ${PN}-tools, переменная будет называться RDEPENDS_${PN}-tools и т. п..
Некоторые зависимости при работе задаются автоматически при упаковке. Такие зависимости включают все общие библиотеки (если пакет example включает libexample, а другой пакет mypackage – двоичные файлы, связанные с libexample, система сборки OE будет автоматически добавлять зависимость mypackage от example). Дополнительная информация о добавлении зависимостей приведена в разделе Automatically Added Runtime Dependencies [1].
3.3.10. Настройка конфигурации задания
Большинство программ включает те или иные средства настройки конфигурации перед сборкой. Обычно для этого применяется сценарий configure с определенными опциями или изменяется конфигурационный файл сборки. Начиная с выпуска YP 1.7, в части основных заданий двоичные сценарии настройки конфигурации были отключены по причине многочисленных ошибок с подстановками путей. Сейчас система сборки OE использует более надежный инструмент pkg-config. Список отключенных сценариев настройки приведен в разделе Binary Configuration Scripts Disabled [3].
Основной частью настройки конфигурации при сборке является проверка зависимостей и возможного включения свойств в результате этой проверки. Нужно задать все зависимости для сборки в переменной задания DEPENDS, указывая задания, требуемые зависимостями. Зависимости для сборки зачастую описаны в документации программ.
Ниже перечислены элементы настройки, применяемые в зависимости от способа сборки программ
Autotools
Если в исходных кодах имеется файл configure.ac, сборка основана на применении autotools и для настройки нужно изменять конфигурацию. В этом случае задание должно наследовать класс autotools и не будет включать задачу do_configure. Тем не менее внесение корректив возможно. Например, можно задать переменную EXTRA_OECONF или PACKAGECONFIG_CONFARGS для передачи параметров конфигурации задания.
Cmake
Если в исходном коде имеется файл CMakeLists.txt file, сборка выполняется с использованием Cmake. В этом случае может потребоваться внесение изменений в конфигурацию. При использовании Cmake задания должны наследовать класс cmake и не будут использовать задачу do_configure. Можно внести некоторые изменения с помощью переменной EXTRA_OECMAKE для передачи конфигурационных опций задания.
Прочее
Если исходные коды не включают файлов configure.ac и CMakeLists.txt, этого говорит о сборке программы с использованием методов, отличных от Autotools и CMake. В таких случаях обычно требуется обеспечить в задачу do_configure, если задание включает какие-либо настройки.
Если задание не использует Autotools или Cmake, настройка конфигурации может потребоваться и нужно понять, нужна ли она на самом деле. Может потребоваться редактирование файла Makefile или иного файла конфигурации, содержащего нужные для сборки опции. Иногда может потребоваться выполнение включенного в исходный код сценария настройки. В этом случае команда ./configure –help позволит увидеть доступные опции.
По завершении настройки конфигурации рекомендуется посмотреть файл log.do_configure, чтобы убедиться в установке нужных параметров и отсутствии дополнительных зависимостей при сборке, которые нужно добавить в DEPENDS. Например, если сценарий настройки нашел что-то, не упомянутое в DEPENDS, или не нашел нужного для обеспечения желаемой функциональности, нужно внести соответствующие добавления в DEPENDS. Просмотр журнала также может выявить элементы, которые были проверены и/или включены в конфигурацию, но не требуются, или не найдены DEPENDS, что может потребовать передачи дополнительных параметров сценарию настройки. Для просмотра полного списка параметров configure служит команда ./configure –help, вызванная из каталога ${S}.
3.3.11. Использование заголовочных файлов для интерфейса с устройствами
Если задание создает программу, которой нужно взаимодействовать с тем или иным устройством, или требуется API для пользовательского ядра, нужны соответствующие файлы заголовков. Ни при каких обстоятельствах недопустимо менять файл meta/recipes-kernel/linux-libc-headers/linux-libc-headers.inc, поскольку эти заголовочные файлы используются для сборки libc и не должны подвергаться рискам со стороны пользовательских или машинозависимых конфигураций. Настройка libc с измененными файлами заголовков будет влиять на все приложения, применяющие libc.
Корректным способом взаимодействия с устройством или пользовательским ядром является использование отдельного пакета, обеспечивающего дополнительные заголовки для драйвера или других уникальных интерфейсов. В этом случае данное приложение отвечает за создание зависимостей.
Предположим, что изменяется имеющийся заголовок, который добавляет управление вводом-выводом или поддержку сети. Если изменение используется небольшим числом программ, предоставление заголовку уникальной версии проще и оказывает меньшее влияние. А этом случае следует учитывать приведенные выше рекомендации.
Если по какой-то причине нужно изменить поведение libc и, следовательно, всех приложений в системе, нужно использовать файл .bbappend для изменения файла linux-kernel-headers.inc. Однако следует учесть, что изменения не должны быть машинозависимыми.
Рассмотрим вариант старого ядра, который требует применения старого libc ABI. Заголовки, установленные заданием, должны относиться к стандартному ядру, а не к пользовательскому. Для пользовательских заголовков ядра нужно получить их из переменной STAGING_KERNEL_DIR, указывающей каталог с заголовками, которые нужны для сборки внешних модулей. Задание должно включать do_configure[depends] += “virtual/kernel:do_shared_workdir”.
3.3.12. Компиляция
В процессе сборки после извлечения, распаковки и настройки конфигурации исходного кода запускается задача do_compile. Если эта задача выполняется без ошибок, дополнительно ничего делать не нужно.
Однако при отказах в процессе компиляции приходится искать причины ошибок. При обнаружении неверных путей в конфигурационных файлах или невозможности найти библиотеки или файлы заголовков убедитесь в использовании надежного пакета pkg-config (параграф 3.3.10. Настройка конфигурации задания).
- Отказы при параллельной сборке проявляются как чередующиеся ошибки или сообщения об отсутствии файлов или каталогов, которые должны быть созданы другой частью процесса сборки. Это может быть связано с некорректным порядком выполнения процесса сборки. Для решения проблемы следует обеспечить невыполненные зависимости в Makefile, создавшем Makefile сценарии или (обходной путь) отключить параллельную сборку, указав PARALLEL_MAKE = “” (см. раздел 3.30.12. Отладка конфликтов параллельной сборки).
- Некорректное использование путей хоста может возникать при сборке заданий для целевой платформы или nativesdk. Ошибка возникает при использовании процессом компиляции некорректных заголовков, библиотек или иных файлов хост-системы при кросс-компиляции для целевой платформы. Для решения проблемы следует просмотреть файл log.do_compile, где нужно найти используемые пути хоста (/usr/include, /usr/lib и т. п.) и исправить соответствующие опции конфигурации или применить исправления.
- Отказ при поиске нужных библиотек и заголовочных файлов. Если зависимости при сборке не выполняются по причине их отсутствия в DEPENDS или использования неверных путей поиска, процесс сборки завершается ошибкой. Система сборки в таких случаях указывает не найденные файлы. Для решения проблему нужно указать пропущенные зависимости или дополнительные параметры сценариев настройки конфигурации.Иногда нужно внести изменения в исходные коды для обеспечения корректных путей поиска. Если нужно указать пути поиска файлов из других заданий, размещенных в sysroot, следует использовать переменные системы сборки OE (например, STAGING_BINDIR, STAGING_INCDIR, STAGING_DATADIR и т. п.).
3.3.13. Инсталляция
Задача do_install в процессе работы копирует файлы сборки вместе с иерархией в места, отражающие их размещение на целевой платформе. Файлы копируются из каталогов ${S}, ${B} и ${WORKDIR} в каталог ${D} для создания структуры, которая должна появиться в целевой системе.
Сборка программ влияет на операции, требуемые для корректной установки. Ниже описаны действия, зависящие от способа сборки программ.
- Autotools и Cmake. Если программы вашего задания собираются с помощью Autotools или CMake, система сборки OE знает, как их установить. Поэтому не требуется включать задачу do_install в задание, достаточно лишь убедиться в полноте сборки и отсутствии ошибок. Однако, если нужно установить дополнительные файлы, которые не учтены командой make install, следует использовать функцию do_install_append с командой install, как описано ниже.
- Прочие (make install). В задании нужно определить функцию do_install, которая должна вызывать oe_runmake install и вероятно будет передавать ей целевой каталог. Способ передачи каталога зависит от файла Makefile (например, DESTDIR=${D}, PREFIX=${D}, INSTALLROOT=${D} и т. п.). Пример задания, использующего make install приведен в параграфе 3.3.21.3. Пакеты на основе Makefile.
- Ручная установка. В задании нужно определить функцию do_install, которая должна использовать команду install -d для создания каталогов в ${D}. Когда каталоги созданы, функция может использовать команду install для установки программ в эти каталоги.Дополнительную информацию можно найти по ссылке.
Для сценариев, не использующих Autotools или CMake, нужно отслеживать инсталляцию, контролируя и исправляя возникающие ошибки. Нужно просматривать каталог ${D} (по умолчанию ${WORKDIR}/image) для проверки корректности установки всех файлов.
- В процессе инсталляции может потребоваться изменение некоторых установленных файлов в соответствии с целевой платформой. Например, может потребоваться замена жестко заданных путей значениями подставляемых системой переменных (например, замена /usr/bin/ на ${bindir}). Если такие замены происходили в процессе do_install, нужно менять целевой файл после копирования, а не до него. Это гарантирует возможность повтора системой сборки задачи do_install при возникновении необходимости.
- Задача oe_runmake, которая может запускаться напрямую или опосредованно через класса autotools и cmake, запускает команды make install параллельно. Иногда в файле Makefile могут отсутствовать зависимости между целями и будут возникать конфликты. При возникновении сбоев в процессе выполнения do_install можно отключить параллельную работу, задав PARALLEL_MAKEINST = “”.
3.3.14. Включение системных служб
Для включения службы, которая будет запускаться при загрузке и работать в фоновом режиме, нужно указать в задании дополнительные определения. Если добавляется служба, а сценарий ее запуска или файл самого сервиса не установлен, нужно обеспечить соответствующую инсталляцию с использованием задачи do_install_append. Если задание уже включает эту функцию, следует добавить данные в конец строки, а не добавлять другую функцию.
При настройке инсталляции служб нужно выполнить операции, которые обычно делает команда make install. Иными словами, нужно убедиться, что при инсталляции данные упорядочиваются как в целевой системе.
Система сборки OE обеспечивает несколько вариантов запуска служб при загрузке.
- SysVinit является менеджером системы и служб, который управляет инициализацией системой init для контроля базовых функций. Программа init является первой программой, запускаемой ядром Linux при загрузке системы. Затем эта программа управляет запуском, работой и отключением всех прочих программ.Для включения службы с помощью SysVinit задание должно наследовать класс update-rc.d, который помогает безопасно устанавливать пакеты на целевой платформе. В задании нужно установить переменные INITSCRIPT_PACKAGES, INITSCRIPT_NAME и INITSCRIPT_PARAMS.
- systemd является демоном управления системой, предназначенным для замены SysVinit и обеспечения более эффективного управления службами (см. http://freedesktop.org/wiki/Software/systemd/). Для управления службами с помощью systemd задание должно наследовать класс systemd, информацию о котором можно найти в файле systemd.bbclass дерева исходных кодов.
3.3.15. Подготовка пакетов
Успешная подготовка пакетов включает автоматизированные процессы системы сборки OE и действия пользователя.
- Разделение файлов. Задача do_package делит файлы, созданные заданием на логические компоненты. Даже программа из одного двоичного файла может включать отладочные символы, документацию и другие компоненты, которые следует разделять.
- Запуск тестов QA. Класс insane добавляет в процесс генерации пакета этап создания тестов качества системой сборки OE. На этом этапе выполняется множество проверок, чтобы гарантировать отсутствие в выводе типичных проблем, возникающих при работе. Информация об этих проверках приведена в описании класса insane и разделе QA Error and Warning Messages [3].
- Проверка пакетов вручную. После сборки программы нужно убедиться в корректности пакетов. Проверяется каталог ${WORKDIR}/packages-split на предмет наличия ожидаемых файлов. При обнаружении проблем следует проверить корректность установки PACKAGES, FILES, do_install(_append) и т. п..
- Разделение приложения на несколько пакетов. См. параграф 3.3.21.4. Разделение программы на несколько пакетов.
- инсталляция сценария пост-установки. См. параграф 3.3.19. Сценарии пост-установки.
- Указание архитектуры пакета. В зависимости от того, что собирает задание и как оно настроено может быть важна маркировка пакетов как относящихся к конкретной машине или архитектуре. По умолчанию пакеты применимы к любой машине с архитектурой, указанной для цели. Когда задание создает машинозависимые пакеты (например, значение MACHINE передается сценарию configure или применяется patch-файл для определенной машины), нужно помечать пакеты, указывая PACKAGE_ARCH = “${MACHINE_ARCH}” в задании.Если задание создает пакеты, которые не привязаны к определенной машине или архитектуре (например, файлы сценариев или конфигурации), следует использовать класс allarch, добавляя в задание inherit allarch.Проверка корректности архитектуры пакета не является критичной для первых сборок задания. Однако она важна для обеспечения гарантий надлежащей перестройки задания при смене конфигурации. Особенно важно контролировать установку на платформе подходящих пакетов в случаях сборки для нескольких целей.
3.3.16. Совместное использование файлов заданиями
Заданиям зачастую нужны файлы из других заданий сборочного хоста. Например, приложение может быть связано с общей библиотекой и ему нужен доступ к самой библиотеке и файлам заголовков. Этот доступ осуществляется через файловую систему sysroot. Каждое задание имеет в рабочем каталоге две системы sysroot, одна из которых служит для целевых файлов (recipe-sysroot), другая для естественных файлов хоста сборки (recipe-sysroot-native).
Заданиям не следует заполнять sysroot напрямую (т. е. записывать туда файлы). Вместо этого файлы должны устанавливаться в стандартные места задачей do_install внутри каталога ${D}. Причина этого заключается в том, что практически все файлы sysroot указываются в манифестах для контроля последующего изменения или удаления заданий. Поэтому система sysroot способна избавляться от устаревших файлов.
Часть файлов, установленных задачей do_install, используется задачей do_populate_sysroot в соответствии с переменной SYSROOT_DIRS для автоматического заполнения sysroot. Список каталогов sysroot можно менять. Например, можно добавить каталог /opt в форме SYSROOT_DIRS += “/opt”. Более подробное описание задачи do_populate_sysroot и связанных с ней функций приведено в описании класса staging.
3.3.17. Использование виртуальных провайдеров
Если до сборки известно, что одну функциональность представляет несколько разных заданий, можно выбрать виртуального провайдера (virtual/*) в качестве замены реального, который будет определен в процессе сборки. Базовым вариантом применения виртуальных провайдеров являются задания для сборки ядра. Предположим наличие трех таких заданий, у которых значения PN отображаются на kernel-big, kernel-mid и kernel-small. Кроме того, каждое из этих заданий своим способом использует оператор PROVIDES, указывая свою возможность предоставить элемент virtual/kernel. Одним из способов прохождения класса kernel является
PROVIDES += "${@ "virtual/kernel" if (d.getVar("KERNEL_PACKAGE_NAME") == "kernel") else "" }"
Любое задание, наследующее класс kernel, использует оператор PROVIDES, который указывает, что задание может обеспечить элемент virtual/kernel.
Когда нужно собрать образ и выбрать для него ядро, можно настроить сборку с нужным ядром с помощью переменной PREFERRED_PROVIDER. Рассмотрим в качестве примера файл x86-base.inc, задающий конфигурацию машины (MACHINE). Этот включаемый файл задает для всех машин x86 использование ядра linux-yocto. Это задается приведенными ниже строками.
PREFERRED_PROVIDER_virtual/kernel ??= "linux-yocto"
PREFERRED_VERSION_linux-yocto ??= "4.15%"
При использовании виртуального провайдера не нужно жестко задавать имя задания в качестве зависимости при сборке. Можно использовать переменную DEPENDS для указания зависимости от virtual/kernel, например, DEPENDS = “virtual/kernel”.
В процессе сборки система OE выберет нужное задание для зависимости virtual/kernel на основе переменной PREFERRED_PROVIDER. Для использования упомянутого выше компактного ядра можно указать PREFERRED_PROVIDER_virtual/kernel ??= “kernel-small”.
Любое задание, где PROVIDES содержит элемент virtual/*, который не выбран с помощью PREFERRED_PROVIDER, собираться не будет. Предотвращение сборки таких заданий обычно желательно, поскольку цель этого механизма заключается в выборе одного из взаимоисключающих провайдеров. Примеры виртуальных провайдеров даны ниже.
- virtual/kernel обеспечивает имя задания для ядра, используемого при сборке образа ядра.
- virtual/bootloader обеспечивает имя загрузчика (bootloader), используемого при сборке образа ядра.
- virtual/mesa обеспечивает gbm.pc.
- virtual/egl обеспечивает egl.pc и возможно wayland-egl.pc.
- virtual/libgl обеспечивает gl.pc (libGL).
- virtual/libgles1 обеспечивает glesv1_cm.pc (libGLESv1_CM).
- virtual/libgles2 обеспечивает glesv2.pc (libGLESv2).
3.3.18. Корректные версии предварительных выпусков
Иногда имя задания может приводить к проблемам с версиями при обновлении до финального выпуска задания. Рассмотрим, например, файл irssi_0.8.16-rc1.bb recipe из примеров параграфа 3.3.3. Сохранение и именование заданий. Это задание указывает предварительный выпуск (rc1), а в окончательном выпуске файл получает имя irssi_0.8.16.bb. Версия 0.8.16-rc1 сменилась на 0.8.16, что представляется уменьшением номера с точки зрения менеджера пакетов, поэтому полученные в результате пакеты не будут корректно обновляться.
Для корректного сравнения версий рекомендуется для PV в задании установить previous_version+current_version. Можно использовать дополнительную переменную, чтобы текущая версия была доступна везде. Например,
REALPV = "0.8.16-rc1"
PV = "0.8.15+${REALPV}"
3.3.19. Сценарии пост-установки
Сценарии пост-установки работают сразу после инсталляции пакета не целевой платформе или при создании образа, когда пакет включен в образ. Для включения в пакет такого сценария нужно добавить функцию pkg_postinst_PACKAGENAME() в файл задания (.bb), заменив PACKAGENAME именем соответствующего пакета. Для применения сценария пост-установки к основному пакету задания (обычно это нужно), вместо PACKAGENAME указывается ${PN}.
Структура функции пост-установки показана ниже.
pkg_postinst_PACKAGENAME() { # Выполняемые команды }
Сценарий, заданный в функции пост-установки, вызывается при создании корневой файловой системы. При успешном выполнении сценария пакет помечается как установленный. Если возникает отказ сценария, пакет помечается как нераспакованный и сценарий повторяется при следующей загрузке.
Всем пост-установочным сценариям RPM на целевой платформе следует возвращать код завершения 0. RPM не разрешает отличные от 0 коды возврата и менеджер пакетов RPM в таких случаях выдает отказ при установке на целевой платформе.
Иногда нужно отложить сценарий пост-установки до первой перезагрузки (например, сценарию может требоваться выполнение на самом устройстве). В таких случаях нужно явно указать отложенные до перезагрузки сценарии, для чего можно использовать функцию pkg_postinst_ontarget() или вызвать postinst-intercepts defer_to_first_boot из pkg_postinst(). Любой отказ сценария pkg_postinst() (включая exit 1) вызывает ошибку задачи do_rootfs.
При наличии заданий, использующих функцию pkg_postinst и требующих нестандартных естественных инструментов, которые имеют зависимости при создании корневой файловой системы, нужно указывать эти инструменты в переменной задания PACKAGE_WRITE_DEPS. Если переменная не используется, задание может отсутствовать и выполнение пост-установочного сценария будет отложено до перезагрузки, что нежелательно, а на файловых системах с доступом только для чтения – невозможно.
Существует эквивалентная поддержка сценариев pre-install, pre-uninstall и post-uninstall с помощью функций pkg_preinst, pkg_prerm и pkg_postrm, соответственно. Эти сценарии работают так же, как pkg_postinst за исключением того, что они запускаются в разные моменты. Кроме того, с учетом момента запуска эти сценарии не применимы во время создания образа, как pkg_postinst.
3.3.20. Тестирование
Финальным этапом задания является проверка корректности работы сборки. Для тестирования добавьте выходные пакеты в образ и проверьте их на целевой платформе. Информация о добавлении пакетов в образы приведена в разделе 3.2. Настройка образов.
3.3.21. Примеры
Для иллюстрирования процесса написания заданий в этом разделе приведено несколько примеров:
- задания, использующие локальные файлы;
- задания, использующие автоматически настраиваемые пакеты;
- задания, использующие пакеты с Makefile;
- расщепление приложения на несколько пакетов;
- добавление двоичных файлов в образ.
3.3.21.1. Пакет с одним файлом .c
Сборка приложения из одного локального файл требует задания, где этот файл указан в переменной SRC_URI. Кроме того, нужно вручную создать задачи do_compile и do_install. Переменная S определяет каталог с исходным кодом, который задается в качестве WORKDIR в данном случае. BitBake использует этот каталог для сборки.
SUMMARY = "Simple helloworld application" SECTION = "examples" LICENSE = "MIT" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" SRC_URI = "file://helloworld.c" S = "${WORKDIR}" do_compile() { ${CC} helloworld.c -o helloworld } do_install() { install -d ${D}${bindir} install -m 0755 helloworld ${D}${bindir} }
По умолчанию собираются пакеты helloworld, helloworld-dbg и helloworld-dev. Информация о настройке процесса упаковки приведена в параграфе 3.3.21.4. Разделение программы на несколько пакетов.
3.3.21.2. Пакеты с автоматической настройкой
Приложения, использующие инструменты автоматической настройки, такие как autoconf и automake, требуют от заданий указать архив исходных кодов в переменной SRC_URI и наследовать класс autotools, который содержит определения всех этапов сборки приложений с автоматической настройкой. Результат сборки автоматически собирается в пакет. Если приложение использует NLS для поддержки разных языков, создаются языковые пакеты (по одному на язык). Ниже приведен пример на основе задания hello_2.3.bb.
SUMMARY = "GNU Helloworld application" SECTION = "examples" LICENSE = "GPLv2+" LIC_FILES_CHKSUM = "file://COPYING;md5=751419260aa954499f7abaabaa882bbe" SRC_URI = "${GNU_MIRROR}/hello/hello-${PV}.tar.gz" inherit autotools gettext
Переменная LIC_FILES_CHKSUM служит для отслеживания изменений в лицензиях, как описано в разделе Tracking License Changes [1]. Задания для автоматически настраиваемых приложений можно создавать по аналогии с предыдущим параграфом.
3.3.21.3. Пакеты на основе Makefile
Приложения, использующие GNU, также требуют от заданий указать архив исходных кодов в переменной SRC_URI. Этап do_compile добавлять не нужно, поскольку BitBake по умолчанию запускает команду make для компиляции приложения. Если нужны дополнительные опции make, следует задать их в переменной EXTRA_OEMAKE или PACKAGECONFIG_CONFARGS. BitBake передает эти опции при вызове GNU make. Отметим, что задача do_install по-прежнему требуется, иначе BitBake будет запускать пустую задачу do_install.
Некоторые приложения могут требовать передачи компилятору дополнительных параметров (например, путь к дополнительным файлам заголовков). Это можно обеспечить, добавив параметры в переменную CFLAGS в форме CFLAGS_prepend = “-I ${S}/include “.
Ниже приведен пример приложения mtd-utils использующего Makefile.
SUMMARY = "Tools for managing memory technology devices" SECTION = "base" DEPENDS = "zlib lzo e2fsprogs util-linux" HOMEPAGE = "http://www.linux-mtd.infradead.org/" LICENSE = "GPLv2+" LIC_FILES_CHKSUM = "file://COPYING;md5=0636e73ff0215e8d672dc4c32c317bb3 \ file://include/common.h;beginline=1;endline=17;md5=ba05b07912a44ea2bf81ce409380049c" # Use the latest version at 26 Oct, 2013 SRCREV = "9f107132a6a073cce37434ca9cda6917dd8d866b" SRC_URI = "git://git.infradead.org/mtd-utils.git \ file://add-exclusion-to-mkfs-jffs2-git-2.patch \ " PV = "1.5.1+git${SRCPV}" S = "${WORKDIR}/git" EXTRA_OEMAKE = "'CC=${CC}' 'RANLIB=${RANLIB}' 'AR=${AR}' 'CFLAGS=${CFLAGS} -I${S}/include -DWITHOUT_XATTR' 'BUILDDIR=${S}'" do_install () { oe_runmake install DESTDIR=${D} SBINDIR=${sbindir} MANDIR=${mandir} INCLUDEDIR=${includedir} } PACKAGES =+ "mtd-utils-jffs2 mtd-utils-ubifs mtd-utils-misc" FILES_mtd-utils-jffs2 = "${sbindir}/mkfs.jffs2 ${sbindir}/jffs2dump ${sbindir}/jffs2reader ${sbindir}/sumtool" FILES_mtd-utils-ubifs = "${sbindir}/mkfs.ubifs ${sbindir}/ubi*" FILES_mtd-utils-misc = "${sbindir}/nftl* ${sbindir}/ftl* ${sbindir}/rfd* ${sbindir}/doc* ${sbindir}/serve_image ${sbindir}/recv_image" PARALLEL_MAKE = "" BBCLASSEXTEND = "native"
3.3.21.4. Разделение программы на несколько пакетов
Чтобы разделить приложение на несколько пакетов, можно использовать переменные PACKAGES и FILES. Ниже приведен пример разделения задания libxpm, которое по умолчанию создает один пакет с библиотекой и несколькими исполняемыми файлами. Можно разделить задание, выделив исполняемые файлы в отдельные пакеты.
require xorg-lib-common.inc SUMMARY = "Xpm: X Pixmap extension library" LICENSE = "BSD" LIC_FILES_CHKSUM = "file://COPYING;md5=51f4270b012ecd4ab1a164f5f4ed6cf7" DEPENDS += "libxext libsm libxt" PE = "1" XORG_PN = "libXpm" PACKAGES =+ "sxpm cxpm" FILES_cxpm = "${bindir}/cxpm" FILES_sxpm = "${bindir}/sxpm"
В этом примере исполняемые файлы sxpm и cxpm вынесены в отдельные пакеты. Поскольку bindir помещается по умолчанию в основной пакет PN, дополнительные пакеты помещены в начало переменной PACKAGES. Это создает дополнительные переменные FILES_*, содержащие информацию о файлах и каталогах, включаемых в пакеты. Включенные предыдущими пакетами файлы и каталоги пропускаются последующими, поэтому указанные в переменных файлы не попадут в основной пакет PN.
3.3.21.5. Упаковка внешних двоичных пакетов
Иногда нужно добавить в образ собранные заранее двоичные файлы. Например, при наличии фирменного (proprietary) кода, созданного отдельным подразделением компании, эти программы могут оказаться нужны для образа, создаваемого в системе сборки OE. Поскольку имеются лишь двоичные файлы без исходных кодов, невозможно использовать типовые задания для сборки, которым нужно указать исходный код в SRC_URI и компилировать его.
Одним из вариантов является упаковка двоичных файлов и установка их в образ. В общем случае это не лучшее решение, поскольку может мешать воспроизведению сборки и создать в будущем проблемы совместимости с ABI. Однако иногда других вариантов просто нет. Простейшим способом является подготовка задания, использующего класс bin_package с указанием принятого по умолчанию размещения результатов сборки. В большинстве случаев класс bin_package «пропускает» этапы настройки и компиляции, а также настраивает извлечение пакетов из указанных мест. В частности, этот класс устанавливает noexec для задач do_configure и do_compile, задает FILES_${PN} = “/” для выборки файлов и настраивает задачу do_install для копирования файлов из ${S} в ${D}. Класс bin_package хорошо работает, когда извлеченные в ${S} файлы уже размещены в соответствии с их расположением на целевой платформе. Информация о переменных FILES, PN, S и D приведена в [3].
- Использование DEPENDS является хорошей идеей для компонент, распространяемых в двоичной форме, и зачастую требуется для общих библиотек. Для библиотек указание зависимостей в DEPENDS обеспечивает доступность этих библиотек при подготовке sysroot, когда другие задания ссылаются на эти библиотеки.
- Использование DEPENDS также позволяет задать автоматическое добавление зависимостей при работе программ (см. раздел Automatically Added Runtime Dependencies [1]).
Если нет возможности использовать класс bin_package, нужно обеспечить выполнение приведенных ниже операций.
- Подготовить задание, где do_configure и do_compile не делают ничего. Обычно для этого достаточно просто не указывать задачи, поскольку принятые по умолчанию реализации нечего не делают, пока не найден файл Makefile в ${S}. Если каталог ${S} может включать файл Makefile или нужно наследовать класс, который заменит do_configure и do_compile настроенными вариантами, можно использовать флаг [noexec] для включения задач в no-ops.
do_configure[noexec] = "1" do_compile[noexec] = "1"
В отличие от удаления задач, использование флага сохранит цепочку зависимостей из задач do_fetch, do_unpack и do_patch для задачи do_install.
- Убедиться в корректной установке двоичных файлов задачей do_install.
- Убедиться, что переменная FILES (обычно FILES_${PN}) указывает устанавливаемые файлы. Это зависит от места установки файлов с учетом принятого по умолчанию размещения.
3.3.22. Рекомендации по стилям заданий
При подготовке заданий разумно следовать сложившемуся стилю. На странице OpenEmbedded Styleguide даны рекомендации по предпочтительному стилю заданий. Реальные задания обычно слегка отклоняются от рекомендуемого стиля, однако стремление следовать стилю является хорошим тоном. Отсутствие пробелов вокруг операторов = при назначении или некорректный порядок компонент задания часто воспринимаются как дурной тон.
3.3.23. Синтаксис заданий
Для подготовки задания важно разобраться с их синтаксисом. Ниже приведен обзор основных элементов файла заданий BitBake, более полная документация содержится в разделе Syntax and Operators [6].
- Назначение и изменение переменных. Назначение может быть статическим текстом или включать содержимое других переменных. Кроме того, поддерживаются операторы добавления в начало или в конец переменной.
S = "${WORKDIR}/postfix-${PV}" CFLAGS += "-DNO_ASM" SRC_URI_append = " file://fixup.patch"
- Функции задают последовательность выполняемых операций. Обычно функции применяются для переопределения принятой по умолчанию реализации функции задачи или ее дополнения (т. е. добавления в начало или конец имеющейся функции). Стандартные функции используют стиль командного процессора sh, но поддерживается также доступ к переменным и внутренним методам OE. Ниже приведен пример функции из задания sed.
do_install () { autotools_do_install install -d ${D}${base_bindir} mv ${D}${bindir}/sed ${D}${base_bindir}/sed rmdir ${D}${bindir}/ }
Можно реализовать новые функции, которые вызываются между имеющимися задачами, если эти функции не заменяют и не дополняют принятых по умолчанию функций. Можно реализовать функции на языке Python.
- Ключевые слова. Задания BitBake используют немного ключевых слов. Они служат для включения базовых функций (inherit), загрузки частей задания из других файлов (include и require), а также для экспорта переменных в среду (export).
export POSTCONF = "${STAGING_BINDIR}/postconf" inherit autoconf require otherfile.inc
- Комментарии (#). Все строки, начинающиеся с символа #, считаются комментариями и не обрабатываются.
# Это комментарий
Далее представлены наиболее важные и распространенный части синтаксиса заданий. Дополнительная информация о синтаксисе приведена в разделе Syntax and Operators [6].
- Продолжение строки (\). Символ \ служит для разделения длинной строки на несколько более коротких.
VAR = "Это длинная \ строка"
Этот символ нельзя заменить другим.
- Использование переменных (${VARNAME}). Синтаксис ${VARNAME} служит для доступа к содержимому переменных, как показано ниже
SRC_URI = "${SOURCEFORGE_MIRROR}/libpng/zlib-${PV}.tar.gz"
Важно понимать, что значение переменной, выраженное в такой форме, не подставляется автоматически сразу. Преобразование выражений происходит позже по запросу (обычно при выполнении ссылающейся на переменную функции). Это обеспечивает гарантию того, что значения больше подходят для контекста, в котором они реально применяются. В редких случаях, когда требуется сразу раскрыть выражение, можно использовать оператор := вместо = при назначении.
- Назначения в кавычках (“value“). Присваиваемые значения следует указывать в двойных кавычках, например,
VAR1 = "${OTHERVAR}" VAR2 = "Версия ${PV}"
- Условное назначение (?=) используется для присваивания переменной значения исключительно в случае его отсутствия в данный момент. Для условного (мягкого) назначения используется оператор ?=). Обычно такие назначения применяются в файле local.conf для переменных, которым разрешено приходить извне. Например, VAR1 ?= “New value” назначит переменной VAR1 значение “New value”, если в этот момент она не имеет значения. Иначе переменная VAR1 сохранит свое значение как в приведенном ниже примере.
VAR1 = "Original value" VAR1 ?= "New value"
- Добавление в конце (+=). Оператор += добавляет значение в конце имеющейся переменной, отделяя новое значение от имеющегося пробелом. Например, SRC_URI += “file://fix-makefile.patch”.
- Добавление в начале (=+). Оператор =+ позволяет добавить значение в начало имеющейся переменной с пробелом между добавленным и прежним значением. Например, VAR =+ “Starts”.
- Добавление в конце (_append). Оператор _append добавляет значение к имеющейся переменной без включения символа пробела. Оператор применяется после всех операторов += и =+, а также после назначений с помощью =. Чтобы добавленное значение не сливалось с имеющимся, следует явно указывать пробел в начале добавляемого значения, например, SRC_URI_append = ” file://fix-makefile.patch”.Оператор _append можно использовать в переопределениях, чтобы изменение относилось лишь к указанной цели или машине. Например, SRC_URI_append_sh4 = ” file://fix-makefile.patch”.
- Добавление в начале (_prepend). Оператор _prepend добавляет значение к имеющейся переменной без включения символа пробела. Оператор применяется после всех операторов += и =+, а также после назначений с помощью =. Чтобы добавленное значение не сливалось с имеющимся, следует явно указывать пробел в начале добавляемого значения, например, CFLAGS_prepend = “-I${S}/myincludes “.Оператор _prepend можно использовать в переопределениях, чтобы изменение относилось лишь к указанной цели или машине. Например, CFLAGS_prepend_sh4 = “-I${S}/myincludes “.
- Переопределение может служить для условной установки значения, обычно в зависимости от способа сборки задания. Например, для установки в переменной KBRANCH значения standard/base для любого целевого значения MACHINE, кроме qemuarm, где следует установить standard/arm-versatile-926ejs, можно задать
KBRANCH = "standard/base" KBRANCH_qemuarm = "standard/arm-versatile-926ejs"
Переопределения применяются также для разделения вариантов переменной. Например, при установке таких переменных как FILES и RDEPENDS, которая зависит от собираемых заданием пакетов, всегда следует применять переопределение, задающее имя пакета.
- Вставка пробелов в начале строки. Для отступа в начале строки следует использовать пробелы, а не символы табуляции. Для функций оболочки ((shell) в настоящее время работают оба варианта, однако это просто правило YP по использованию табуляции в shell-функциях. В некоторых слоях (уровнях) может применяться иная трактовка отступов.
- Комплексные операции Python. Для более сложной обработки (например, поиск и замена в переменной) можно использовать при назначении переменных код Python, указываемого с помощью синтаксиса ${@python_code}, например, SRC_URI = “ftp://ftp.info-zip.org/pub/infozip/src/zip${@d.getVar(‘PV’,1).replace(‘.’, ”)}.tgz.
- Синтаксис shell-функций. Эти функции создаются как сценарии командного процессора для описания последовательности выполняемых операций. Следует проверить работу сценария с базовым командным процессором sh и отсутствие потребности в использовании bash или иного процессора. Это относится и к применяемым системным утилитам (например, sed, grep, awk). При наличии сомнений следует проверить функцию с несколькими реализациями, включая BusyBox.
3.4. Добавление машины
Добавление новой машины в YP достаточно просто. В этом разделе описано, как добавить машины по аналогии с имеющимися в YP. Добавление полностью новой архитектуры может потребовать внесения изменений в gcc/glibc и информацию о сайте, но это выходит за рамки данного руководства. Полное описание процессов добавления новой машины приведено в разделе Creating a New BSP Layer Using the bitbake-layers Script [5].
3.4.1. Добавление конфигурационного файла машины
Для добавления машины нужно создать конфигурационный файл машины в каталоге conf/machine нужного уровня. Этот файл будет включать данные о добавляемом устройстве. Система сборки OE использует корневое имя конфигурационного файла машины для ссылок на нее. Например, при конфигурационном файле crownbay.conf система сборки будет называть машину crownbay.
Наиболее важными переменными в конфигурационном файле машины или включаемых в него файлах являются:
- TARGET_ARCH (например, “arm”);
- PREFERRED_PROVIDER_virtual/kernel;
- MACHINE_FEATURES (например, “apm screen wifi”).
Могут также потребоваться переменные:
- SERIAL_CONSOLES (например, “115200;ttyS0 115200;ttyS1”);
- KERNEL_IMAGETYPE (например, “zImage”);
- IMAGE_FSTYPES (например, “tar.gz jffs2”).
В качестве образца можно взять один из файлов .conf каталога meta-yocto-bsp/conf/machine/.
3.4.2. Добавление ядра для машины
Система сборки OE должна быть способна собрать ядро для машины, что требует создать специальное задания для ядра или расширить имеющееся. Примеры заданий для ядер можно найти в каталоге исходных кодов (meta/recipes-kernel/linux) и использовать в качестве образца.
При подготовке нового задания для ядра применяются обычные правила установки SRC_URI. Таким образом, нужно указать все требуемые исправления (patch) и установить в S местоположение исходного кода. Нужно создать задачу do_configure для настройки распакованного ядра с использованием файла defconfig. Это можно сделать с помощью команды make defconfig или путем копирования подходящего файла defconfig и запуска команды make oldconfig. При использовании наследуемого ядра и, возможно, некоторых файлов linux-*.inc большая часть остальных функций будет централизована и принятые по умолчанию настройки классов обычно будут работать хорошо.
При расширении имеющегося задания обычно следует добавить подходящий файл defconfig. Файл нужно добавлять в каталог, похожий на каталоги размещения файлов defconfig других машин в данном задании для ядра. Это можно сделать путем включения файла с SRC_URI и добавления машины в выражение COMPATIBLE_MACHINE, например, COMPATIBLE_MACHINE = ‘(qemux86|qemumips)’.
Дополнительная информация о файлах defconfig приведена в разделе Changing the Configuration [7].
3.4.3. Добавление файла аппаратной конфигурации
Файл аппаратной конфигурации обеспечивает информацию о целевой платформе, для которой будет собираться образ, а также сведения, которые система сборки не может получить из других источников, таких как ядро. Примерами данных, включаемых в этот файл, служат ориентация буфера кадров, наличие клавиатуры, ее расположение относительно экрана, а также экранное разрешение.
Система сборки в большинстве случаев подразумевает разумные значения, однако может потребоваться создание файла machconfig в каталоге meta/recipes-bsp/formfactor/files, содержащем данные для конкретных машин, таких как qemuarm и qemux86. Информацию о доступных и заданных по умолчанию значениях можно найти в файле meta/recipes-bsp/formfactor/files/config указанного каталога. Ниже приведен пример для машины qemuarm.
HAVE_TOUCHSCREEN=1 HAVE_KEYBOARD=1 DISPLAY_CAN_ROTATE=0 DISPLAY_ORIENTATION=0 #DISPLAY_WIDTH_PIXELS=640 #DISPLAY_HEIGHT_PIXELS=480 #DISPLAY_BPP=16 DISPLAY_DPI=150 DISPLAY_SUBPIXEL_ORDER=vrgb
3.5. Обновление заданий
С течением времени разработчики публикуют новые версии программ, собираемых заданиями для уровней. Рекомендуется поддерживать актуальность кода таких заданий. Есть несколько способов обновления заданий, но сначала разумно проверить текущее состояние. Сделать это можно с помощью команды devtool check-upgrade-status (см. раздел Checking on the Upgrade Status of a Recipe [3]).
Далее рассмотрены три варианта обновления заданий – автоматическое, полуавтоматическое и ручное.
3.5.1. Использование AUH
Утилита AUH9 работает с системой сборки OE для автоматической генерации обновлений на основе новых опубликованных версий кода. AUH позволяет создать службу автоматического обновления и может уведомлять о результатах по электронной почте. AUH может обновлять несколько заданий в один прием. Можно также протестировать результаты сборки и интеграфии, используя образы, сохраненные на диске, с возможность. Отправки результатов теста сопровождающим по электронной почте. Кроме того, AUH создает фиксации Git (commit) с сообщениями в дереве уровня для просмотра внесенных изменений.
В некоторых случаях не следует применять AUH для обновления, используя взамен команду devtool upgrade или обновление вручную.
- AUH не может завершить последовательность обновлений, что обычно является результатом невозможности автоматического переноса пользовательских исправлений в новую версию. Проблему решает обновление вручную.
- Требуется более полный контроль процесса обновления, например, при наличии специальных тестов.
Ниже перечислены этапы автоматического обновления с помощью AUH.
- Настройка хоста разработки для работы с YP в соответствии с разделом 2.2. Подготовка сборочного хоста.
- Настройка Git. Утилита AUH требует настройки конфигурации Git, поскольку этот пакет служит для сохранения изменений. Это требует указать пользователя Git и электронную почту. Для просмотра конфигурации служит команда git config —list. Если имя пользователя и электронная почта еще не заданы, следует ввести команды
$ git config --global user.name some_name $ git config --global user.email username@domain.com
- Клонирование репозитория AUH. Для использования AUH нужно клонировать репозиторий на хост разработки, как показано ниже.
$ git clone git://git.yoctoproject.org/auto-upgrade-helper Cloning into 'auto-upgrade-helper'... remote: Counting objects: 768, done. remote: Compressing objects: 100% (300/300), done. remote: Total 768 (delta 499), reused 703 (delta 434) Receiving objects: 100% (768/768), 191.47 KiB | 98.00 KiB/s, done. Resolving deltas: 100% (499/499), done. Checking connectivity... done.
AUH сейчас является частью репозиториев OpenEmbedded-Core (OE-Core) и Poky.
- Создание выделенного каталога сборки. Сценарий oe-init-build-env создает свежий каталог сборки, который используется лишь для запуска утилиты AUH.
$ cd ~/poky $ source oe-init-build-env your_AUH_build_directory
Использование имеющегося каталога сборки и его конфигурации не рекомендуется, поскольку имеющиеся настройки могут помешать работе AUH.
- Создание локальной конфигурации. Нужно включить некоторые настройки в файл local.conf созданного AUH каталога сборки, как показано ниже.
- Если нужно включить историю сборки (3.28.1. Управление историей сборки), нужно добавить в файл приведенные ниже строки.
INHERIT =+ "buildhistory" BUILDHISTORY_COMMIT = "1"
При такой конфигурации после успешного обновления появится файл diff в подкаталоге upgrade-helper/work/recipe/buildhistory-diff.txt каталога сборки.
- Если нужно добавить тестирование с помощью класса testimage, следует добавить строку
INHERIT += "testimage"
Если у дистрибутиве по умолчанию отключено свойство ptest (как в Poky) нужно добавить строку
DISTRO_FEATURES_append = " ptest"
- Если нужно включить историю сборки (3.28.1. Управление историей сборки), нужно добавить в файл приведенные ниже строки.
- Необязательный запуск vncserver. При работе без графического интерфейса X11 нужно запустить vncserver.
$ vncserver :1 $ export DISPLAY=:1
- Создание и редактирование файла конфигурации AUH. Нужно иметь файл upgrade-helper/upgrade-helper.conf в каталоге сборки. Образец файла можно найти в репозитории AUH и воспользоваться им для создания своего файла. Например, если нужно сохранять историю сборки, следует включить ее в upgrade-helper.conf.Если используется принятый по умолчанию файл maintainers.inc из дистрибутива Poky, размещенный в meta-yocto, не установлено maintainers_whitelist или global_maintainer_override в файле upgrade-helper.conf и задана опция -e all в командной строке AUH, утилита автоматически будет отправлять почтовые сообщения всем сопровождающим. Следует избегать этого.
Далее приведены примеры использования утилиты AUH.
- Обновление конкретного задания – upgrade-helper.py recipe_name. Например, для обновления xmodmap можно ввести команду upgrade-helper.py xmodmap.
- Обновление конкретного задания до указанной версии – upgrade-helper.py recipe_name -t version. Например, для обновления xmodmap до версии 1.2.3 служит команда upgrade-helper.py xmodmap -t 1.2.3.
- Обновление всех заданий до последних версий без уведомления сопровождающих – upgrade-helper.py all.
- Обновление всех заданий до последних версий с уведомлением сопровождающих – upgrade-helper.py -e all.
После запуска утилиты AUH можно посмотреть результаты в каталоге сборки AUH ${BUILDDIR}/upgrade-helper/timestamp. Утилита AUH также создает фиксации обновления заданий после успешного обновления в дереве уровня.
Можно настроить регулярный запуск AUH из задания cron. Пример этого представлен в файле weeklyjob.sh.
3.5.2. Использование devtool upgrade
Другим методом обновления заданий является команда devtool upgrade, подробно описанная в разделе Use devtool upgrade to Create a Version of the Recipe that Supports a Newer Version of the Software [2]. Справку о параметрах можно получить по команде devtool upgrade -h. Если нужно лишь узнать версию находящегося в разработке задания без его реального обновления, следует применять команду devtool latest-version recipe_name.
Как было отмечено в описании AUH, команда devtool upgrade менее автоматизирована, нежели AUH. В частности, devtool upgrade работает лишь с одним заданием, которое указано в командной строке, не может выполнять тестирование сборки и интеграции, а также автоматически создавать фиксацию (commit) изменений в дереве исходных кодов. Несмотря на эти ограничения, devtool upgrade обновляет файл задания до новой версии и пытается совместить пользовательские правки с patch-файлами репозитория. AUH на деле использует devtool upgrade, будучи своего рода «оболочкой» для devtool upgrade.
Типичный пример использования предполагает применение Git для клонирования репозитория, который будет применяться для сборки. Поскольку задание было создано раньше, уровень уже имеется в вашей конфигурации. Если же уровня нет, его можно легко добавить с помощью сценария bitbake-layers. Предположим, например, использование задания nano.bb с уровня meta-oe в репозитории meta-openembedded, также клонирование уровня в каталог /home/scottrif/meta-openembedded. Приведенная ниже команда, запущенная из каталога сборки, добавит уровень в конфигурацию сборки (${BUILDDIR}/conf/bblayers.conf):
$ bitbake-layers add-layer /home/scottrif/meta-openembedded/meta-oe NOTE: Starting bitbake server... Parsing recipes: 100% |##########################################| Time: 0:00:55 Parsing of 1431 .bb files complete (0 cached, 1431 parsed). 2040 targets, 56 skipped, 0 masked, 0 errors. Removing 12 recipes from the x86_64 sysroot: 100% |##############| Time: 0:00:00 Removing 1 recipes from the x86_64_i586 sysroot: 100% |##########| Time: 0:00:00 Removing 5 recipes from the i586 sysroot: 100% |#################| Time: 0:00:00 Removing 5 recipes from the qemux86 sysroot: 100% |##############| Time: 0:00:00
Предположим, что задание nano.bb в репозитории разработки имеет версию 2.9.3, а в локальном – 2.7.4. Приведенная ниже команда, запущенная из каталога сборки, автоматически обновит задание (опция -V не обязательна и при ее отсутствии devtool upgrade выполнит обновление до последней версии).
$ devtool upgrade nano -V 2.9.3 NOTE: Starting bitbake server... NOTE: Creating workspace layer in /home/scottrif/poky/build/workspace Parsing recipes: 100% |##########################################| Time: 0:00:46 Parsing of 1431 .bb files complete (0 cached, 1431 parsed). 2040 targets, 56 skipped, 0 masked, 0 errors. NOTE: Extracting current version source... NOTE: Resolving any missing task queue dependencies ... NOTE: Executing SetScene Tasks NOTE: Executing RunQueue Tasks NOTE: Tasks Summary: Attempted 74 tasks of which 72 didn't need to be rerun and all succeeded. Adding changed files: 100% |#####################################| Time: 0:00:00 NOTE: Upgraded source extracted to /home/scottrif/poky/build/workspace/sources/nano NOTE: New recipe is /home/scottrif/poky/build/workspace/recipes/nano/nano_2.9.3.bb
В продолжение примера используем команду devtool build для сборки обновленного задания.
$ devtool build nano NOTE: Starting bitbake server... Loading cache: 100% |################################################################################################| Time: 0:00:01 Loaded 2040 entries from dependency cache. Parsing recipes: 100% |##############################################################################################| Time: 0:00:00 Parsing of 1432 .bb files complete (1431 cached, 1 parsed). 2041 targets, 56 skipped, 0 masked, 0 errors. NOTE: Resolving any missing task queue dependencies ... NOTE: Executing SetScene Tasks NOTE: Executing RunQueue Tasks NOTE: nano: compiling from external source tree /home/scottrif/poky/build/workspace/sources/nano NOTE: Tasks Summary: Attempted 520 tasks of which 304 didn't need to be rerun and all succeeded.
В рабочем процессе devtool upgrade имеется возможность развернуть и протестировать вновь собранные программы. Однако в нашем примере команда devtool finish очищает рабочее пространство при очистке исходных кодов. Обычно это означает использование Git для подготовки и представления изменений, внесенных при обновлении. Как только дерево будет очищено, можно очистить остальное с помощью приведенной ниже команды из каталога ${BUILDDIR}/workspace/sources/nano.
$ devtool finish nano meta-oe NOTE: Starting bitbake server... Loading cache: 100% |################################################################################################| Time: 0:00:00 Loaded 2040 entries from dependency cache. Parsing recipes: 100% |##############################################################################################| Time: 0:00:01 Parsing of 1432 .bb files complete (1431 cached, 1 parsed). 2041 targets, 56 skipped, 0 masked, 0 errors. NOTE: Adding new patch 0001-nano.bb-Stuff-I-changed-when-upgrading-nano.bb.patch NOTE: Updating recipe nano_2.9.3.bb NOTE: Removing file /home/scottrif/meta-openembedded/meta-oe/recipes-support/nano/nano_2.7.4.bb NOTE: Moving recipe file to /home/scottrif/meta-openembedded/meta-oe/recipes-support/nano NOTE: Leaving source tree /home/scottrif/poky/build/workspace/sources/nano as-is; if you no longer need it then please delete it manually
Команда devtool finish очищает рабочее пространство и создает patch-файл на основе фиксаций (commit). Инструмент помещает все patch-файлы обратно в дерево исходного кода (каталог nano в данном случае).
3.5.3. Обновление заданий вручную
Если по какой-то причине обновление с помощью AUH или команды devtool upgrade не подходит, можно вручную отредактировать файлы задания для обновления версии. Обновление вручную множества заданий требует значительных усилий и времени, этапы процесса кратко описаны ниже.
- Смена версии. Следует переименовать задание с учетом версии (т. е. изменить PV в имени задания). Если версия не включена в имя измените значение, как это делается для PV в самом задании.
- Обновление SRCREV при необходимости. Если исходные коды задания получены с помощью Git или иной системы контроля версий, следует обновить SRCREV с указанием хеша фиксации для новой версии.
- Сборка программ. Соберите программу с помощью BitBake. Возможные отказы при сборке указаны ниже.
-
- Операторы лицензирования для новой версии изменены. В этом случае следует просмотреть изменния в лицензировании и при необходимости обновить переменные LICENSE и LIC_FILES_CHKSUM. Изменения в лицензиях зачастую малозначимы, например, может измениться год в авторских правах (copyright).
- Пользовательские изменения (patch) в старой версии могут не подойти для новой. В таких случаях нужно найти причину отказа. Исправления могут оказаться ненужными в новой версии, если проблема, вызвавшая их, была решена. Если правки нужны, но не работают, нужно изменить их для новой версии.
- Необязательная сборка для разной архитектуры. После сборки новой программы для одной архитектуры можно проверить другую, изменив переменную MACHINE. Это важно для публикуемых заданий.
- Проверка журнала обновлений и заметок к выпускам в репозитории. Просмотр упомянутого позволяет узнать о новых функциях и совместимости с прежними версиями. Это поможет при определении нужных действий.
- Необязательное создание и проверка загружаемого образа путем загрузки на реальном устройстве.
- Фиксация изменений в репозитории уровня. После успешной сборки и тестирования можно создать фиксацию (commit) для всех изменений на уровне, содержащем обновленное задание.
3.6. Поиск временных исходных кодов
Во время разработки может представиться полезным изменить временный исходный код используемый для сборки пакетов. Например, это может потребоваться при экспериментах для внесения правок (patch). После изначальной сборки пакеты можно итеративно настроить исходный код из каталога сборки, а затем форсировать повторную компиляцию и быстрое тестирование измененного кода. Когда решение будет найдено, можно сохранить внесенные изменения в форме правок (patch).
Во время сборки распакованный временный исходный код используется заданиями для сборки пакетов, доступный в сборочном каталоге, заданном переменной S. Ниже используется принятое по умолчанию значение S, указанное в файле meta/conf/bitbake.conf дерева исходных кодов, S = “${WORKDIR}/${BP}”. Многие задания переопределяют S, например, задания, получающие исходный код с помощью Git, обычно устанавливают S = ${WORKDIR}/git.
BP представляет базовое имя задания, включающее имя и версию в форме BP = “${BPN}-${PV}”. Путь к рабочему каталогу задания (WORKDIR) определяется как ${TMPDIR}/work/${MULTIMACH_TARGET_SYS}/${PN}/${EXTENDPE}${PV}-${PR}.
Реальные каталоги зависят от нескольких переменных:
- TMPDIR – выходной каталог верхнего уровня для сборки;
- MULTIMACH_TARGET_SYS – идентификатор целевой системы;
- PN – имя задания;
- EXTENDPE – эпоха (если PE не задана, что нормально для большинства заданий, значение EXTENDPE пусто);
- PV – версия задания;
- PR – ревизия (пересмотр) задания.
Предположим, например, каталог исходных кодов верхнего уровня poky, принятый по умолчанию каталог сборки poky/build и целевую систему qemux86-poky-linux. Кроме того, предположим, что задание названо foo_1.3.0.bb. В этом случае рабочим каталогом системы сборки будет poky/build/tmp/work/qemux86-poky-linux/foo/1.3.0-r0.
3.7. Использование Quilt
Quilt – это мощный инструмент для фиксации изменений исходного кода без наличия чистого дерева кода. В этом параграфе рассмотрен типовой процесс, который можно применять для изменения исходного кода, тестирования изменений и их сохранения в форме patch-файлов с помощью Quilt. В части сохранения изменений при очистке задания или включении rm_work процесс devtool, описанный в [2] является более надежным, чем использование Quilt.
Ниже приведены общие этапы работы с Quilt.
- Поиск исходного кода. Временный исходный код, используемый системой сборки OE, хранится в каталоге сборки. Поиск каталога с временным кодом для конкретного пакета рассмотрен в параграфе 3.6. Поиск временных исходных кодов.
- Смена рабочего каталога. Нужно перейти в каталог с временным исходным кодом, заданный переменной S.
- Создание правок (patch). Перед изменением исходного кода нужно создать patch-файл с помощью команды quilt new my_changes.patch.
- Уведомление Quilt и добавление файлов. После создания patch-файла нужно уведомить Quilt о файлах, которые планируется редактировать. Эти файлы могут быть добавлены к созданным правкам с помощью команды вида quilt add file1.c file2.c file3.c.
- Редактирование файлов. Отредактируйте указанные ранее файлы.
- Тестирование изменений. После редактирования исходного кода простейшим способом проверки внесенных изменений служит запуск задачи do_compile командой bitbake -c compile -f package. Опция -f или –force задает выполнение указанной в команде задачи. При возникновении проблем следует внести в исходный код соответствующие правки и повторить процедуру. Все изменения, внесенный во временные исходные коды, будут утеряны при запуске задачи do_clean или do_cleanall с помощью BitBake (команда bitbake -c clean package или bitbake -c cleanall package). Правки будут утеряны также при использовании функции rm_work, как описано в параграфе 3.21. Экономия дискового пространства при сборке.
- Создание patch-файла. После получения желаемых результатов правки нужно использовать Quilt для создания финального patch-файла со всеми внесенными изменениями. Для этого служит команда quilt refresh, после выполнения которой файл my_changes.patch будет включать все правки, внесенные в файлы file1.c, file2.c и file3.c. Файл правок будет размещен в каталоге patches/ дерева исходных кодов (S).
- Копирование patch-файла. Для простоты следует скопировать файл правок в каталог files, который можно создать в том же каталоге, где размещен файл задания (.bb) или добавления (.bbappend). Это позволит системе сборки OE найти файл правок. Затем patch-файл следует указать в переменной SRC_URI вашего задания, например, SRC_URI += “file://my_changes.patch”.
3.8. Использование среды devshell
При отладке некоторых команд или редактировании пакетов может быть полезна оболочка devshell, при вызове которой запускаются все задачи для указанной цели, вплоть до do_patch. Затем открывается новая консоль с текущим каталогом ${S} (исходный код). В этой консоли сохраняются все переменные среды OE, относящиеся к сборке, и можно пользоваться такими командами, как configure и make. Команды выполняются как в системе сборки OE, поэтому могут быть полезны для отладки или подготовки программы к использованию в системе сборки OE. Например, для использования devshell с целью matchbox-desktop может служить команда bitbake matchbox-desktop -c devshell, которая откроет терминал в среде сборки OE. Тип командного процессора задает переменная OE_TERMINAL. Для терминала:
- переменная PATH включает инструменты кросс-разработки;
- переменные pkgconfig находят нужные файлы .pc;
- команда configure находит файлы сайта YP и другие нужные файлы.
В этой среде можно вызывать команды configure или compile как при работе в системе сборки OE. Рабочим каталогом служит каталог исходных кодов (S).
Для запуска вручную из devshell нужной задачи служат сценарии run.* из каталога ${WORKDIR}/temp (например, run.do_configure.pid). Если сценария для задачи нет, что бывает в случае пропуска задачи в кэше sstate, можно создать задачу за пределами devshell с помощью команды bitbake -c task.
- Выполнение сценариев run.* и выполнение задач в BitBake идентично, т. е. запуск сценария запускает задачу так же, как при использовании bitbake -c command.
- Любой сценарий run.*, не имеющий расширения .pid, является символьной ссылкой на свежую версию файла.
Механизм devshell позволяет попасть в среду выполнения задач BitBake, поэтому все команды должны вызываться так же, как это делает BitBake. Это означает предоставление соответствующих опций кросс-компиляции и т. п.
По окончании работы с devshell следует использовать команду exit или просто закрыть терминальное окно.
- При работе в devshell нужно указывать полное имя компилятора (например, arm-poky-linux-gnueabi-gcc), а не просто gcc. Это относится и к приложениям binutils, libtool и т. п. BitBake устанавливает переменные окружения, такие как CC, чтобы команда make находила нужные инструменты.
- Среда devshell поддерживает пересылку X11 и другие подобные функции.
3.9. Использование среды разработки Python
Подобно использованию devshell, описанному выше, можно работать в интерактивной среде разработки Python. При отладке некоторых команд и редактировании пакетов devpyshell может служить полезным инструментом. При вызове devpyshell запускаются все задачи для указанной цели, вплоть до do_patch в новом терминальном окне. Важные объекты и код Python доступны как при работе с задачами BitBake (в частности, хранилище данных ‘d’). Ниже приведены некоторые полезные команды для работы с хранилищем данных и вызова функций.
pydevshell> d.getVar("STAGING_DIR") '/media/build1/poky/build/tmp/sysroots' pydevshell> d.getVar("STAGING_DIR") '${TMPDIR}/sysroots' pydevshell> d.setVar("FOO", "bar") pydevshell> d.getVar("FOO") 'bar' pydevshell> d.delVar("FOO") pydevshell> d.getVar("FOO") pydevshell> bb.build.exec_func("do_unpack", d) pydevshell>
Команды выполняются как в системе сборки OE, поэтому могут применяться для отладки и подготовки программ к сборке в системе OE. Ниже приведен пример использования devpyshell для цели matchbox-desktop.
$ bitbake matchbox-desktop -c devpyshell
Эта команда открывает терминальное окно с интерактивным интерпретатором Python в среде сборки OE. Тип командного процессора задает переменная OE_TERMINAL. По завершении работы с devpyshell следует ввести команду exit, нажать клавиши Ctrl+d или просто закрыть терминальное окно.
3.10. Сборка
В этом разделе описаны различные процедуры сборки, включая простые варианты, целевые системы с несколькими конфигурациями, сборку образов и т. п.
3.10.1. Сборка простого образа
В среде разработки нужно собирать образ при каждом изменении поддерживаемого оборудования, добавлении или изменении системных библиотек, а также служб, с которыми связаны зависимости. Имеется несколько методов сборки образов в YP. В этом параграфе рассматриваются основные этапы сборки простого образа с использованием BitBake на сборочном хосте Linux.
- Информация о работе с интерфейсом Toaster приведена в [8].
- Сборка образов с использованием devtool описана в разделе Using devtool in Your SDK Workflow [2].
- Пример быстрой сборки образа в системе OE приведен в [4].
Процесс сборки создает весь дистрибутив Linux из исходных кодов и помещает его в каталог tmp/deploy/images внутри сборочного каталога. Подробное описание процесса сборки с использованием BitBake дано в разделе Images [1].
На рисунке и в приведенном ниже списке приведен обзор процесса сборки.
- Организация хоста для поддержки разработки с использованием YP, как описано в главе Глава 2. Настройка YP.
- Инициализация среды сборки с помощью сценария oe-init-build-env по команде source oe-init-build-env [build_dir].При использовании сценария инициализации система сборки OE создает build в качестве принятого по умолчанию каталога сборки в текущем каталоге, из которого запущен сценарий. Аргумент build_dir позволяет задать иной каталог сборки. Общепринято использовать разные каталоги сборки для каждой цели. Например, ~/build/x86 для qemux86 и ~/build/arm для qemuarm.
- Проверка корректности файла conf/local.conf в каталоге с учетом реальных задач. Этот файл задает многие аспекты среды сборки, включая архитектуру машине в переменной MACHINE, формат пакетов для этой сборки (PACKAGE_CLASSES), и централизованный каталог загрузки архивов в переменной DL_DIR.
- Сборка образа с использованием команды bitbake target [6]. Параметр target указывает имя задания для сборки. Базовыми целями являются образы из каталогов meta/recipes-core/images, meta/recipes-sato/images и т. п. в каталоге исходных кодов. Параметр target может также указывать имя задания для определенного набора программ, такого как BusyBox. Более подробные сведения о поддерживаемых системой образах даны в разделе Images [3].Например, по команде bitbake core-image-minimal будет собран образ core-image-minimal.После сборки образа его зачастую нужно установить. Образы и ядра, создаваемые системой сборки OE помещаются в каталог tmp/deploy/images внутри каталога сборки. Информация о запуске собранных образов, таких как qemux86 и qemuarm приведена в [2], установка образов рассматривается в описаниях плат и машин.
3.10.2. Сборка образов для нескольких платформ с разными конфигурациями
Можно использовать одну команду bitbake для сборки нескольких образов или пакетов для разных целей, где каждому образу или пакету нужна своя конфигурация. Такое вариант сборки называют иногда multiconfigs. В этом параграфе описана организация среды для сборки разных конфигураций и учет зависимостей кросс-сборки для конфигураций.
3.10.2.1. Настройка и запуск сборки с несколькими конфигурациями
Для сборки нескольких конфигураций нужно задать конфигурацию для каждой цели, используя файл параллельной конфигурации в каталоге сборки, следуя требуемой иерархии файлов. Кроме того, нужно включить использование сборки нескольких конфигураций в файле local.conf.
- Создание отдельных файлов конфигурации. Нужно создать конфигурационный файл для каждого собираемого задания. По меньшей мере каждый такой файл должен задавать машину и временный каталог, используемый BitBake для сборки. Опыт диктует создание не перекрывающихся временных каталогов для сборки, однако можно использовать общий временный каталог TMPDIR. Например, при сборке двух конфигураций для одной машины (MACHINE) qemux86 с дистрибутивами poky и poky-lsb целесообразно примянать общий каталог TMPDIR.Ниже показаны требуемые операторы в файле конфигурации qemux86 с временным каталогом tmpmultix86.
MACHINE="qemux86" TMPDIR="${TOPDIR}/tmpmultix86"
Файлы конфигурации должны размещаться в определенном месте, а именно в подкаталоге multiconfig каталога conf. На рисунке показан пример с двумя конфигурационными файлами для x86 и arm в каталоге multiconfig.
Использование такой иерархии обусловлено тем, что переменная BBPATH не создается, пока не будут проанализированы уровни. Поэтому использование заранее подготовленного файла конфигурации невозможно, если он не находится в текущем рабочем каталоге. - Добавление переменной BitBake для нескольких конфигураций в локальный файл конфигурации. Переменная BBMULTICONFIG в файле conf/local.conf задает каждый файл конфигурации. В приведенном выше примере эта переменная имеет вид BBMULTICONFIG = “x86 arm”.
- Запуск BitBake с помощью команды вида
$ bitbake [multiconfig:multiconfigname:]target [[[multiconfig:multiconfigname:]target] ... ]
Для приведенного выше примера команда будет иметь вид
$ bitbake multiconfig:x86:core-image-minimal multiconfig:arm:core-image-sato
В результате будет собран образ core-image-minimal, заданный файлом x86.conf, и образ core-image-sato, заданный arm.conf.
Поддержка сборки нескольких конфигураций в выпуске YP 2.7.1 (Warrior) не включает оптимизации общего состояния (sstate), поэтому при использовании одного объекта несколько раз создается несколько каталогов TMPDIR и сборка использует имеющийся кэш sstate или запускается заново.
3.10.2.2. Включение зависимостей при сборке нескольких конфигураций
Иногда могут возникать зависимости между целями (multiconfig) при сборке нескольких конфигураций. Предположим, например, что при сборке образа core-image-sato для x86 нужна корневая файловая система arm. Это может быть связано с тем, что задача do_image в core-image-sato зависит от выполнения задачи do_rootfs в core-image-minimal. Для включения зависимостей при сборке нескольких конфигураций их нужно объявить в задании как task_or_package[mcdepends] = “multiconfig:from_multiconfig:to_multiconfig:recipe_name:task_on_which_to_depend“.
Рассмотрим в качестве примера конфигурацию из предыдущего параграфа. В этом случае нужно в задание для образа core-image-sato добавить строку do_image[mcdepends] = “multiconfig:x86:arm:core-image-minimal:do_rootfs”. В этом примере в качестве from_multiconfig служит x86, а в качестве to_multiconfig – arm. Задачей, от которой зависит do_image, является do_rootfs из задания core-image-minimal, связанного с arm.
После указания зависимости можно собрать образ x86 с помощью команды bitbake multiconfig:x86:core-image-sato. Команда выполняет все задачи, требуемые при создании образа core-image-sato для x86. В результате задания зависимости BitBake выполняет также задачу do_rootfs для arm.
Наличие задания, зависимого от корневой файловой системы другого задания может показаться бессмысленным. Рассмотрим это на примере оператора в задании core-image-sato.
do_image[mcdepends] = "multiconfig:x86:arm:core-image-minimal:do_image"
В этом случае BitBake нужно создать образ core-image-minimal для сборки arm, поскольку от него зависит сборка x86. В результате того, что x86 и arm включены во множественную конфигурацию и имеют раздельные конфигурационные файлы, BitBake помещает результаты сборки в соответствующие временные каталоги (TMPDIR).
3.10.3. Сборка образа initramfs
Образ первичного RAM-диска (initramfs) обеспечивает временную корневую файловую систему на раннем этапе инициализации (например, загрузка модулей, требуемых для нахождения и монтирования корневой системы).
Образ initramfs является «наследником» initrd и использует архив cpio на исходной файловой системе для загрузки в память при запуске Linux. Поскольку Linux использует содержимое архива в процессе инициализации, в образ initramfs нужно включать все драйверы и инструменты, нужные для монтирования окончательной корневой файловой системы.
Ниже перечислены этапы создания образа initramfs.
- Подготовка задания для initramfs. Можно воспользоваться заданием core-image-minimal-initramfs.bb из каталога meta/recipes-core в дереве исходных кодов как примером.
- Решение вопроса о встраивании образа initramfs в образ ядра. Если нужно объединить образ initramfs с образом ядра, следует задать INITRAMFS_IMAGE_BUNDLE = “1” в файле local.conf и установить переменную INITRAMFS_IMAGE в задании для сборки ядра. Рекомендуется объединять образы ядра и initramfs для предотвращения зацикливания зависимостей при включении в образ initramfs модулей ядра. Установка флага INITRAMFS_IMAGE_BUNDLE ведет к распаковке образа initramfs в каталог ${B}/usr/. Распакованный образ initramfs передается в Makefile ядра через переменную CONFIG_INITRAMFS_SOURCE, что позволяет встроить образ initramfs в ядро. Если образ initramfs не встраивается в образ ядра, это означает использование initrd. Создание initrd выполняется в основном через переменные INITRD_IMAGE, INITRD_LIVE и INITRD_IMAGE_LIVE (см. описание image-live.bbclass).
- Добавление элементов в initramfs через задания. При добавлении элементов initramfs следует использовать переменную PACKAGE_INSTALL, а не IMAGE_INSTALL, поскольку это обеспечивает более прямой контроль дополнений по сравнению с принятыми по умолчанию настройками классов image и core-image.
- Сборка образов ядра и initramfs. Ядро собирается с использованием BitBake. Поскольку задание для ядра зависит от initramfs, образ initramfs собирается и связывается с ядром, если установлена переменная INITRAMFS_IMAGE_BUNDLE, как указано выше.
3.10.4. Сборка миниатюрной системы
Компактные дистрибутивы могут обеспечивать ряд преимуществ, таких как меньшие потребности в памяти (снижение цены), повышение производительности за счет эффективного кэширования, снижение энергопотребления за счет уменьшения размера памяти, ускорение загрузки и снижение расходов на разработку. Примерами таких систем в реальном мире являются цифровые камеры, медицинское оборудование и т. п.
В этом параграфе приведена информация о способах сокращения размера дистрибутива по сравнению с poky-tiny, занимающим около 5 Мегабайт.
3.10.4.1. Обзор
Ниже представлены рассмотренные в соответствующих параграфах этапы снижения размера корневой файловой системы для обеспечения быстрой загрузки в сочетании с требуемой функциональностью без использования начального RAM-диска.
- 3.10.4.2. Цели и принципы
- 3.10.4.3. Влияние компонент на размер образа
- 3.10.4.4. Минимизация корневой файловой системы
- 3.10.4.5. Минимизация ядра
- 3.10.4.6. Исключение требований к управлению пакетами
- 3.10.4.7. Другие способы снижения размера
- 3.10.4.8. Итерации процесса
3.10.4.2. Цели и принципы
Ниже приведен список вопросов, которые нужно решить при создании компактных дистрибутивов:
- определение требуемого размера (например, ядро меньше 1 Мбайт и корневая файловая система не больше 3 Мбайт);
- определение областей, занимающих большую часть пространства для концентрации усилий по сокращению;
- отказ от внесения сложных изменений для достижения цели;
- использование специфичных для устройства опций;
- работа с отдельным уровнем для изоляции изменений (см. раздел 3.1. Уровни и их создание).
3.10.4.3. Влияние компонент на размер образа
Проще всего начать с создания своего дистрибутива. Можно воспользоваться в качестве примера имеющимся в YP дистрибутивом poky-tiny, для чего следует установить для переменной DISTRO в файле local.conf значение “poky-tiny”, как описано в разделе 3.19. Создание своего дистрибутива.
Понимание концепций работы с памятью позволит уменьшить размер системы. Память включает статические, динамические и временные разделы. Статическая память – это разделы TEXT (код), DATA (инициализированные данные в коде) и BSS (неинициализированные данные). Динамическая память выделяется в процессе работы для стека, хэш-таблиц и т. п. Временная память включает области для распаковки ядра и функций __init__ и освобождается по завершении загрузки.
Для просмотра текущих размеров ядра и корневой файловой системы в каталоге scripts/tiny/ дерева исходных кодов есть два полезных сценария:
- ksize.py определяет размер компонент собранного ядра;
- dirsize.py определяет размер компонент корневой файловой системы.
Еще один сценарий и команда помогают организовать фрагменты конфигурации и увидеть зависимости файлов.
- merge_config.sh помогает управлять конфигурационными файлами и фрагментами конфигурации ядра. Сценарий позволяет объединять фрагменты конфигурации, а также создавать переопределения и выдает предупреждения о пропущенных опциях. Это хорошо подходит для итеративной настройки конфигурации и создания конфигурационных файлов для разных машин без дублирования процессов.Сценарий является частью репозитория Linux Yocto (linux-yocto-3.14, linux-yocto-3.10, linux-yocto-3.8 и т. п.) и хранится в каталоге scripts/kconfig. Дополнительная информация о фрагментах конфигурации приведена в разделе Creating Configuration Fragments [7].
- bitbake -u taskexp -g bitbake_target открывает Dependency Explorer для просмотра зависимостей. Понимание зависимостей позволяет принять обоснованные решения при исключении компонент ядра и корневой файловой системы.
3.10.4.4. Минимизация корневой файловой системы
Корневая файловая система содержит пакеты для загрузки, библиотеки и приложения. Для изменения размера можно поменять способ подготовки пакетов, а также саму файловую систему.
Сначала следует разобраться с размерами файловой системы и отдельных файлов с помощью сценария dirsize.py:
$ cd root-directory-of-image $ dirsize.py 100000 > dirsize-100k.log $ cat dirsize-100k.log
Параметр 100000 задает игнорирование файлов, размер которых меньше 100 кбайт. Сценарий возвращает размеры несжатых файлов, поэтому на файловых системах с компрессией нужно вводить коэффициент. После просмотра журнала dirsize-100k.log можно будет сосредоточиться на крупных файлах.
Следует учитывать взаимосвязи между файлами, чтобы не навредить функциональности. Можно посмотреть зависимости с помощью интерфейса Dependency Explorer пакета BitBake, как показано ниже.
$ cd image-directory $ bitbake -u taskexp -g image
Изучив зависимости можно понять, какие пакеты или файлы можно безбоязненно исключить. При выборе пакетов для удаления следует учитывать их функциональность. Например, может оказаться ненужным дисплей VGA или можно обойтись devtmpfs и mdev вместо udev. Изменения следует вносить в файл local.conf. Например, для исключения udev и glib можно указать VIRTUAL-RUNTIME_dev_manager = “”.
Следует также учитывать тип корневой файловой системы и ее соответствие поставленным задачам. Например, можно рассмотреть системы cramfs, squashfs, ubifs, ext2 или initramfs. Следует учитывать, что файловой системе ext3 потребуется 1 Мбайт для журнала, который не будет нужен в файловой системе с доступом лишь для чтения.
После каждого исключения следует заново собирать систему, контролируя функциональность и размер.
3.10.4.5. Минимизация ядра
Ядро собирается с включением правил для зависимых от оборудования аспектов, включая разрешенные подсистемы, архитектуру, драйверы. При необходимости может изменяться исходный код ядра.
Сценарий ksize.py из каталога сборки верхнего уровня может подсказать, что следует изменить в ядре.
$ cd top-level-linux-build-directory $ ksize.py > ksize.log $ cat ksize.log
При просмотре журнала можно увидеть размер встроенных файлов .o для драйверов, сети, базовых функций, файловых систем, звука и т. п. Сценарий возвращает размеры несжатых компонент и для сжатых ядер следует вводить коэффициент. Следует выделить наиболее крупные области и оптимизировать их размеры. Для более подробного изучения структуры служит специальная опция -d.
$ ksize.py -d > ksize.log
Просмотр журнала позволяет определить компоненты, которые можно исключить. Например, если в системе нет звуковых устройств, можно исключить драйверы для звука.
После определения исключаемых компонент нужно заново настроить конфигурацию ядра для учета изменений при следующей сборке. Это можно сделать с помощью команды menuconfig. Однако в этом случае могут возникнуть затруднения с учетом влияния отдельных исключений, а также с репликацией изменений на другие целевые устройства. Лучше начать с пустой конфигурации, введя команду allnoconfig, создать фрагменты конфигурации для отдельных изменений, а затем использовать сценарий merge_config.sh. Это упрощает итерации настройки конфигурации в цикле сборки.
При каждом изменении конфигурации следует выполнять сборку ядра для контроля размера и результатов изменений.
3.10.4.6. Исключение требований к управлению пакетами
Требования управления пакетами ведут к увеличению образа, поэтому исключение этих требований позволяет сделать образ более компактным. Это включает удаление менеджера пакетов с его зависимостями, а также всех данных управления пакетами.
Для исключения требований к управлению пакетами следует убедиться в отсутствии значения package-management в операторе IMAGE_FEATURES для образа. При удалении этого свойства из корневой файловой системы будет исключен менеджер пакетов и все его зависимости.
3.10.4.7. Другие способы снижения размера
В зависимости от конкретных задач могут быть и иные способы снижения размера. При поиске решений могут помочь указанные здесь инструменты в сочетании с экспериментами и итерациями.
- glibc
-
- удалите из DISTRO_FEATURES свойства glibc, которые представляются ненужными;
- соберите дистрибутив;
- при возникновении отказа по причине отсутствия символов в пакете определите возможность настройки пакета без этих символов;
- повторите сборку и проверку работоспособности.
- busybox. Процедуры похожи на описанные выше для glibc. Разница заключается в необходимости загрузки получившейся системы для проверки. Нужно обеспечить интеграцию фрагментов конфигурации в Busybox, поскольку BusyBox самостоятельно обрабатывает основные возможности, позволяя добавлять фрагменты конфигурации.
3.10.4.8. Итерации процесса
Если цель не достигнута с первой попытки, процесс следует повторить. Следует обращать внимание на компоненты, занимающие 90% корневой файловой системы и ядра. Удаляйте компоненты, которые не нужны при работе системы.
В зависимости от конкретной системы следует обращать внимание на Busybox, где обеспечиваются урезанные версии инструментов Unix в одном исполняемом файле.
3.10.5. Сборка образов для нескольких машин
Разработчикам зачастую приходится создавать образы разных машин, использующих одинаковую программную среду. В таких случаях заманчиво установить настройки и флаги оптимизации для каждой сборки специально под целевую платформу. Однако это может существенно увеличить время сборки и осложнить поддержку хранилища пакетов для всех машин. Например, выбор настроек, наиболее подходящих для процессора платформы, может включать тонкую оптимизацию GCC для определенной платформы, но без этого не будет достигнуто существенного роста производительности по сравнению с применением базовых настроек для всех платформ. Вместо этого можно выполнить настройки, которые заставят систему сборки OE многократно использовать программные компоненты на разных платформах, когда это имеет смысл.
Если скорость сборки и обслуживание хранилища пакетов важны, следует рассмотреть приведенные ниже рекомендации.
- Общий каталог сборки. По возможности следует применять для сборок общий каталог TMPDIR. YP поддерживает переключение между значениями MACHINE в одном каталоге TMPDIR. Такая практика хорошо поддерживается и часто применяется разработчиками при сборке для нескольких машин. При использовании общего каталога TMPDIR система сборки OE может многократно применять имеющиеся естественные и кросс-задания для разных машин, что снижает время сборки. При изменении настроек DISTRO или важных параметров конфигурации (например, схема файловой системы) нужно начинать работу с чистого каталога TMPDIR. Общий каталог TMPDIR в таких случаях может работать, но это не гарантируется.
- Включение подходящей архитектуры управления пакетами. По умолчанию система сборки OE включает 3 уровня управления пакетами – all, tune или package, machine. Задания обычно выбирают для своего вывода одну архитектуру (тип). В зависимости от цели создания пакетов заданием наличие соответствующей архитектуры управления пакетами может напрямую влиять на время сборки.Задание, создающее сценарии, может выбрать архитектуру all, поскольку оно не создает двоичных файлов. Для выбора этой архитектуры следует обеспечить наследование класса allarch, который в данном случае настраивает множество переменных так, что пакеты подходят для разной архитектуры.Если задание создает машинозависимые пакеты или одна из зависимостей при работе или сборке уже включает машину или архитектуру, что делает задание машинозависимым, следует выбирать тип machine через переменную MACHINE_ARCH в виде PACKAGE_ARCH = “${MACHINE_ARCH}”. Если архитектура управления пакетами осознанно не включена через PACKAGE_ARCH, система сборки OE по умолчанию устанавливает PACKAGE_ARCH = “${TUNE_PKGARCH}”.
- Выбор базового файла настройки (по возможности). Некоторые настройки являются достаточно общими и могут применяться для разных платформ (например, armv5 устанавливает пакеты, которые в большинстве случаев могут работать на armv6 и armv7, а двоичные файлы i486 могут работать на i586 и последующих платформах). Однако следует понимать, что усовершенствования новых процессоров работать не будут.При выборе одной настройки для множества машин система сборки OE повторно использует собранные ранее программы, что сокращает время сборки. Даже при смене sysroot для машин программы не компилируются заново и в хранилище существует лишь один пакет.
- Управление детализацией подготовки пакетов. Иногда бывает полезно внедрение иного уровня архитектуры пакетов в дополнение к 3 указанным ранее. В качестве примера рассмотрим, как NXP (ранее Freescale) позволяет повторно использовать двоичные пакеты на своем уровне meta-freescale. Класс fsl-dynamic-packagearch обеспечивает совместное использование пакетов GPU для плат i.MX53, поскольку на всех применяется AMD GPU. Для плат i.MX6 можно поступить аналогично, поскольку все они используют Vivante GPU. Этот класс проверяет хранилище данных BitBake на предмет наличия пакетов, предоставляющих такую субархитектуру или зависящих от нее. При наличии таких пакетов класс устанавливает значение PACKAGE_ARCH на основе значения MACHINE_SUBARCH. Если пакет не предоставляет такую субархитектуру и не зависит от нее, но соответствует значению специфичного для машины фильтра, устанавливается MACHINE_ARCH. Это снижает число собираемых пакетов и экономит время.
- Использование инструментов отладки. Иногда возникают случаи повторной сборки программ без вашего ведома. Например, система сборки OE может не использовать общего состояния с другой машиной, которое вы предполагаете. Такие ситуации часто возникают в результате ссылок на машинозависимые переменные, такие как MACHINE, SERIAL_CONSOLES, XSERVER, MACHINE_FEATURES и т. п. в коде, который должен зависеть лишь от настройки или когда задание зависит (DEPENDS, RDEPENDS, RRECOMMENDS, RSUGGESTS и т. п.) от другого задания, уже определившего PACKAGE_ARCH как “${MACHINE_ARCH}”. Для таких случаев есть инструменты, помогающие разобраться в ситуации.
-
- sstate-diff-machines.sh в каталоге scripts репозитория исходных кодов. Информация о работе со сценарием приведена в комментариях.
- Опция BitBake “-S printdiff” заставляет BitBake попытаться насти максимальное соответствие подписи (например, в кэше общего состояния) и запустить bitbake-diffsigs для определения штампов и приращений (delta), где два штампа разошлись.
3.10.6. Сборка программ из внешних источников
По умолчанию система сборки OE использует в процессе работы сборочный каталог. Процесс сборки включает извлечение файлов исходного кода, их распаковку и применение исправления (если они есть). В некоторых случаях может потребоваться собрать программы из источников, расположенных вне системы сборки OE. Например, проект может включать BSP, ядро для которого имеет весьма специальные настройки, и при этом нужно минимизировать работу команды разработчиков с системой сборки, чтобы они могли сосредоточиться на своем проекте. В этом случае специализированное ядро может размещаться на машине, где осуществляется разработка и в переменной SRC_URI задания для сборки будет указан внешний каталог, чтобы не копировать файлы.
Для сборки программы из внешнего источника нужно наследовать класс externalsrc и указать в переменной EXTERNALSRC местоположение исходного кода. Эти операторы помещаются в файл local.conf, как показано ниже.
INHERIT += "externalsrc" EXTERNALSRC_pn-myrecipe = "path-to-your-source-tree"
Можно также задать переменные в файле задания или файле дополнения. Например,
EXTERNALSRC = "path" EXTERNALSRC_BUILD = "path"
Чтобы эти установки сработали, нужно глобально или локально наследовать класс externalsrc.
По умолчанию класс externalsrc.bbclass собирает исходный код в каталоге, отличающемся от внешнего каталога источников, заданного в EXTERNALSRC. Если нужно собрать исходный код в том же каталоге, где он хранится или в неком ином названном каталоге, можно указать нужный каталог в переменной EXTERNALSRC_BUILD
EXTERNALSRC_BUILD_pn-myrecipe = "path-to-your-source-tree"
3.10.7. Автономная репликация сборки
Иногда полезно сделать «моментальный снимок» разрабатываемого кода, использованного для сборки и затем применять этот снимок для репликации сборки в автономном режиме. Для этого нужно сначала подготовить и заполнить каталог файлами «снимка». После загрузки файлов их можно применять для репликации сборки в любой момент и с любой машины. Процедура подготовки описана ниже.
- Создание пустого каталога для загрузки (DL_DIR). Можно очистить имеющийся каталог или указать новое значение в переменной DL_DIR.
- Генерация архивов репозитория Git. В файле local.conf нужно указать строки:
DL_DIR = "/home/your-download-dir/" BB_GENERATE_MIRROR_TARBALLS = "1"
При выборке файлов на следующем этапе BitBake соберет файлы исходного кода и создаст архив в каталоге DL_DIR. Дополнительная информация приведена в описании BB_GENERATE_MIRROR_TARBALLS.
- Заполнение каталога загрузки без сборки с помощью BitBake:
$ bitbake target --runonly=fetch
После этого каталог загрузки (${DL_DIR}) будет содержать снимок исходного кода в виде архива.
- Необязательное удаление служебных данных Git или иных SCM. Можно удалить из каталога загрузки подкаталоги Git или других SCM, такие как ${DL_DIR}/git2/*, поскольку они присутствуют в архиве.
После заполнения каталога загрузки можно создать «свое зеркало» и собрать программу для своей целевой платформы, как описано ниже.
- Использование только локальных файлов. В файл local.conf следует добавить переменную SOURCE_MIRROR_URL, наследование класса own-mirrors и переменную BB_NO_NETWORK.
SOURCE_MIRROR_URL ?= "file:///home/your-download-dir/" INHERIT += "own-mirrors" BB_NO_NETWORK = "1"
SOURCE_MIRROR_URL и класс own-mirror задают использование каталога загрузки в качестве «своего зеркала», а переменная BB_NO_NETWORK заставляет BitBake извлекать файлы из локального источника.
- Начало с «чистого листа» путем удаления каталога ${TMPDIR} или использования нового каталога сборки.
- Сборка цели с использованием BitBake
$ bitbake target
Сборка выполняется с использованием локального снимка исходных файлов. Автономная сборка не будет работать, если задание пытается найти свежую версию программ путем установки SRCREV = “${AUTOREV}”, поскольку в этом случае система обращается в сеть, пытаясь найти последнюю версию программы в SCM. Задания, использующие AUTOREV, обычно являются пользовательскими или измененными, а задания из публичных репозиториев как правило не применяют AUTOREV.
При наличии заданий с AUTOREV можно выполнить приведенные ниже рекомендации для автономной сборки.
- Использовать конфигурацию, созданную включением истории сборки (3.28.1. Управление историей сборки).
- Использовать команду buildhistory-collect-srcrevs для сбора сохраненных значений SRCREV из истории сборки (3.28.2.1. История сборки пакета).
- Поскольку имеются корректные выпуски исходного кода, можно изменить задания, установив в SRCREV нужные версии программ.
3.11. Ускорение сборки
Время сборки может быть продолжительным. По умолчанию система сборки применяет простые элементы управления для повышения эффективности сборки. Обычно принятые по умолчанию значения перечисленных ниже переменных обеспечивают наиболее эффективную сборку на системах с одним процессором (не ядром). Если на хосте имеется несколько CPU, можно попытаться изменить эти переменные для повышения скорости сборки.
- BB_NUMBER_THREADS задает максимальное число потоков для выполнения задач BitBake.
- BB_NUMBER_PARSE_THREADS задает число потоков, используемых BitBake при анализе заданий.
- PARALLEL_MAKE – добавочные опции, передаваемые команде make в задаче do_compile для выполнения параллельной компиляции на локальном хосте сборки.
- PARALLEL_MAKEINST – добавочные опции, передаваемые команде make в задаче do_install для выполнения параллельной инсталляции на локальном хосте сборки.
Эти переменные управляют числом процессорных ядер, доступных системе сборки. Для однопроцессорных систем автоматическое масштабирование обеспечивает использование системой сборки возможностей параллельного выполнения операций. Ниже рассмотрены дополнительные факторы, способные влиять на скорость сборки.
- Тип файловой системы на хосте сборки может влиять на скорость. Рекомендуется использовать файловые системы ext4, поскольку они обеспечивают более высокую производительность по сравнению с ext2 и ext3.
- Запрет обновления времени доступа с помощью noatime. Опция монтирования noatime позволяет системе сборки не обновлять время доступа к файлам и каталогам.
- Более продолжительный интервал фиксации. Использовании опции монтирования “commit=” позволяет задать интервал (в секундах) между записями дискового кэша. Смена принятого по умолчанию интервала в 5 секунд на более долгий повышает производительность сборки, но также увеличивает риск потери данных.
- Выбор системы управления пакетами. Из числа доступных менеджеров самым быстрым является IPK. Кроме того, ускоряет сборку использование единственного менеджера вместо нескольких.
- Использование файловой системы tmpfs для каталога TMPDIR может ускорить сборку, но преимущества ограничены, поскольку компилятор использует -pipe. Система сборки предпринимает несколько действий по предотвращению вызовов sync() для файловой системы, исходя из того, что при серьезном отказе содержимое каталога сборки легко создать заново.
- Наследование класса rm_work позволяет ускорить сборку за счет снижения объема данных, сохраняемых в кэше и на диске. Это также ускоряет очистку TMPDIR. Разработчики файловых систем рекомендуют в качестве наиболее быстрого способа удаления большого числа файлов переформатирование файловой системы. Однако это требует соответствующей организации дисковых разделов.
В дополнение к перечисленным рекомендациям отметим несколько компромиссов, которые могут ускорить сборку.
- Удаление ненужных элементов из DISTRO_FEATURES.
- Исключение отладочных символов и других данных отладки путем запрета генерации пакетов*-dbg установкой INHIBIT_PACKAGE_DEBUG_SPLIT = “1”.
- Запрет создания статических библиотек для заданий, выведенных из autoconf или libtool, как показано ниже.
STATICLIBCONF = "--disable-static" STATICLIBCONF_sqlite3-native = "" EXTRA_OECONF += "${STATICLIBCONF}"
-
- Некоторым заданиям статические библиотеки нужны для корректной работы (например, pseudo-native требует sqlite3-native). Приведенные выше переопределения учитывают это.
- Для подготовки некоторых пакетов нужны статические библиотеки и может потребоваться их сборка.
3.12. Работа с библиотеками
Библиотеки являются важной частью сборки и здесь даны некоторые рекомендации по работе с библиотеками.
3.12.1. Включение файлов статических библиотек
При создании библиотеки, предлагающей статическую компоновку можно управлять включением в собираемую библиотеку статических файлов (*.a). Переменные PACKAGES и FILES_* в файле meta/conf/bitbake.conf определяют включение в пакеты файлов, установленных задачей do_install. По молчанию PACKAGES включает ${PN}-staticdev, представляя все файлы статических библиотек. В нескольких прежних выпусках YP статические библиотеки указывались как ${PN}-dev. Ниже приведен фрагмент файла конфигурации BitBake для файлов статических библиотек.
PACKAGE_BEFORE_PN ?= "" PACKAGES = "${PN}-dbg ${PN}-staticdev ${PN}-dev ${PN}-doc ${PN}-locale ${PACKAGE_BEFORE_PN} ${PN}" PACKAGES_DYNAMIC = "^${PN}-locale-.*" FILES = "" FILES_${PN} = "${bindir}/* ${sbindir}/* ${libexecdir}/* ${libdir}/lib*${SOLIBS} \ ${sysconfdir} ${sharedstatedir} ${localstatedir} \ ${base_bindir}/* ${base_sbindir}/* \ ${base_libdir}/*${SOLIBS} \ ${base_prefix}/lib/udev/rules.d ${prefix}/lib/udev/rules.d \ ${datadir}/${BPN} ${libdir}/${BPN}/* \ ${datadir}/pixmaps ${datadir}/applications \ ${datadir}/idl ${datadir}/omf ${datadir}/sounds \ ${libdir}/bonobo/servers" FILES_${PN}-bin = "${bindir}/* ${sbindir}/*" FILES_${PN}-doc = "${docdir} ${mandir} ${infodir} ${datadir}/gtk-doc \ ${datadir}/gnome/help" SECTION_${PN}-doc = "doc" FILES_SOLIBSDEV ?= "${base_libdir}/lib*${SOLIBSDEV} ${libdir}/lib*${SOLIBSDEV}" FILES_${PN}-dev = "${includedir} ${FILES_SOLIBSDEV} ${libdir}/*.la \ ${libdir}/*.o ${libdir}/pkgconfig ${datadir}/pkgconfig \ ${datadir}/aclocal ${base_libdir}/*.o \ ${libdir}/${BPN}/*.la ${base_libdir}/*.la" SECTION_${PN}-dev = "devel" ALLOW_EMPTY_${PN}-dev = "1" RDEPENDS_${PN}-dev = "${PN} (= ${EXTENDPKGV})" FILES_${PN}-staticdev = "${libdir}/*.a ${base_libdir}/*.a ${libdir}/${BPN}/*.a" SECTION_${PN}-staticdev = "devel" RDEPENDS_${PN}-staticdev = "${PN}-dev (= ${EXTENDPKGV})"
3.12.2. Объединение разных версий библиотек в одном образе
Система сборки позволяет создавать библиотеки с оптимизацией под разные платформы и архитектуру, объединяя их в одном образе. Можно связать разные исполняемые файлы образа с разными библиотеками для конкретных вариантов применения. Это свойство называется Multilib. Примером может служить ситуация, когда большая часть системы собрана в 32-битовом режиме с 32-битовыми библиотеками, но есть некоторые 64-битовые приложения, которым нужны 64-битовые библиотеки. Хотя feature чаще всего используется для обслуживания различий между 32- и 64-битовыми приложениями, система сборки упрощает и другие варианты оптимизации. Можно собрать некоторые приложения для работы с одним набором библиотек, другие – с иным. Библиотеки могут различаться архитектурой, опциями компиляции и другими параметрами оптимизации. Несколько примеров представлено на уровне meta-skeleton:
- conf/multilib-example.conf;
- conf/multilib-example2.conf;
- recipes-multilib/images/core-image-multilib-example.bb.
3.12.2.1. Подготовка к использованию Multilib
Применение Multilib обусловлено потребностями пользователей, поэтому нет готовой конфигурации на все случаи. Для включения Multilib нужно сначала обеспечить поддержку разных библиотек в задании, что уже реализовано во многих стандартных заданиях. Следует проверить значение переменной BBCLASSEXTEND в файле meta/conf/multilib.conf дерева источников. В конечном итоге поддержка будет включена во все задания и проверка станет ненужной.
Расширение Multilib в основном работает автоматически, преобразуя имя пакета ${PN} в ${MLPREFIX}${PN}, где MLPREFIX указывает конкретную библиотеку (например, “lib32-” or “lib64-“). Стандартные переменные, такие как DEPENDS, RDEPENDS, RPROVIDES, RRECOMMENDS, PACKAGES и PACKAGES_DYNAMIC преобразуются системой автоматически. Если задание преобразуется вручную, можно использовать переменную ${MLPREFIX} для корректного преобразования имен. Код автоматического преобразования включен в класс multilib.bbclass.
3.12.2.2. Использование Multilib
После настройки заданий нужно указть требуемую комбинацию библиотек в файле local.conf каталога сборки.
MACHINE = "qemux86-64" require conf/multilib.conf MULTILIBS = "multilib:lib32" DEFAULTTUNE_virtclass-multilib-lib32 = "x86" IMAGE_INSTALL_append = " lib32-glib-2.0"
В приведенном примере включена дополнительная библиотека lib32. При объединении с вариантами lib32 в примере используется x86. Эту настройку можно посмотреть в файле meta/conf/machine/include/ia32/arch-ia32.inc. Пример включает lib32-glib-2.0 во все образы, что является одним из вариантов. Можно использовать обычную сборку образа для включения этой зависимости. Например, bitbake core-image-sato. Можно также собрать пакеты Multilib независимо с помощью команды вида bitbake lib32-glib-2.0.
3.12.2.3. Детали реализации
Имеются как общие, так и связанные с системой менеджером пакетов детали реализации. Рассмотрим сначала общие.
- Типичное соглашения для кода расширения класса, используемого Multilib, предполагает, что все имена пакетов из PACKAGES, включающие ${PN}, начинаются с ${PN}. При указании ${PN} не в начале имени возникают проблемы.
- Значение TARGET_VENDOR в Multilib расширено до “-vendormlmultilib” (например, -pokymllib32 для lib32 в Multilib с Poky). Причиной послужило то, что символы – в строке производителя в настоящее время противоречат config.sub в Autoconf, а использование иных разделителей проблематично.
Для системы управления пакетами RPM также существует ряд деталей, указанных ниже.
- Определенная отдельная архитектура для пакетов Multilib, а также отдельный каталог развертывания tmp/deploy/rpm. Например, для lib32 в образе qemux86-64 будут представлены архитектуры “all”, “qemux86_64”, “lib32_qemux86_64” и “lib32_x86”.
- Переменная ${MLPREFIX} вырезается из ${PN} при подготовке пакетов RPM. Именование обычных и Multilib пакетов RPM в системе qemux86-64 будет иметь вид bash-4.1-r2.x86_64.rpm и bash-4.1.r2.lib32_x86.rpm.
- Для образа Multilib менеджер RPM сначала устанавливает базовый образ, затем – библиотеки Multilib.
- Система сборки использует RPM при совпадении имен файлов в нескольких пакетах Multilib.
Детали, связанные с системой управления IPK, перечислены ниже.
- ${MLPREFIX} не удаляется из ${PN} при подготовке пакетов IPK. Именование обычных и Multilib пакетов IPK в системе qemux86-64 имеет вид bash_4.1-r2.x86_64.ipk и lib32-bash_4.1-rw_x86.ipk.
- Каталог развертывания IPK не меняется при использовании ${MLPREFIX}, поскольку пакеты различаются значениями ${PN}.
- IPK проверяет пригодность установки Multilib с использованием правил сравнения, переопределения и т. п.
3.12.3. Установка нескольких версий одной библиотеки
Может возникать потребность использовать одновременно несколько версий библиотеки в одной системе. Это почти всегда происходит при смене версии API, если имеется несколько программ, работающих с разными версиями библиотеки. Решением проблемы является параллельная установка нескольких версий в одной системе. Сделать это достаточно просто, если библиотеки корректно управляют версиями. Нужно просто отдельно указать библиотеки путем подготовки заданий с именами, где переменная PN включает версию библиотеки (например, старшую часть номера). В результате каждое задание будет загружать свою версию библиотеки. Например, показанные ниже примеры имен заданий для библиотеки clutter позволяют использовать две версии.
clutter-1.6_1.6.20.bb
clutter-1.8_1.8.4.bb
Если другие задания зависят от конкретной версии библиотеки, нужно указать соответствующую версию в переменной DEPENDS таких заданий. Например, для задания, зависящего от библиотеки clutter версии 1.8, следует указать DEPENDS = “clutter-1.8”.
1Source Control Manager.
2Board Support Package – пакет поддержки плат.
3QuickEMUlator.
4Windows Subsystem for Linux – подсистема Windows для Linux.
5Опыт показывает, что YP достаточно эффективно работает на сборочном хосте с Linux Mageia 7.1.
6Опыт сборки образов для платформы HiFive Unleashed объем исходных файлов и результатов сборки около 80 Гбайт. Дополнительно отметим, что каталог сборки лучше размещать на быстром диск (SAS или SSD), поскольку это значительно ускоряет работу.
7Software Development Kit – комплект для разработки программ.
8CROssPlatformS – модель кросс-платформенной разработки с открытым исходным кодом.