Quench: инструмент сборки, который я написал, потому что достал Make

Сразу проясню: я не маркетолог и не продаю здесь ничего. Проект под GPLv3, деньги от вас не требуются. Есть опциональный донат для тех, кто захочет поддержать, но это именно опция, а не завуалированная плата за доступ к нормальной функциональности, как это часто бывает у "открытых" проектов.

Пару слов о том, откуда это вообще взялось. Последние пять-шесть месяцев проект вообще не светился публично. Мы с напарником писали операционную систему на ассемблере — да, буквально с нуля, руками, без готовых фреймворков. Если у кого-то от этой фразы дёрнулся глаз — не переживайте, речь не про саму ОС, а про инструмент, который родился как побочный продукт этой затеи.

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

Кто-то в комментариях уже пишет: "а почему не Ninja, она же быстрее". Пробовали. На практике, на наших реальных задачах, быстрее не оказалась — и это не ощущение, а результат, который я гонял через бенчмарки не один раз, сравнивая с обоими инструментами. В итоге мы написали своё. И оно обогнало Ninja. А потом обзавелось именем.

Кстати про имя. Проект переименован: ForgeZero теперь называется Quench, а организация на GitHub переехала с forgezero-cli на qecko-labs. Хочу закрыть вопрос сразу и честно: это не форк, не передача проекта другой команде и не смена курса. Команда та же, кодовая база та же, планы те же, просто новая вывеска на входе. Старые ссылки пока редиректят, но если у вас где-то зашиты старые адреса в конфигах CI или в ремоутах — самое время это поправить, пока редирект однажды тихо не перестанет работать и не испортит вам утро.

Quench 2.0, он же ядро версии 6.0.0 — это не просто смена таблички с новым номером версии. Поменялась сама философия: ноль магии, максимум производительности. Инструмент не прячет от вас компилятор и линковщик — он исходит из того, что вы понимаете, что делает линковщик, и не боитесь ему об этом сказать напрямую. Если хочется чёрного ящика — вокруг полно систем сборки, которые с радостью станут этим ящиком. Quench — не про это.

В основе этого релиза три вещи. Полностью переписанный планировщик задач — lock-free, без лишних аллокаций памяти, построенный на графе зависимостей, работающий в горячем пути буквально без единой лишней аллокации на операцию. Встроенный препроцессор FZP — тот же функционал, за которым раньше приходилось тянуть внешние инструменты для шаблонов заголовочных файлов, теперь просто часть тулы, с корректным разрешением инклюдов и обнаружением циклов. И менеджер пакетов fzpkg, который на самом деле проверяет то, что устанавливает, а не просто доверяет всему, что лежит в папке зависимостей — потому что "доверять папке" никогда не было моделью безопасности, только имитацией.

Дальше — цифры, потому что слова стоят дешево. Собрал полноценный Lua — рабочий интерпретатор, а не hello world, — и сборка заняла меньше 200 миллисекунд, после чего интерпретатор сразу запустился и заработал. Дальше взял Redis — реальная база данных, больше 400 тысяч строк кода, куча файлов, реальная боль для любой системы сборки. Полная сборка redis-server заняла порядка трёх секунд суммарного времени, при этом инструмент аккуратно вывел предупреждение о зависимости, которая была отключена в конфиге, и корректно отказался подхватывать инклюд за пределами корня проекта без явного разрешения — то есть повёл себя именно так, как должен вести себя инструмент, которому доверяют реальную сборку, а не так, как ведёт себя красивый слайд с презентации.

На синтетических бенчмарках против make с четырьмя параллельными потоками разница растёт вместе с размером проекта: на маленьких проектах Quench быстрее в два с половиной раза, а уже на четырёхстах модулях разрыв доходит почти до пяти раз. На стресс-тесте из пяти тысяч файлов на C, где Quench сравнивался напрямую с Ninja на шестнадцати потоках, разница выходит за сорок семь раз в пользу Quench при почти стопроцентной загрузке всех ядер. На отдельном синтетическом бенчмарке планировщика на двух тысячах модулей разница с Ninja доходила до шестнадцати с половиной раз. Это разные тесты и разные сравнения, но вывод один: переписанный планировщик — не украшение, а реально работающая часть системы.

Из остального, что реально стоит знать, а не просто строчка в списке изменений. Тот самый DAG-планировщик, который был главной темой релиза, уже успел уступить дефолтное место в билдере и линковщике более простому пулу потоков с воркстилингом — да, буквально в том же цикле разработки. Признаю, звучит немного неловко объявлять замену главной фиче через несколько дней после её анонса, но цифры на типичных по размеру проектах говорят за более простой подход, а DAG остаётся штатным решением там, где граф зависимостей глубокий и неровный — так что старый планировщик никуда не пропал, просто больше не тащит на себе повседневную работу.

Появилась нормальная система диагностики ошибок — с указанием файла, строки, конкретного параметра, который сломался, и предложенным исправлением, если оно есть. Если вы хоть раз молча смотрели на голую ошибку Go из загрузчика конфига, пытаясь понять, какое из сорока полей в TOML сломало сборку — это сделано специально для того, чтобы вы больше так не смотрели.

Добавилась конфигурация с учётом железа — путь к компилятору, целевой процессор, набор инструкций, число воркеров, привязка к ядрам. Кросс-компиляция или пиннинг сборки на конкретные ядра больше не требует писать отдельный скрипт конфигурации только чтобы почувствовать контроль над процессом.

И отдельно — безопасность, сделанная без пафоса, но по делу: проверка путей от directory traversal в препроцессоре, проверка переполнений и границ значений в ассемблере и при генерации символов ELF32, обязательная проверка подписей пакетов для тех, кто включит эту опцию в fzpkg. Ничего из этого не годится для красивой гифки в презентации. Но именно из таких вещей складывается разница между инструментом сборки и инструментом сборки, которому реально можно доверять в продакшен-пайплайне. Основным форматом конфигурации теперь официально стал .qh.toml — YAML пока грузится, но при загрузке молча выдаёт предупреждение о том, что его дни сочтены.

Можете разбирать код до последнего байта — он весь открыт, никакой закрытой "core" части не существует. Заводите issues, я их читаю и реально готов помогать. Пользуйтесь, пишите мне, как оно себя ведёт, и я отвечу на любую жалобу, любую критику, любой вопрос — без шаблонных ответов и без "закрыто как не будем делать". Называйте меня как хотите при этом, мне не принципиально. Принципиально — чтобы аргумент был про код, а не про личное.

И да, я уже знаю, какой комментарий сейчас пишется: "зачем ещё один инструмент сборки, когда уже есть готовые, это же изобретение велосипеда". Можно назвать это велосипедом, если хочется. Я бы назвал это как минимум мотоциклом, а по некоторым дням — уже почти ракетой. Спорьте с бенчмарками, спорьте с архитектурой, спорьте с конкретной строчкой кода, которая кажется вам неправильной — это разговор, который я охотно поддержу. А "кто-то уже придумал колесо" — это не аргумент, это просто способ ни о чём не думать, и он никогда ещё не сделал существующий инструмент быстрее.

Репозиторий: github.com/qecko-labs/Quench

Документация: qecko-labs.github.io/quench-docs

Issues: github.com/qecko-labs/Quench/issues — прикладывайте свой .qh.toml и реальный вывод ошибки. "Не собирается" без лога не продвинет вопрос никуда — ни вас, ни меня.

Важное предупреждение: это пре-релиз, а не "можно нести в прод с закрытыми глазами" релиз. В этом цикле изменения затронули почти каждую подсистему, и наиболее вероятные проблемные места сейчас — загрузка конфига, автосборка зависимостей и проверка подписей в fzpkg. Гоняйте на том, что не страшно пересобрать с чистого чекаута, а не на единственной продовой сборке без бэкапов.

Оригинальный пост(на английском языке):

Автор: Alex Voste

11