Divide and conquer при отладке сборки работает так: не чини PKGBUILD целиком, а сначала локализуй стадию, на которой падает makepkg (fetch, prepare, build, check, package), потом изолируй её флагами и запусти вручную, чтобы увидеть первую ошибку. Только после этого правь PKGBUILD и проверяй результат итерациями. Так одна ошибка превращается в понятную задачу, а не в бесконечный перебор догадок.
Когда makepkg падает, вывод занимает сотни строк. Соблазн прочитать всё и сразу понять причину. На практике так не работает: глаза скользят по предупреждениям, а настоящая ошибка прячется где-то в середине. Ты начинаешь менять флаги, патчи и зависимости наугад, и каждая попытка занимает минуты, а то и десятки минут.
Методика divide and conquer решает эту проблему. Сборка пакета в Arch Linux проходит через пять стадий, и каждая отвечает за свою часть:
Ошибка на любой стадии останавливает 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 умеет останавливаться и пропускать стадии.
Флаг -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:
prepare() {
echo "=== prepare: srcdir=$srcdir ==="
echo "=== файлы в src: $(ls $srcdir) ==="
patch -p1 -i "$srcdir/../fix.patch"
}
После запуска makepkg ты увидишь эти строки в выводе. Так проверяешь, что переменные заполнены, файлы на месте, патч применился. Это подготовительные хуки в действии: ты встраиваешь проверки в нужную точку сборки.
Убирай echo после отладки. Отладочные строки в финальном PKGBUILD только засоряют вывод и мешают другим.
Функции 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 маленькими шагами. Одна правка, один запуск, проверка результата. Не меняй три вещи одновременно: если сборка снова упадёт, ты не поймёшь, что из трёх изменений сломало.
Типичные правки:
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».
Да. Добавь check() { :; } в PKGBUILD или запусти makepkg --nocheck. Но сначала посмотри, почему тесты падают: иногда это несовместимость с новой библиотекой, а не проблема твоего пакета.
При -j1 компиляция идёт в один поток, и ошибки не перемешиваются. При параллельной сборке сообщения от разных задач переплетаются, и первую ошибку трудно найти. Для отладки скорость не важна, важна читаемость вывода.
Значит, стадия зависит от предыдущих. Проверь, что prepare отработал до конца: патчи применились, файлы на месте. Запусти makepkg -e -o, посмотри вывод prepare, потом продолжай сборку.
Скачай PKGBUILD похожего пакета из официального репозитория через asp или посмотри в AUR. Сравни функции prepare и build: какие патчи, какие флаги, какие зависимости. Различия часто указывают на причину падения.
В 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 подсказывает решение. Так любая падающая сборка становится решаемой за несколько минут.
Задай вопрос в чате — отвечаем быстро, по делу и без воды.
Комментарии