Страницы

Поиск по вопросам

суббота, 7 декабря 2019 г.

Кросскомпиляция deb-пакетов

#ubuntu #debian #arm #orange_pi


Каким образом собрать пакет в ubuntu той же версии, но под другую архитектуру используя
кросс-компилятор arm-linux-gnueabihf-gcc?
Как модифицировать Makefile, чтобы вызывался кросс-компилятор вместо обычного?
    


Ответы

Ответ 1



Для сборки пакетов в Debian существует стек утилит (каждая из которых вызывает следующие более низкоуровневые): pdebuild pbuilder apt-get, debuild dpkg-buildpackage dpkg-architecture, fakeroot, debian/rules dh, dh_... make, strip, dpkg-deb Верхние четыре уровня позволяют указывать целевую архитектуру в аргументах запуска. Нижние уровни берут эту информацию из переменных окружения. Первые два собирают пакеты в изолированном окружении для проверки, что все зависимости сборки указаны. Они требуют много дисковой памяти и времени для подготовки окружения, ими стоит пользоваться перед выпуском вашего пакета в общее пользование. Для внутреннего использования наверно лучше подойдёт dpkg-buildpackage. Запуск из каталога исходников пакета (тот, в котором находится подкаталог debian): dpkg-buildpackage -a armhf Так же можно использовать debuild: debuild -a armhf Для успешной сборки этого может быть недостаточно. Необходимо указать правильный компилятор. Для этого можно использовать переменную окружения CC. Как я подсмотрел в модуле /usr/share/perl5/Debian/Debhelper/Dh_Lib.pm и программе dh_strip, для определения префикса утилит компиляции используется переменная окружения DEB_HOST_GNU_TYPE, если она отличается от DEB_BUILD_GNU_TYPE, в противном случае префикс не используется. Значит нам нужно поместить либо в debian/rules либо в Makefile первого уровня строку: export CC=$(DEB_HOST_GNU_TYPE)-gcc Аналогично для C++: export CXX=$(DEB_HOST_GNU_TYPE)-g++ Если в процессе сборки нужен родной компилятор для компиляции какого-нибудь препроцессора и т.п., нужно вернуть переменную в старое состояние (gcc/g++) для конкретных файлов или каталогов. Если пакет использует qmake, cmake или autoconf, всё это должно делаться автоматически, но не всегда работает. Отдельного рассмотрения стоит кросскомпиляция библиотек и зависимых пакетов. Зависимости при сборке dpkg-buildpackage и более высокоуровневые утилиты сборки проверяют зависимости указанные в строке Build-Depends: файла debian/control, что в прочем можно отключить опцией -d. Чтобы пакет удовлетворил зависимость, он либо должен быть архитектуронезависимым (Architecture: all), либо совпадающей архитектуры (что подходит для библиотек и не подходит, если в процессе сборки необходимо выполнить его бинарный файл), либо иметь свойство Multi-Arch: foreign, которое должно быть в его файле control. Возможен так же более сложный вариант, который используется для интерпретаторов с плагинами в виде динамически загружаемых библиотек как perl или python: в зависимом пакете в Build-Depends после имени пакета добавляется :any, а в удовлетворяющем зависимость пишется строка Multi-Arch: allowed. Последний способ позволяет предъявлять два варианта требований к пакету: без :any - требуется "своя" архитектура (собираемся связывать свою программу с файлом из этого пакета, например используем свой плагин) - для кросс-сборки скорее всего не подойдёт, так как такие пакеты не могут устанавливаться одновременно двух архитектур, этот вариант обычно используют в зависимостях при установке; с :any - любая (просто собираемся запускать интерпретатор). Кроме :any в зависимостях ещё возможен суффикс :native, означающий что требуется пакет архитектуры, на которой производится сборка (билдера). Этот суффикс почему-то не удовлетворяют пакеты с Multi-Arch: foreign или Architecture: all, подойдёт пакет без Multi-Arch, либо с Multi-Arch: same или Multi-Arch: allowed. Библиотеки Если ваш собираемый пакет использует библиотеку, лучший вариант если её пакет имеет свойство Multi-Arch: same. Это означает, что можно будет установить одинаковые пакеты одновременно под несколько разных архитектур. Файлы библиотек в таких пакетах находятся в разных каталогах в зависимости от архитектуры. Т.е. вместо старого пути /lib/ используется /lib/arm-linux-gnueabihf/ или /lib/i386-linux-gnu/. Имена этих подкаталогов при сборке пакетов библиотек должны браться из переменной DEB_HOST_MULTIARCH (которая может отличаться от DEB_HOST_GNU_TYPE). Остальные файлы могут совпадать, но должны в таком случае быть идентичны. Версии устанавливаемых пакетов так же должны быть одинаковы. В зависимом пакете в Build-Depends просто указывается имя библиотечного пакета. В противном случае требуемая библиотека чужой архитектуры при установке заменяет собой родную библиотеку, что приводит к удалению всех зависимых пакетов родной архитектуры. Если вы используете для сборки dpkg-buildpackage (или более высокоуровневую утилиту), переменные DEB_... определяются автоматически. Если вы вызываете fakeroot debian/rules binary напрямую, эти переменные не определены. Узнать их стандартнтые значения для вашей системы можно с помощью команд: dpkg-architecture -qDEB_HOST_MULTIARCH dpkg-architecture -qDEB_HOST_GNU_TYPE А для другой архитектуры добавив опцию -a, например -a armhf. Установка библиотек чужой архитектуры При установке появляются две проблемы: библиотека не адаптирована к многоархитектурности, или в репозиториях для разных архитектур последние версии библиотек различаются. Во втором случае apt-get выдаёт ошибку типа "битые пакеты" или как и в первом предлагает удалить из системы много нужных пакетов. В первом случае нужно переделать пакет, как описано выше, во втором может помочь понижение версии, т.е. явно указать версию пакета, которая есть для обеих архитектур, например: # apt-get install linux-libc-dev:armhf=3.19.0-68.76 linux-libc-dev:i386=3.19.0-68.76

Комментариев нет:

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