Когда сборка кода была болью
Make это одна из старейших утилит в мире Unix.
Первая версия make была написана Стюартом Фельдманом (Stuart Feldman) во времена его работы в Bell Labs. Как это нередко было в те времена, мотивацией к созданию make
было отсутствие инструментов для автоматизации компиляции кода. До этого приходилось каждый раз перекомпилировать проект вручную.
По данным Wikipedia, Фельдман завершил первую версию make
в апреле 1976 года во время работы в Bell Labs, и за неё позже (в 2003) получил ACM Software System Award
Один гневный программист и рождение make
Чтобы понять всю боль представим что мы попали в мир до ChatGPT примерно в 70е
Тогда рабочий день разработчика выглядел примерно так. Вот, например, небольшой проект:
project/
├── main.c
├── util.c
├── util.h
└── README
Если вы меняли util.c
, нужно было самому помнить, какие файлы пересобирать:
cc -c main.c # компиляция main.c в main.o
cc -c util.c # компиляция util.c в util.o
cc main.o util.o -o myprog # линковка в исполняемый файл
А если файлов не 2-3, а сотни? Тогда это становилось реальной проблемой.
Как вспоминал Стюарт Фельдман, идея make
родилась, когда его коллега Стив Джонсон (Steve Johnson) ворвался в офис, яростно проклиная судьбу, которая вынудила его потратить утро на отладку программы, которая на самом деле уже работала корректно.
Фельдман предложил описывать зависимости между файлами и команды для их сборки в отдельном файле, а выполнение этих команд поручить утилите. Утилита должна была сравнивать время модификации файлов и пересобирать только устаревшие targets.
Пример Makefile для приведённого выше проекта:
myprog: main.o util.o
cc main.o util.o -o myprog
main.o: main.c util.h
cc -c main.c
util.o: util.c util.h
cc -c util.c
При изменении util.c
будет пересобран только util.o
, после чего выполнится линковка myprog
.
Fun fact: Требование, чтобы все команды в Makefile начинались с символа табуляции это легаси, тянущееся ещё с первой версии
make
1976 года. В оригинальной реализации Стюарт Фельдман выбрал табуляцию просто потому что это простой способ для парсера отличать команды от строк с зависимостями. Этот технический хак оказался настолько удобным, что вошёл в POSIX-стандарт и пережил десятилетия. Если заменить табуляцию пробелами,make
до сих пор выдаст ошибку.
Как GNU закрепило make в Linux
Фельдман изначально позиционировал make
как инструмент для автоматизации рутинных операций сборки и сопровождения кода в проектах среднего размера. Его ключевая ценность это минимизация ручных действий разработчика: достаточно один раз описать зависимости и команды, после чего весь цикл работы сводится к схеме
think — edit — make — test.
Первая реализация make
вошла в состав PWB/UNIX 1.0, а затем была перенесена в System V и BSD, что сделало утилиту стандартной частью Unix-систем.
Следующим шагом в развитии make
стала его реализация в рамках проекта GNU. В 1988 году появилась утилита GNU Make, разработанная Ричардом Столлманом (Richard Stallman) и Роландом Макгрэйтом(Roland McGrath). Первый зафиксированный коммит в репозитории GNU Make датируется 23 апреля 1988 года. Эта реализация расширила синтаксис оригинальной версии, добавила встроенные функции, условные конструкции, макросы и обеспечила более широкую совместимость. GNU Make быстро стала стандартной реализацией в большинстве дистрибутивов Linux и используется по умолчанию до сих пор. Параллельно развивались и другие реализации: BSD Make (входит в BSD-системы), nmake (Microsoft Windows), Remake (форк GNU Make с отладчиком и профилированием), Kati (реализация от Google, используемая в Android-сборках).
Почему make всё ещё жив
Идея декларативного описания зависимостей и автоматической сборки, заложенная в make
, стала основой для появления современных систем сборки от CMake и Ninja до Gradle и Ant
Сегодня make
остаётся одним из ключевых инструментов в экосистеме разработки. Его история началась с конфликта в офисе Bell Labs, когда утро, потраченное на отладку уже исправленного кода, подтолкнуло Стюарта Фельдмана к созданию утилиты. Несмотря на появление множества надстроек и альтернатив, make
по-прежнему используется в миллионах проектов и служит основой для современных систем сборки. Простота модели зависимостей, проверенная временем, и гибкость синтаксиса позволяют ему эффективно решать задачи автоматизации даже спустя десятилетия после своего появления.