Next: Мультимедиа форматы, Previous: Почему современный Web для меня недоступен и мёртв?, Up: Articles
redo
это предложенная
DJB
альтернатива Make
системе сборки. Своё видение такой системы
он просто описал тремя небольшими
страницами. Никакого кода не опубликовал. Alan Grosskurth написал
работу в институте на эту тему. А десятки других людей позже написали свои реализации этой
системы сборки на самых разных языках. Очень хорошее пояснение и
введение с примерами есть в документации к
apenwarr/redo
.
Ещё одно хорошее введение.
Программ/реализаций Make
– десятки. Систем сборки
несовместимых с Make
– с полсотни минимум. Десяток систем
генерирующих Makefile-ы. Несовместимых между собой диалектов
Make
-ов тоже десятки (например GNU Make и BSD Make). Так чем
же примечательна ещё одна система? Почему нельзя использовать POSIX Make
подмножество, которое, по идее, должно поддерживаться и одинаково
работать на широком круге Make
реализаций? Чуть ли не каждый
заявляет что он лучше Make
или как минимум удобнее.
Начну с единственного, что можно причислить к недостатку: redo
из коробки не часто стоит в ОС. Впрочем, как и почти все системы сборки,
кроме какого-то одного из Make
, часто вас всё равно не
удовлетворяющего (сколько вам приходится дополнительно ставить GNU Make
в вашу систему чтобы хоть как-то собиралась масса софта)?
Преимущества:
Make
реализации переходят в
директорию при исполнении make -C dir
, а другие нет.
redo
, с возможностью распараллеливания
заданий, на чистом C, без зависимостей, с встроенной полной реализацией
SHA256, занимает менее 1k SLOC. Реализация на чистом POSIX shell
запросто умещается в 100 SLOC. Поэтому, даже если redo
не
установлен в системе, то достаточно скопировать небольшой shell скрипт
(например apenwarr/minimal/do
занимает одну треть от размера
GPLv3 лицензии) или один бинарный исполняемый файл в пару десятков
килобайт. Реализации имеются и на других shell, Python, Haskell, Go,
C++, Inferno Shell.
redo
позволяет делать абсолютно все те же самые
задачи что и Make
. В отличии от Make
, в нём нет
ни предположений о том, что вы собираете (.SUFFIXES
), ни
специфичного для языка (часто это C/C++) hard-code.
Make
нельзя
удобно записывать shell в несколько строчек. Лично у меня, на практике,
redo
описания получаются меньше по размеру чем Makefile-ы.
#include
из .[ch]), что в Makefile невозможно.
Зависимости можно задать даже после сборки цели.
Зависимости от изменённых переменных окружения или переменных
Make
, аналогично, делаются тривиально. На практике, мало кто
делает подобное для Make
из-за сложности, зачастую просто
вручную выполняя make clean
, с последующей полной пересборкой.
Более того, в redo
можно задавать зависимости уже
после сборки цели!
redo
все
цели собирает атомарно, через fsync
и переименование временного
файла. Make
ничем не помогает в этом – вы вынуждены вручную
эмулировать атомарность сборки, чего, на практике, мало кто делает из-за
сложности и неудобства. Частично скопированные/скачанные файлы или
упавшая команда не будут более считаться успешно выполненной целью.
Make
к изменению файлов, например из-за
NFS, mmap, VCS, FUSE (со всеми ними
нет гарантий об изменениях в
mtime
), небольшой гранулярностью времени mtime
,
нестабильных часов. Многие реализации используют криптографические хэши
для выяснения изменённости файлов.
redo
позволяет делать зависимости на цели в других
директориях, с полным централизованным глобальным ведением информации о
зависимостях, с state-ом и lock-ами, без каких-либо недостатков
описанных в Recursive Make Considered Harmful.
Как же пользоваться этой системой сборки? Приведу её полное описание с точки зрения пользователя. Для конкретных примеров советую ссылки в начале этой статьи.
/bin/sh -e
скрипт. Но это
может зависеть от конкретных redo
реализаций: некоторые, если
файл является исполняемым, запускают его как полноценную программу;
некоторые, позволяют запускать иные интерпретаторы при указании shebang-а.
Некоторые реализации при задании отладочного флага, добавляют -x
к вызову /bin/sh
.
dir/default.a.b.do dir/default.b.do dir/default.do default.a.b.do default.b.do default.do
А для цели ../a/b/xtarget.y ищутся:
./../a/b/xtarget.y.do ./../a/b/default.y.do ./../a/b/default.do ./../a/default.y.do ./../a/default.do ./../default.y.do ./../default.do
В принципе, единственный default.do можно использовать как аналог единственного Makefile.
$1
– имя цели
$2
– базовое имя цели. Совпадает с $1
если это
не default файл. В противном случае оно будет без
расширения, например для цели a.b.c:
a.b.c.do -> $2=a.b.c default.do -> $2=a.b.c default.c.do -> $2=a.b default.b.c.do -> $2=a
$3
– имя временного выходного файла, который будет
переименован в "цель"
stdout
.do скрипта записывается во временный файл и
становится результатом выполнения цели. Вместо stdout
можно
использовать $3
файл.
stdout
/$3
не было, для удобства.
redo-ifchange
с передачей в качестве аргументов множества
зависимых целей. Если файла перечисленной зависимости нет, то она
собирается и запоминается в state как зависимость. Если файл зависимости
не изменился, то цель зависимости не пересобирается. Зависимость от
текущего .do автоматическая.
redo-ifcreate
с аргументами несуществующих файлов. В
state запоминается отсутствие файла. Его появление вызывает пересборку
текущей цели.
redo target
форсированно вызывает пересборку
цели, даже если зависимости не изменились (.PHONY
-like цель).
Многие реализации дополнительно предлагают ещё такую команду как
redo-always
: всегда пересобирать указанные зависимости.
Некоторые реализации используют ctime
для понимания изменился ли
файл, а некоторые – множество различных атрибутов файлов (mtime, size,
inode number, file mode, UID/GID, и т.д.). Некоторые просто считают
криптографический хэш от файла – плюсом этого решения является
уменьшение false-positive сборок.
Проверенные мной работающие реализации:
apenwarr/do
– из состава apenwarr/redo
(POSIX shell)
Next: Мультимедиа форматы, Previous: Почему современный Web для меня недоступен и мёртв?, Up: Articles