Все об Arch Linux

Arch Linux будет тем, что вы из него сделаете!

Тонкости divide and conquer при сборке: пошаговая отладка

Divide and conquer при отладке сборки работает так: не чини PKGBUILD целиком, а сначала локализуй стадию, на которой падает makepkg (fetch, prepare, build, check, package), потом изолируй её флагами и запусти вручную, чтобы увидеть первую ошибку. Только после этого правь PKGBUILD и проверяй результат итерациями. Так одна ошибка превращается в понятную задачу, а не в бесконечный перебор догадок.

Почему не стоит чинить сборку целиком

Когда makepkg падает, вывод занимает сотни строк. Соблазн прочитать всё и сразу понять причину. На практике так не работает: глаза скользят по предупреждениям, а настоящая ошибка прячется где-то в середине. Ты начинаешь менять флаги, патчи и зависимости наугад, и каждая попытка занимает минуты, а то и десятки минут.

Методика divide and conquer решает эту проблему. Сборка пакета в Arch Linux проходит через пять стадий, и каждая отвечает за свою часть:

  • fetch: скачивание исходников и проверка контрольных сумм;
  • prepare: распаковка, применение патчей, подготовка исходников;
  • build: компиляция (configure, make);
  • check: прогон тестов, если они есть;
  • package: упаковка файлов в архив.

Ошибка на любой стадии останавливает makepkg. Задача не в том, чтобы починить всё сразу, а в том, чтобы определить, какая стадия падает, и работать только с ней. Остальные стадии при этом не трогаешь.

Как понять, на какой стадии падает сборка

makepkg сам подсказывает. Перед каждой стадией он печатает строку вида ==> Starting build()... или ==> Starting package().... Последняя такая строка перед ошибкой и есть твоя стадия.

Смотри на конец вывода. Если последняя строка перед падением ==> Starting prepare()..., значит, проблема в подготовке исходников. Если ==> Starting build()..., значит, проблема в компиляции. Дальше работаешь только с этой функцией PKGBUILD.

Ещё один признак: код возврата. makepkg завершается с ненулевым кодом, и в конце вывода обычно есть строка ==> ERROR: A failure occurred in build(). В скобках указана функция, которая упала. Это самый быстрый способ локализации.

Запомни соответствие: fetch падает при скачивании, prepare при распаковке и патчах, build при компиляции, check при тестах, package при упаковке. Если makepkg упал до первой строки ==> Starting..., значит, проблема в самом PKGBUILD: синтаксис, переменные, отсутствующие файлы.

Дополнительно включи журнал сборки: makepkg --log пишет полный вывод в файл makepkg.log в каталоге пакета. По нему удобно искать ошибку grep’ом, не перелистывая терминал.

Если падает fetch, причина обычно в контрольных суммах или недоступном источнике. Разбор такого случая есть в статье «Сборка AUR падает: submodules и checksum».

Как изолировать стадию флагами makepkg

Когда стадия найдена, не запускай сборку целиком каждый раз. makepkg умеет останавливаться и пропускать стадии.

Флаг -o (от англ. “no extract”) запускает только подготовку исходников:

makepkg -o -p PKGBUILD

Он выполнит fetch и prepare, но не тронет компиляцию. Удобно, когда падает именно prepare: ты правишь патчи и проверяешь их без пересборки.

Флаг -e (от англ. “no extract”) пропускает повторное извлечение исходников:

makepkg -e

Если исходники уже распакованы, makepkg не будет скачивать и распаковывать их заново. Это экономит время, когда ты правишь только build или package. Комбинация makepkg -e -o изолирует подготовку, а обычный запуск с -e доходит до конца без повторного fetch.

Важно: -e работает только если каталог src/ уже существует и заполнен. После makepkg -C (очистка) или удаления src/ флаг не поможет.

Ещё пара флагов пригодится в цикле отладки. makepkg -f пересобирает пакет, даже если готовый архив уже лежит в каталоге. makepkg --nocheck пропускает стадию check, когда тесты не нужны или падают по вине окружения.

Как запустить стадию вручную и увидеть первую ошибку

Флаги изолируют стадии, но иногда удобнее запустить команды руками. makepkg распаковывает исходники в каталог src/, и ты можешь зайти туда и повторить шаги вручную.

cd src/<имя-исходников>
./configure
make -j1

Запуск вручную даёт два преимущества. Первое: ты видишь вывод без шума makepkg, только команда и её ошибки. Второе: make -j1 собирает в один поток, и сообщения не перемешиваются с выводом параллельных задач. При -j$(nproc) ошибки от разных потоков переплетаются, и первую найти сложно.

Смотри на первую ошибку, а не на последнюю строку. Компилятор часто выдаёт каскад ошибок: одна неверная переменная порождает десятки сообщений дальше. Первая ошибка указывает на корень, остальные лишь следствия. Исправь первую, и каскад исчезнет.

Если configure падает, читай его вывод внимательно: он проверяет зависимости и библиотеки, и причина обычно в отсутствующем пакете или неверном флаге. Подробнее про сборку из исходников читай в статье «Сборка из исходников: configure и make».

После ручного запуска вернись в каталог пакета: makepkg ожидает, что сборка идёт из каталога с PKGBUILD. Если запустить makepkg из src/, он не найдёт PKGBUILD и упадёт с ошибкой.

Как отлаживать PKGBUILD с помощью echo

Иногда ошибка не в компиляции, а в логике самого PKGBUILD: неверный путь, не та переменная, патч не применился. Тут помогает старый добрый echo.

Вставь отладочные выводы в функции PKGBUILD:

prepare() {
  echo "=== prepare: srcdir=$srcdir ==="
  echo "=== файлы в src: $(ls $srcdir) ==="
  patch -p1 -i "$srcdir/../fix.patch"
}

После запуска makepkg ты увидишь эти строки в выводе. Так проверяешь, что переменные заполнены, файлы на месте, патч применился. Это подготовительные хуки в действии: ты встраиваешь проверки в нужную точку сборки.

Убирай echo после отладки. Отладочные строки в финальном PKGBUILD только засоряют вывод и мешают другим.

Как использовать pre/post хуки при сборке

Функции PKGBUILD и есть хуки сборки. makepkg вызывает их по порядку: prepare, build, check, package. Каждая функция работает как точка входа, в которую ты встраиваешь свои проверки до и после основной работы.

Если нужно выполнить код до или после стадии, добавь вспомогательные функции и вызывай их из основной:

_pre_build() {
  echo "=== старт build: $(date) ==="
  ./configure --prefix=/usr
}

_post_build() {
  echo "=== конец build ==="
  ls -la "$srcdir/build"
}

build() {
  _pre_build
  make
  _post_build
}

Так ты получаешь pre и post хуки для любой стадии, не трогая логику самой сборки. Отладочные выводы показывают, что произошло до и после, и где именно всё сломалось.

Отдельно стоят pacman-хуки. Они выполняются не при сборке, а при установке готового пакета: pacman -U запускает хуки из /usr/share/libalpm/hooks/, например обновление базы desktop-файлов или иконок. Если после установки пакета что-то не работает, проверь вывод хуков в /var/log/pacman.log. Иногда проблема не в сборке, а в том, что пакет не зарегистрировался в системе.

Как чинить PKGBUILD итерациями

Нашёл причину, правь PKGBUILD маленькими шагами. Одна правка, один запуск, проверка результата. Не меняй три вещи одновременно: если сборка снова упадёт, ты не поймёшь, что из трёх изменений сломало.

Типичные правки:

  • патчи: добавь patch -p1 в prepare, если исходники требуют исправлений;
  • флаги: добавь CFLAGS или ./configure --with-..., если не находится библиотека;
  • зависимости: добавь depends или makedepends, если configure ругается на отсутствующий пакет.

После каждой правки запускай makepkg с флагом -e, чтобы не ждать повторного извлечения. Если правка касается prepare, используй makepkg -e -o и проверяй только подготовку.

Пример. Пакет падает в build с ошибкой про отсутствующий заголовочный файл. Первая итерация: добавь в makedepends пакет, который поставляет этот файл, и запусти makepkg -e. Если ошибка ушла, дело было в зависимости. Если нет, посмотри, откуда файл ожидается: возможно, нужен патч, который подправит путь в исходниках. Каждая итерация сужает круг поиска.

Сравнение с рабочим PKGBUILD из репозитория тоже помогает. Возьми похожий пакет из официальных репозиториев или из AUR, посмотри, как там устроены prepare и build. Часто решение лежит на поверхности: тот же патч, тот же флаг, та же зависимость. Как проверять чужой PKGBUILD перед запуском, описано в статье «Как проверить, что делает AUR-пакет».

Если каждая итерация занимает минуты из-за долгой компиляции, ускорение сборки через ccache и tmpfs описано в статье «Ускорить сборку: ccache и tmpfs».

Частые вопросы

Можно ли пропустить тесты, если makepkg падает на check?

Да. Добавь check() { :; } в PKGBUILD или запусти makepkg --nocheck. Но сначала посмотри, почему тесты падают: иногда это несовместимость с новой библиотекой, а не проблема твоего пакета.

Почему make -j1 медленнее, но полезнее при отладке?

При -j1 компиляция идёт в один поток, и ошибки не перемешиваются. При параллельной сборке сообщения от разных задач переплетаются, и первую ошибку трудно найти. Для отладки скорость не важна, важна читаемость вывода.

Что делать, если ошибка появляется только при полной сборке?

Значит, стадия зависит от предыдущих. Проверь, что prepare отработал до конца: патчи применились, файлы на месте. Запусти makepkg -e -o, посмотри вывод prepare, потом продолжай сборку.

Как сравнить свой PKGBUILD с рабочим из репозитория?

Скачай PKGBUILD похожего пакета из официального репозитория через asp или посмотри в AUR. Сравни функции prepare и build: какие патчи, какие флаги, какие зависимости. Различия часто указывают на причину падения.

Что такое pre/post хуки в контексте сборки?

В PKGBUILD это вспомогательные функции, которые ты вызываешь в начале и в конце стадии: _pre_build перед make, _post_build после. А pacman-хуки из /usr/share/libalpm/hooks/ выполняются при установке пакета через pacman -U и обновляют системные базы.

Полезные ресурсы

Заключение

Divide and conquer превращает отладку сборки в последовательность маленьких шагов: локализуй стадию по последней строке makepkg, изолируй её флагами -o и -e, запусти команды вручную в src/, найди первую ошибку и правь PKGBUILD по одной правке за раз. Отладочные echo и pre/post хуки в функциях показывают, что происходит внутри, а сравнение с рабочим PKGBUILD подсказывает решение. Так любая падающая сборка становится решаемой за несколько минут.



Не получилось? Поможем настроить

Задай вопрос в чате — отвечаем быстро, по делу и без воды.

Читайте также

Комментарии

Загрузка…

Откроется GitHub: создайте новый issue с вашим комментарием (кнопка «Submit new issue»). После отправки обновите эту страницу — комментарий появится ниже.

Telegram Max