Openembedded: Часть 2. Создание и использование SDK для ARM

OpenEmbedded SDKДля написания программ для платформ отличных от х86 требуется cross-toolchain. Cross-toolchain - это набор кросс-компиляторов, соответствующего окружения и кросс-библиотек, таких как libc под выбранную платформу, в нашем случае это будет ARM, а конкретно ARM926. В прошлой статье мы начали знакомство с OpenEmbedded, этот фреймворк позволяет как построить собственный cross-toolchain, так и использовать прекомпилированные SDK которые можно найти в интернете, например Yagarto или CodeSourcery. Последняя возможность очень скупо описана на официальном сайте, тем интереснее будет исследовать её. Работать мы будем с процессорным модулем PM9263 от Австрийской компании Ronetix. К счастью, эта компания уже интегрировала поддержку своих модулей в OpenEmbedded так что нам остается только установить переменную MACHINE в файле конфигурации Bitbake. Забегая вперед скажу, что Вам надо позаботиться о свободном месте на диске. При строительстве SDK каталог ~/my-distr/tmp стал занимать 21.4Гб, в общем система пересталаа влезать на мой 30 гигабайтный винчестер, пришлось поправить переменную TMPDIR в файле ~/my-distr/build/conf/local.conf и разместить временный каталог на другом диске.

Подготовка

Отредактируем файл ~/my-distr/build/conf/local.conf
Изменим строки:

MACHINE = "ronetix-pm9263"
DISTRO = "angstrom-2010.x"

 

Создание Software Development Kit (SDK)

Software Development Kit (SDK) должен обеспечивать окружение и инструменты для создания приложений которые будут работать на целевой системе. Для этого SDK содержат кросс-компиляторы, библиотеки и подключаемые файлы заголовков, а также сценарии для установки переменных среды окружения. Как мы уже упоминали ранее, OpenEmbedded позволяет строить такие законченные SDK.

В OpenEmbedded SDK разделены на 2 логические части, host и target

Подготовка host-части SDK

host-часть - строит утилиты которые должны будут запускаться на host-PC, такие как cmake или симулятор qemu, а так же различные скрипты и библиотеки. Эти утилиты импортируются наследованием SDK (inherit sdk) и по соглашению имена таких пакетов оканчиваются на -sdk, для примера можете посмотреть файл 'task-sdk-host.bb'.

Части SDK создаются как задачи (task). Создаим файл с именем task-my-toolchain-host.bb в каталоге '~/my-distr/openembedded/recipes/tasks' и запишем в него следующий текст

require task-sdk-host.bb
DESCRIPTION = "Host packages for my-distr SDK"
LICENSE = "MIT"
ALLOW_EMPTY = "1"
RDEPENDS_${PN} += ""

Пока мы не планируем использовать какие-либо дополнительные пакеты, по-этому оставим список зависимостей пустым (в дальнейшем мы выясним, что нам надо было включить сюда библиотеку libusb), а базовые пакеты, такие как gcc-cross-sdk, gdb-cross-sdk и другие подключены в файле task-sdk-host.bb.

Подготовка target-части SDK

target-часть - строит заголовочные файлы и библиотеки которые будут использоваться при разработке приложений. В OpenEmbedded имена пакетов для файлов заголовков, символических ссылок на библиотеки, pkg-config файлов и т.п. оканчиваются на -dev. Для инсталляции девелопмент пакетов в SDK создадим файл task-my-toolchain-target.bb в каталоге '~/my-distr/openembedded/recipes/tasks' со следующим содержимым

DESCRIPTION = "Target packages for my-distr SDK"
LICENSE = "MIT"
ALLOW_EMPTY = "1"

PR = "r0"

PACKAGES = "${PN}"

DEPENDS = "task-sdk-bare"


RDEPENDS_${PN} += "\
	task-sdk-bare \
        "

Здесь минимальный набор пакетов импортируется из файла task-sdk-bare.

Сложим их вместе

В предыдущих двух частях мы подготовили host и target части SDK, теперь нам осталось только сложить их вместе. Создадим meta-toolchain-my.bb в каталоге '~/my-distr/openembedded/recipes/meta' с текстом

PR = "r0"
TOOLCHAIN_TARGET_TASK = "task-my-toolchain-target"
TOOLCHAIN_HOST_TASK = "task-my-toolchain-host"

require meta-toolchain.bb
SDK_SUFFIX = "toolchain-my"

Теперь можно запустить сборку SDK коммандой

~/my-distr$ bitbake meta-toolchain-my

Если все прошло успешно, то в конце Вы увидите что-то похожее на

NOTE: Tasks Summary: Attempted 1281 tasks of which 980 didn't need to be rerun and 0 failed.

К сожалению, более внятной информации о завершении процесса сборки чего бы то ни было, bitbake не дает. После удачной сборки SDK в каталоге '~/my-distr/tmp/deploy/eglibc/sdk/' должны появиться файлы 'angstrom-v20110413-i686-linux-armv5te-linux-gnueabi-toolchain-my-extras.tar.bz2' и 'angstrom-v20110413-i686-linux-armv5te-linux-gnueabi-toolchain-my.tar.bz2', в них и находится наш только что созданный SDK. Цифры 20110413 в имени - это дата сборки, у Вас она, естественно, будет другой.

Установка и проверка SDK

Теперь эти файлы нужно распаковать в корневой каталог:

cd /
sudo tar xf ~/my-distr/tmp/deploy/eglibc/sdk/angstrom-v20110413-i686-linux-armv5te-linux-gnueabi-toolchain-my.tar.bz2
sudo tar xf ~/my-distr/tmp/deploy/eglibc/sdk/angstrom-v20110413-i686-linux-armv5te-linux-gnueabi-toolchain-my-extras.tar.bz2

Чтобы использовать SDK выполните следующую команду:

$ . /usr/local/angstrom/arm/environment-setup

Ее нужно будет выполнять всякий раз при начале работы, или прописать ее в .bashrc чтобы это выполнялось автоматически. Теперь проверим:

$ arm-angstrom-linux-gnueabi-gcc -v
Using built-in specs.
COLLECT_GCC=arm-angstrom-linux-gnueabi-gcc
Target: arm-angstrom-linux-gnueabi
Configured with: /mnt/windows/Dimon/oetmp/work/i686-armv5te-sdk-angstrom-linux-gnueabi/gcc-cross-sdk-4.5-r31.2+svnr168622/gcc-4_5-branch/configure --build=i686-linux --host=i686-linux --target=arm-angstrom-linux-gnueabi --prefix=/usr/local/angstrom/arm --exec_prefix=/usr/local/angstrom/arm --bindir=/usr/local/angstrom/arm/bin --sbindir=/usr/local/angstrom/arm/bin --libexecdir=/usr/local/angstrom/arm/libexec --datadir=/usr/local/angstrom/arm/share --sysconfdir=/usr/local/angstrom/arm/etc --sharedstatedir=/usr/local/angstrom/arm/share/com --localstatedir=/usr/local/angstrom/arm/var --libdir=/usr/local/angstrom/arm/lib --includedir=/usr/local/angstrom/arm/include --oldincludedir=/usr/local/angstrom/arm/include --infodir=/usr/local/angstrom/arm/share/info --mandir=/usr/local/angstrom/arm/share/man --with-libtool-sysroot --enable-largefile --disable-nls --enable-ipv6 --with-gnu-ld --enable-shared --enable-languages=c,c++,objc --enable-threads=posix --disable-multilib --enable-c99 --enable-long-long --enable-symvers=gnu --enable-libstdcxx-pch --program-prefix=arm-angstrom-linux-gnueabi- --enable-target-optspace --enable-lto --enable-libssp --disable-bootstrap --disable-libgomp --disable-libmudflap --with-float=soft --with-sysroot=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi --with-build-time-tools=/mnt/windows/Dimon/oetmp/sysroots/i686-linux/usr/armv5te/arm-angstrom-linux-gnueabi/bin --with-build-sysroot=/mnt/windows/Dimon/oetmp/sysroots/armv5te-angstrom-linux-gnueabi --disable-libunwind-exceptions --with-mpfr=/mnt/windows/Dimon/oetmp/sysroots/i686-linux/usr --with-system-zlib --enable-__cxa_atexit
Thread model: posix
gcc version 4.5.3 20110110 (prerelease) (GCC) 

Точно таким же образом вы можете установить SDK на любой другой компьютер работающий под управлением ОС Linux.

Решение проблем

ERROR: QA Issue with eglibc-pic: non debug package contains .debug directory: eglibc-pic path /work/armv5te-angstrom-linux-gnueabi/eglibc-2.12-r21.8+svnr12323/packages-split/eglibc-pic/usr/lib/libc_pic/.debug/sofini.o
ERROR: QA Issue with eglibc-pic: non debug package contains .debug directory: eglibc-pic path /work/armv5te-angstrom-linux-gnueabi/eglibc-2.12-r21.8+svnr12323/packages-split/eglibc-pic/usr/lib/libc_pic/.debug/soinit.o
ERROR: QA Issue with eglibc-pic: non debug package contains .debug directory: eglibc-pic path /work/armv5te-angstrom-linux-gnueabi/eglibc-2.12-r21.8+svnr12323/packages-split/eglibc-pic/usr/lib/libc_pic/.debug/sofini.o
ERROR: QA Issue with eglibc-pic: non debug package contains .debug directory: eglibc-pic path /work/armv5te-angstrom-linux-gnueabi/eglibc-2.12-r21.8+svnr12323/packages-split/eglibc-pic/usr/lib/libc_pic/.debug/soinit.o
FATAL: QA run found fatal errors. Please consider fixing them.
ERROR: Error in executing python function in: ~/my-distr/openembedded/recipes/eglibc/eglibc_2.12.bb
ERROR: Exception:<type 'exceptions.SystemExit'> Message:1
ERROR: Printing the environment of the function
ERROR: Function do_package_qa failed
ERROR: TaskFailed event exception, aborting
ERROR: Build of ~/my-distr/openembedded/recipes/eglibc/eglibc_2.12.bb do_package failed
FATAL: QA run found fatal errors. Please consider fixing them.
ERROR: Task 67 (~/my-distr/openembedded/recipes/eglibc/eglibc_2.12.bb, do_package) failed with 256
ERROR: TaskFailed event exception, aborting
ERROR: Build of ~/my-distr/openembedded/recipes/gcc/gcc-cross_4.5.bb do_compile failed
ERROR: TaskFailed event exception, aborting
ERROR: Build of ~/my-distr/openembedded/recipes/gcc/gcc-cross-sdk_4.5.bb do_compile failed

Как можно понять из сообщения, в файле '~/my-distr/openembedded/recipes/eglibc/eglibc_2.12.bb' есть проблема, а именно, не dbg пакет содержит в себе .debug каталог. Чтобы исправить эту ситуацию надо отредактироватьстроку в файле '/my-distr/openembedded/recipes/eglibc/eglibc-package.inc':

FILES_${PN}-dbg += "${libexecdir}/*/.debug ${libdir}/gconv/.debug"

Заменить на

FILES_${PN}-dbg += "${libexecdir}/*/.debug ${libdir}/gconv/.debug ${libdir}/libc_pic/.debug"

И заново запустить сборку SDK. Если после этого Вы увидите такое сообщение об ошибке

ERROR: TaskFailed event exception, aborting
ERROR: Build of /home/d400/my-distr/openembedded/recipes/eglibc/eglibc_2.12.bb do_configure failed
ERROR: Task 64 (/home/d400/my-distr/openembedded/recipes/eglibc/eglibc_2.12.bb, do_configure) failed with 256
ERROR: '/home/d400/my-distr/openembedded/recipes/eglibc/eglibc_2.12.bb' failed
ERROR: Function do_configure failed
NOTE: Task failed: ('function do_configure failed', '/mnt/windows/Dimon/oetmp/work/armv5te-angstrom-linux-gnueabi/eglibc-2.12-r21.8+svnr12323/temp/log.do_configure.10632')
ERROR: Logfile of failure stored in: /mnt/windows/Dimon/oetmp/work/armv5te-angstrom-linux-gnueabi/eglibc-2.12-r21.8+svnr12323/temp/log.do_configure.10632
Log data follows:
| checking build system type... i686-pc-linux-gnu
| checking host system type... arm-angstrom-linux-gnueabi
| checking for arm-angstrom-linux-gnueabi-gcc... arm-angstrom-linux-gnueabi-gcc -march=armv5te -mtune=arm926ej-s -mthumb-interwork -mno-thumb
| checking for suffix of object files... o
| checking whether we are using the GNU C compiler... yes
| checking whether arm-angstrom-linux-gnueabi-gcc -march=armv5te -mtune=arm926ej-s -mthumb-interwork -mno-thumb accepts -g... yes
| checking for arm-angstrom-linux-gnueabi-gcc -march=armv5te -mtune=arm926ej-s -mthumb-interwork -mno-thumb option to accept ISO C89... unsupported
| checking for gcc... gcc
| checking how to run the C preprocessor... arm-angstrom-linux-gnueabi-gcc -E
| configure: error: in `/mnt/windows/Dimon/oetmp/work/armv5te-angstrom-linux-gnueabi/eglibc-2.12-r21.8+svnr12323/build-arm-angstrom-linux-gnueabi':
| configure: error: C preprocessor "arm-angstrom-linux-gnueabi-gcc -E" fails sanity check
| See `config.log' for more details.
| ERROR: Function do_configure failed
NOTE: package eglibc-2.12-r21.8+svnr12323: task do_configure: Failed
ERROR: TaskFailed event exception, aborting
ERROR: Build of /home/d400/my-distr/openembedded/recipes/eglibc/eglibc_2.12.bb do_configure failed
ERROR: Task 64 (/home/d400/my-distr/openembedded/recipes/eglibc/eglibc_2.12.bb, do_configure) failed with 256
ERROR: '/home/d400/my-distr/openembedded/recipes/eglibc/eglibc_2.12.bb' failed
ERROR: '/home/d400/my-distr/openembedded/recipes/eglibc/eglibc_2.12.bb' failed

то выполните очистку пакетов eglibc-initial и eglibc

~/my-distr$ bitbake -cclean eglibc-initial eglibc

И снова запустите сборку SDK.

Использование прекомпилированного toolchain-а

TODO: You want to use external-toolchain. Setting PREFERRED_PROVIDER for the toolchain to that + environment variables + toolchain layout. Please someone write the documentation for that.

Вот и всё что написано на сайте openembedded.org о возможности использования готовых cross-toolchain-ов. Печально, но не страшно, попробуем разобраться. В интернете нашлось вот такое описание использования прекомпилированного toolchain-а совместно с OE. Вообще, файлы конфигурации OE довольно хорошо откомментированы, так что иногда проще почитать коммантарии, чем рыться в документации.

Итак, как я писал в самом начале статьи, cross-toolchain состоит из:

  • binutils, таких как gcc, as, ld и т.д.
  • библиотек, таких как libc
  • переменных окружения и путей ко всему этому добру.

Всё это мы и должны сконфигурировать.

Binutils

У меня они лежат в каталоге /usr/local/angstrom/arm/bin/, вот список:

arm-angstrom-linux-gnueabi-addr2line
arm-angstrom-linux-gnueabi-ar
arm-angstrom-linux-gnueabi-as
arm-angstrom-linux-gnueabi-c++filt
arm-angstrom-linux-gnueabi-cpp
arm-angstrom-linux-gnueabi-g++
arm-angstrom-linux-gnueabi-gcc
arm-angstrom-linux-gnueabi-gccbug
arm-angstrom-linux-gnueabi-gcov
arm-angstrom-linux-gnueabi-gdb
arm-angstrom-linux-gnueabi-gdbtui
arm-angstrom-linux-gnueabi-gprof
arm-angstrom-linux-gnueabi-ld
arm-angstrom-linux-gnueabi-nm
arm-angstrom-linux-gnueabi-objcopy
arm-angstrom-linux-gnueabi-objdump
arm-angstrom-linux-gnueabi-ranlib
arm-angstrom-linux-gnueabi-readelf
arm-angstrom-linux-gnueabi-run
arm-angstrom-linux-gnueabi-size
arm-angstrom-linux-gnueabi-strings
arm-angstrom-linux-gnueabi-strip

Бибилиотеки

Кросс-компилированные библиотеки и заголовочные файлы находятся в каталоге /usr/local/angstrom/arm/arm-angstrom-linux-gnueabi, в подкаталогах include и lib

Окружение

Для экспорта переменных создадим такой скрипт и назовем его build_source:

BITBAKE_PATH=~/my-distr/bitbake/bin
TOOLCHAIN=/usr/local/angstrom/arm/bin/
export PRE_BUILT=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi

export PATH=$BITBAKE_PATH:$TOOLCHAIN:$PATH
export OEDIR=$PWD

Как Вы, наверное, помните, такие скрипты надо запускать строкой:

$ . /путь-к-скрипту/build_source

или

$ source /путь-к-скрипту/build_source

либо вписать содержимое этого скрипта в .bashrc

Настройки OpenEmbedded

Мы определили, где у нас лежат файлы cross-toolchain-а и бибилиотек, теперь надо объяснить всё это OpenEmbedded-у.

Итак, открываем файл ~/my-distr/build/conf/local.conf и находим там такие строки:

# Uncomment this if you want to use a prebuilt toolchain. You will need to
# provide packages for toolchain and additional libraries yourself. You also
# have to set PATH in your environment to make sure BitBake finds additional binaries.
ASSUME_PROVIDED += "virtual/${TARGET_PREFIX}gcc virtual/libc"

Изначально эта строка закомментирована, надо это исправить. Затем, в конец файла надо добавить следующие строки:

export CC  = "${CCACHE}arm-angstrom-linux-gnueabi-gcc ${HOST_CC_ARCH}"
export CXX = "${CCACHE}arm-angstrom-linux-gnueabi-g++ ${HOST_CC_ARCH}"
export CPP = "arm-angstrom-linux-gnueabi-gcc -E"
export LD = "arm-angstrom-linux-gnueabi-ld"
export AR  = "arm-angstrom-linux-gnueabi-ar"
export AS  = "arm-angstrom-linux-gnueabi-as"
export RANLIB  = "arm-angstrom-linux-gnueabi-ranlib"
export STRIP  = "arm-angstrom-linux-gnueabi-strip"
export PRE_BUILT=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi

Если у Вас установлен какой-то другой toolchain, естественно, нужно будет указать его префиксы в названиях.
Следующие строки переопределяют соответствующие переменные из bitbake.conf, так же добавим их в конец нашего local.conf

#
# point OE to the lib and include directory
#
TARGET_CPPFLAGS_append = " -isystem${PRE_BUILT}/include "
TARGET_LDFLAGS_prepend = " -L${PRE_BUILT}/lib -Wl,-rpath-link,${PRE_BUILT}/lib "

Если Вы используете другие библиотеки, например Qt, то их надо указать здесь же, а так же добавить их в переменную ASSUME_PROVIDED описанную выше.

Собираем тестовый дистрибутив

~/my-distr$ bitbake micro-image

если в результате мы увидим ошибки, например такие:

| /usr/local/angstrom/arm/lib/gcc/arm-angstrom-linux-gnueabi/4.5.3/../../../../arm-angstrom-linux-gnueabi/bin/ld: cannot find -lusb-1.0
| collect2: ld returned 1 exit status
| make[2]: *** [libusb.la] Error 1
| make[2]: Leaving directory `/mnt/windows/Dimon/oetmp/work/armv5te-angstrom-linux-gnueabi/libusb-compat-1_0.1.3-r0/libusb-compat-0.1.3/libusb'
| make[1]: *** [all-recursive] Error 1
| make[1]: Leaving directory `/mnt/windows/Dimon/oetmp/work/armv5te-angstrom-linux-gnueabi/libusb-compat-1_0.1.3-r0/libusb-compat-0.1.3'
| make: *** [all] Error 2
| FATAL: oe_runmake failed
| ERROR: Function do_compile failed
NOTE: package libusb-compat-1_0.1.3-r0: task do_compile: Failed
ERROR: TaskFailed event exception, aborting
ERROR: Build of /home/d400/my-distr/openembedded/recipes/libusb/libusb-compat_0.1.3.bb do_compile failed
ERROR: Task 786 (/home/d400/my-distr/openembedded/recipes/libusb/libusb-compat_0.1.3.bb, do_compile) failed with 256

значит отсутствуют какие-либо нужные библиотеки в нашем toolchain-е. В данном примере отсутствует библиотека libusb. Её нужно добавить в host часть SDK и пересобрать его, только перед этим нужно убрать все изменения что мы делали для работы с предустановленным toolchain-ом, иначе новый toolchain будет собираться с использованием старого. Оказывается, создание собственного SDK не такое уж и простое дело.

Добавляем библиотеку в файл '~my-distr/openembedded/recipes/tasks/task-my-toolchain-host.bb'

RDEPENDS_${PN} += "libusb"

Пересобираем и переустанавливаем toolchain как было описано ранее. Теперь можно снова собрать rootfs image.

~/my-distr$ bitbake micro-image

После успешного окончания сборки идем в каталог 'tmp/deploy/eglibc/images/ronetix-pm9263' - там находятся файлы для прошивки

Angstrom-micro-image-eglibc-ipk-v20110705-ronetix-pm9263.rootfs.jffs2
Angstrom-micro-image-eglibc-ipk-v20110705-ronetix-pm9263.rootfs.tar.gz

Файл с расширением jffs2 - это и есть прошивка, которую надо поместить на NAND Flash нашего устройства. Tar-архив - это та же прошивка, только ее можно легко просмотреть на ПК, например для контроля, что нужные файлы попали в прошивку. Это полезно при разработке собственных рецептов.

Заключение

В данной статье мы рассмотрели вопросы создания SDK в среде OpenEmbedded, а так же использование собственноручно созданного SDK в качестве предустановленного toolchain-а при сборке rootfs.

Во время поиска информации по использованию предустановленного toolchain-а, я наткнулся на следующие настройки для работы с CodeSourcery Toolchain

# enable following line to use CodeSourcery Lite
TOOLCHAIN_VENDOR := "-none"
TOOLCHAIN_TYPE := "external"
TOOLCHAIN_BRAND := "csl"

Эти строки нужно добавить в ~/my-distr/build/conf/local.conf. Я не проверял что получится в результате, так что буду рад, если кто-то попробует CodeSourcery и отпишется в комментариях.

Комментарии

Отправить комментарий

Содержание этого поля является приватным и не предназначено к показу.
  • Syntax highlight code surrounded by the {syntaxhighlighter SPEC}...{/syntaxhighlighter} tags, where SPEC is a Syntaxhighlighter options string or "class="OPTIONS" title="the title".
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Доступны HTML теги: <a> <p> <span> <s> <strike> <div> <h1> <h2> <h3> <h4> <h5> <h6> <img> <map> <area> <hr> <br> <br /> <ul> <ol> <li> <dl> <dt> <dd> <table> <caption> <tbody> <tr> <td> <em> <b> <u> <i> <strong> <del> <ins> <sub> <sup> <quote> <blockquote> <pre> <address> <code> <cite> <embed> <object> <param> <strike>
  • Использовать как разделитель страниц.

Подробнее о форматировании