Сборка из исходников: make, ./configure
Что на самом деле происходит, когда README говорит «./configure && make && make install», и как не превратить /usr/local в свалку.
Сборка из исходников — превращение исходного кода программы в исполняемые файлы прямо на вашей машине компилятором, в отличие от установки готового бинарного пакета через apt/dnf.
В 95% случаев программу ставят пакетным менеджером — это быстро и безопасно. Но иногда выбора нет: нужна версия новее, чем в репозитории; нужны опции компиляции, которых нет в готовом пакете; программы просто нет в репозитории; или вы патчите исходники сами. Тогда в дело идёт классическая троица configure → make → make install. Понимать её обязан любой, кто работает с серверами: рано или поздно вы соберёте nginx с нужным модулем, свежий htop или чью-то утилиту с GitHub.
Инструменты: gcc и make в двух словах
gcc (или cc, clang) — компилятор: переводит .c-файлы в машинный код и линкует их в исполняемый файл. Простейший пример:
cat > hello.c <<'EOF'
#include <stdio.h>
int main(void) { printf("Привет из C\n"); return 0; }
EOF
gcc hello.c -o hello # скомпилировать в файл hello
./hello
Вывод:
Привет из C
Когда файлов сотни, вручную звать gcc невозможно — этим управляет make. Утилита make читает Makefile (список целей и правил), смотрит на даты файлов и пересобирает только то, что изменилось. Цель — это имя задачи; типичные цели — сборка (по умолчанию), install, clean. Минимальный Makefile:
hello: hello.c
gcc hello.c -o hello
clean:
rm -f hello
(Отступ в Makefile обязан быть символом табуляции, не пробелами.) Теперь make соберёт hello, а make clean уберёт результат.
Зачем нужен ./configure
Реальные проекты должны собираться на разных системах с разным набором библиотек. Скрипт ./configure (его генерирует Autotools) проверяет окружение: есть ли компилятор, какие библиотеки и заголовки установлены, поддерживает ли система нужные функции. По итогам он создаёт Makefile, заточенный под вашу машину. Если чего-то не хватает — configure сразу падает с понятной ошибкой, и это лучше, чем загадочный сбой в середине компиляции.
Канонический цикл сборки
# 1. скачать и распаковать исходники
tar xzf htop-3.3.0.tar.gz
cd htop-3.3.0
# 2. настроить под систему (без аргументов — параметры по умолчанию)
./configure
# 3. собрать (распараллелить по числу ядер процессора)
make -j"$(nproc)"
# 4. установить (нужны права на целевой каталог)
sudo make install
Что делает каждый шаг: configure проверяет зависимости и пишет Makefile; make компилирует; make install копирует готовые файлы в систему (по умолчанию в /usr/local). Флаг -j у make запускает сборку в несколько потоков — $(nproc) подставит число ядер и заметно ускорит компиляцию крупных проектов.
-dev зависимости: почему configure падает
Самая частая стена новичка — configure ругается: «library X not found» или «header Y.h missing». Причина в том, что для использования библиотеки хватает рантайм-пакета (например, libssl3), а для сборки против неё нужны ещё заголовочные файлы (.h) — они лежат в отдельном пакете с суффиксом -dev (Debian/Ubuntu) или -devel (Fedora/RHEL).
# Debian/Ubuntu: базовый набор для сборки + примеры -dev пакетов
sudo apt install build-essential
sudo apt install libssl-dev zlib1g-dev libncursesw5-dev
# Fedora/RHEL: аналог build-essential — группа, плюс -devel пакеты
sudo dnf groupinstall "Development Tools"
sudo dnf install openssl-devel zlib-devel ncurses-devel
Метапакет build-essential тянет gcc, make, libc-заголовки и прочее — без него собирать нечем. Имя нужного -dev пакета обычно угадывается по сообщению об ошибке: «zlib.h not found» → zlib1g-dev.
prefix: куда устанавливать
По умолчанию make install раскидывает файлы по /usr/local (/usr/local/bin, /usr/local/lib и т.д.). Аргумент --prefix у configure меняет корень установки. Это спасает в двух случаях: установка без root (в домашний каталог) и аккуратная изоляция программы в отдельной папке:
# поставить только себе, без sudo
./configure --prefix="$HOME/.local"
make -j"$(nproc)" && make install
# бинарь окажется в ~/.local/bin — он должен быть в PATH
# изолировать конкретную версию в своём каталоге
./configure --prefix=/opt/htop-3.3.0
make && sudo make install
Связка с прошлым уроком: чтобы система нашла программу из нестандартного --prefix, её bin должен быть в PATH (для ~/.local/bin часто уже так).
Проблема удаления и checkinstall
Главный недостаток make install: он просто копирует файлы, не записывая их в базу пакетного менеджера. Поэтому apt/dnf о такой программе ничего не знают, обновлять и удалять её нечем, а файлы расползаются по системе. Частичные решения:
- У многих проектов есть цель
make uninstall— но только если её предусмотрел автор и вы сохранили дерево сборки. checkinstallвместоmake installотслеживает, какие файлы установились, и собирает из них настоящий.deb/.rpm. Тогда программа попадает в базу пакетов и удаляется штатно.
sudo apt install checkinstall
# вместо `sudo make install`:
sudo checkinstall # создаст и установит .deb
# удалить потом — как обычный пакет:
sudo apt remove htop
Как это работает под капотом
«Скомпилировать» — это на самом деле конвейер из четырёх стадий, который gcc прячет за одной командой: препроцессор раскрывает #include и макросы; компилятор переводит C в ассемблер; ассемблер — в объектные файлы .o (машинный код, но ещё без связей между файлами); линкер (ld) сшивает все .o и подключает библиотеки в единый исполняемый файл. Промежуточные стадии можно увидеть:
gcc -c hello.c -o hello.o # только компиляция, без линковки -> объектный файл
gcc hello.o -o hello # отдельный шаг линковки
file hello.o hello # типы файлов: object vs executable
Заголовочные .h нужны именно препроцессору и компилятору — отсюда обязательность -dev пакетов. А make экономит время, сравнивая даты .c и .o: если исходник не менялся, его .o не пересобирается — поэтому повторный make в большом проекте отрабатывает мгновенно.
Частые ошибки
- Пропустили
build-essential/ «Development Tools» — собирать нечем,configureне находит компилятор. - Видят «header.h not found» и не понимают, что нужен
-dev/-develпакет соответствующей библиотеки, а не сама библиотека. - Делают
sudo make installна каждый чих в системный/usr/local, а потом не могут это удалить — используйте--prefixв отдельный каталог илиcheckinstall. - В
Makefileотступ сделан пробелами вместо табуляции —makeпадает с «missing separator». - Запускают чистый
makeна 8-ядерной машине без-j— сборка тянется в один поток в разы дольше.
Итоги
- Сборка из исходников нужна, когда пакета нет, версия устарела или требуются особые опции компиляции.
- Цикл
./configure && make && make install: проверка окружения → компиляция → установка файлов в систему. build-essential(или «Development Tools») даёт компилятор и make;-dev/-develпакеты дают заголовки для сборки против библиотек.--prefixзадаёт корень установки — для установки без root или изоляции версии; не забудьте проPATH.make installне регистрирует файлы в пакетном менеджере;checkinstallилиmake uninstallрешают проблему удаления.