Каким образом собрать пакет в ubuntu той же версии, но под другую архитектуру используя кросс-компилятор arm-linux-gnueabihf-gcc? Как модифицировать Makefile, чтобы вызывался кросс-компилятор вместо обычного?
Ответ
Для сборки пакетов в 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
Комментариев нет:
Отправить комментарий