[C++, Компиляторы, Разработка на Raspberry Pi] Кросс-компилятор для Raspberry Pi4

Автор Сообщение
news_bot ®

Стаж: 6 лет 9 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
17-Фев-2021 12:35


Хочу рассказать, как я собрал себе кросс-компилятор для Raspberry Pi4 с помощью crosstool-ng. Возможно кому-то тема покажется слишком примитивной и скучной. Я и сам поначалу думал, что быстро смогу собрать кросс-компилятор, но пришлось повозиться и изучать вопрос, некоторые нюансы были для меня неожиданны. Дальше расскажу что и как я делал.
Пожалуй первый вопрос, который нужно себе задать: «Для чего нужен кросс-компилятор?» В самом деле, Raspberry Pi4 довольно быстр и компилировать программы можно прямо на нем. Если проект простой, то вполне можно так и делать. Но когда проект разрастается и усложняется, то тут уже лучше переходить на кросс-компиляцию. Тогда и другие вопросы проще решить, например, можно организовать авто сборку проекта на интеграционном сервере. При кросс-компиляции на быстром ПК можно значительно поднять скорость сборки, да и средства редактирования программ на ПК можно найти лучше.
Второй вопрос: «Может взять уже готовый кросс-компилятор? Зачем свой-то собирать?» Сказать по правде я не нашел нормального кросс-компилятора для Raspberry. Может я плохо искал? На github от распберри есть проект tools и там есть несколько кросс-компиляторов, но они же древние! Ну что там? Версия 4.9.3? Как-то не серьезно. На странице загрузки Linaro я вижу только версию 7.5, уже получше, но, во-первых, на самом Raspberry Buster OS уже версия 8.3, а во-вторых, компилятор Linaro у меня заработал только после некоторых патчей. Как-то странно…
Именно после попыток запустить компилятор Linaro я подумал, что наверное смогу сам собрать свой собственный кросс-компилятор. Некоторый опыт работы с crosstool-ng у меня уже был. Я делал кросс-компилятор для системы на кристалле Amber.
В чем сложность сборки? У инструмента crosstool-ng есть множество различных настроек, которые не всегда понятны. Сборка кросс-компилятора на моем ноутбуке занимает примерно 45 минут. Если с настройками ошибся, то полученный кросс-компилятор как-то не так работает, что-то не собирает, или собирает, но полученный бинарник не запускается на Raspberry. После проверки полученного кросс-компилятора мне приходилось опять что-то изменять в настройках и опять генерировать его сначала. Ну я сделал несколько попыток, пока не получилось так как я хотел.
Пожалуй главное, чего я не очень понимал сначала — компилятор должен соответствовать операционной системе. Это выглядит несколько странно, но это так получается. В самом деле, в ОС уже содержатся стандартные библиотеки c/c++. Они экспортируют набор функций. Код, генерируемый кросс-компилятором, должен содержать вызовы этих библиотечных функций. Поэтому версии библиотек в самом кросс-компиляторе и в ОС для которой будет генерироваться код должны совпадать.
Попробуем создать кросс-компилятор.
Порядок действий будет такой:
1) Проверить, что в нашей хост системе (я пользуюсь Ubuntu 18) установлены следующие пакеты:
gcc g++ gperf bison flex texinfo help2man make libncurses5-dev python3-dev autoconf automake libtool libtool-bin gawk wget bzip2 xz-utils unzip patch libstdc++6 rsync git
Если чего-то нет, то нужно установить через sudo apt install…
2) Скачиваем crosstool-ng версии 1.24.0 с их сайта

3) Распаковываем полученный архив
tar xjf crosstool-ng-1.24.0.tar.bz2
cd crosstool-ng-1.24.0

4) Собираем crosstool-ng
./configure
make
make install

5) Патчим crosstool-ng
Это довольно странное действие, но без него у меня не получалось хорошего результата. Без этого патча кросс-компилятор отказывался по умолчанию искать библиотеки в папке /usr/lib/arm-linux-gnueabihf относительно sysroot.
Патч нужно получить на самом распберри.
На распберри пи4 с установленной OS Buster (это важно, я делаю кросс-компилятор именно для этой ОС) нужно взять исходники binutils:
sudo apt install binutils-source
и посмотреть файл /usr/src/binutils/patches/129_multiarch_libpath.patch
Этот файл мы кладем в папку crosstool-ng-1.24.0/packages/binutils/2.31.1 на нашем хост компьютере. Это важно положить именно в эту папку, так как на самой Raspberry Pi OS Buster версия binutils 2.31.1. Проверьте это командой в консоли на распбери
ld --version
Кроме этого, нужно проверить, какая GLIB стоит в вашей OS на распбери
ldd --version
У меня в Buster стоит 2.28 и значит и сам crosstool-ng нужно будет сконфигурировать в эту версию GLIB 2.28 там по умолчанию не такая версия. Если этого не сделать, то кросс-компилятор будет генерировать код, который не будет запускаться на Raspberry в Buster OS — бинарник может ссылаться на несуществующие функции во внешних библиотеках.
6) Подготовим начальную конфигурацию crosstool-ng
В самом crosstool-ng уже есть довольно много типовых конфигураций. В том числе, там есть очень похожая на то, что нам надо конфигурация для Raspberry Pi3
Список всех возможных конфигураций можно посмотреть командой
./ct-ng list-samples
Потом выбранную концигурацию нужно «активировать» командой
./ct-ng armv8-rpi3-linux-gnueabihf
Появится новый файл конфигурации .config, который полностью определяет свойства будущего кросс-компилятора. Теперь его нужно немного поправить. Можно редактировать и вручную, но легче исправлять из меню
./ct-ng menuconfig
Выглядит самое первое меню вот так:

7) Дальше меняем странную опцию, возможно необязательную.
Практически везде где хоть что-то пишется о создании кросс-компилятора для Raspberry пишут убрать галочку с опции «Render the toolchain read-only». Эта настройка находится в меню «Paths and misc options». В документации к crosstool-ng написано, что по умолчанию итоговый компилятор будет доступен только для чтения, чтобы ненароком компилируемая программа не была установлена в sysroot самого компилятора. На мой взгляд это вполне разумное решение. Не знаю, для чего всякие авторы пишут убрать галочку отсюда…
8) Следующее. Заходим в пункт «Target options» и устанавливаем значения согласно скриншоту:

Нужно сказать, что вообще-то Raspberry Pi4 имеет процессор Cortex-A72 и это можно здесь в меню назначить. Однако, я себе оставил Cortex-A53 потому, что я буду компилировать не только для Pi4, но и для Pi3. Хотя, точную настройку можно будет задавать уже при запуске компилятора gcc с помощью параметра в командной строке -mcpu=cortex-a72
Хочу еще добавить, что я предпочитаю, чтобы кросс-компилятор имел точно такой же tuple, как и компилятор на самой плате Raspberry. То есть итоговый компилятор будет arm-linux-gueabihf и никак иначе. Мне так проще. Многие существующие пакеты имеют в своем составе готовые cmake файлы, где компилятор назначается именно arm-linux-gnueabihf. Мы же не хотим потом эти все cmake файлы исправлять вручную и писать там что-то вроде armv8-mygcc-linux-gnueabihf? Для этого я выключаю опцию «Omit vendor part of target tuple».
9) Заходим в меню «Binary utilities» и устанавливаем версию binutils 2.31.1 (Помните, что у нас еще патч именно для него?)

10) Заходим в меню «Operating system» и устанавливаем версию ядра 4.20

Вообще-то Raspberry Buster OS уже сейчас имеет ядро 5.10, но максимум, что можно поставить это только 4.20
11) Заходим в меню «C-libraries» и устанавливаем версию GLIB 2.28

12) Заходим в меню «C-compiler»

Устанавливаем желаемую версию будущего кросс-компилятора 8.3.0 и добавляем в настройки компилятора core gcc extra config опцию --enable-multiarch. Это важно, чтобы кросс-компилятор находил библиотеки в sysroot по пути /usr/lib/arm-linux-gnueabihf
Теперь выходим из всех меню, сохраняем сделанные изменения, когда спросит и приступаем к сборке.
13) Сборка выполняется простыми командами
export DEB_TARGET_MULTIARCH=arm-linux-gnueabihf
./ct-ng build
Придется подождать. У меня сборка на ноутбуке шла примерно 45 минут. После сборки ваш новый кросс-компилятор расположен в пути ~/x-tools/arm-linux-gnueabihf
Можно проверить какие пути к библиотекам по умолчанию будет использовать кросс-компилятор. Будет ли он искать в пути /usr/lib/arm-linux-gnueabihf?
Для этого запустим команду:
~/x-tools/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-ld --verbose | grep «SEARCH»
Команда должна выдать что-то такое:
SEARCH_DIR("=/usr/local/lib/arm-linux-gnueabihf"); SEARCH_DIR("=/lib/arm-linux-gnueabihf"); SEARCH_DIR("=/usr/lib/arm-linux-gnueabihf"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); SEARCH_DIR("=/home/nick/x-tools/arm-linux-gnueabihf/arm-linux-gnueabihf/lib");
Обратите внимание, что пути начинаются со знака "=". Это значит, что это пути относительно sysroot, если он будет указан при запуске gcc с опцией командной строки --sysroot=PATH_TO_YOUR_SYSROOT.
Вот пожалуй и все. Остается решить вопрос, где взять sysroot. Проще всего на Raspberry Pi установить все нужные девелоперские пакеты и потом, вытащив из устройства SD карту, переписать ее на хост ПК. Но там тоже есть некоторые нюансы.
Теперь, когда кросс-компилятор у нас есть мы можем собрать какую ни будь специфичную для распберри программу. Например, демонстрационные программы userland от самой Raspberry:
git clone github.com/raspberrypi/userland.git
cd userland
export export PATH=${HOME}/x-tools/arm-linux-gnueabihf/bin:$PATH
./buildme
Результат компиляции будет в папке build/bin.
В завершении статьи я хотел бы привести таблицу дополнительных параметров для компиляторов gcc при сборке проектов под различные версии raspberry
Raspberry Pi 1: -mcpu=arm1176jzf-s -mfloat-abi=hard -mfpu=vfp (alias for vfpv2)
Raspberry Pi 2: -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4
Raspberry Pi 3: -mcpu=cortex-a53 -mfloat-abi=hard -mfpu=neon-fp-armv8 -mneon-for-64bits
Raspberry Pi 4: -mcpu=cortex-a72 -mfloat-abi=hard -mfpu=neon-fp-armv8 -mneon-for-64bits

Надеюсь, что моя статья кому-то окажется полезной.
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_c++, #_kompiljatory (Компиляторы), #_razrabotka_na_raspberry_pi (Разработка на Raspberry Pi), #_raspberry_gcc_crosstoolng, #_c++, #_kompiljatory (
Компиляторы
)
, #_razrabotka_na_raspberry_pi (
Разработка на Raspberry Pi
)
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 22-Ноя 10:24
Часовой пояс: UTC + 5