Решаемые проблемы:
- Поддержка только одной тактики разрешения зависимостей — «сборочная инструкция запускается если целевой файл отсутствует или он старее одной из зависимостей». В Goals планируется реализовать и другие тактики, такие как проверка наличия URL, сравнение времени изменения с любым файлом, оценка сборки пакета в Koji, сравнение контрольных сумм, запуск тестовых наборов с выборочным пропуском тестов.
- При обработке сборочных целей утилита make не разделяет файлы и имена правил, и, как следствие, отсутствует проверка того, что при запуске правила действительно будет создан файл, создание которого заявлено. Например, если при наличии правила с именем «test», запускающего скрипты с тестами, случайно будет создан файл с именем «test», то тесты перестанут вызываться, так как make посчитает, что цель собрана и не требует выполнения каких-либо действий (для обхода проблемы в make можно указать директиву «.PHONY: test»). Goals явно разделяет файлы и имена правил.
- Проблема с предоставлением только одного параметра для сборочных инструкций.
В Goals предлагается использовать произвольное число именованных параметров. Например, можно отдельно выделить из имени признак отладочного файла:
- Завязка на shell-интерпретатор. Например, необходимость контролировать экранирование пробелов в именах файлов и каталогов, трата ресурсов на запуск отдельного shell-интерпретатора при выполнении каждой команды, двойная трактовка символа «$» (используется как в shell, так и в make), учёт отступов.
Указанные проблемы решаются в Goals использованием символа «%» вместо «$» для сборочных переменных («$» остаётся только для shell), применением парсера LALR(1), требующего обрамлять пути и имена файлов кавычками и выделять фигурными скобками блоки с кодом. Весь блок команда запускается в одном экземпляре командной оболочки, а внутри блока допускается произвольное форматирование кода, без привязки к специальным пробелам.
Было: target: foo.o bar.o ${CC} ${CFLAGS} $
Другие особенности Goals:
- Опциональная поддержка задания произвольных имён и параметров:
goal all = : "target" goal link = "target" : "foo.o", "bar.o" { ... } goal compile (name) = "%name.o" : "%name.c", "dep.h" { %CC %CFLAGS -c $^ -o $@ }
- Два режима запуска: режим make для сопоставления сборочных целей с именами файлов (например, файл «foo.o» соответствует цели «%name.o»), и режим прямой компиляции:
goal all = : link goal link = "target" : "foo.o", compile ("bar") { ... } goal compile (name) = "%name.o" : "%name.c", "dep.h" { %CC %CFLAGS -c $^ -o $@ }
- Тактика сборки определяется специальными правилами, при помощи которых можно определять необходимость пересборки сборочной цели. Если осуществляется привязка к наличию файла, то это явно определяется через соответствующий признак («target» для имени правила и *file(«target») для проверки файла).
"target" : "foo.o", "bar.o" { ... } *file("target") : *file("foo.o"), *file("bar.o") { ... }
- Разработчик может определять произвольные признаки сборочных тактик. Признак «*file» определён по умолчанию (@{…} указывает на подавление вывода, а «exit 99» сигнализирует о необходимости пересборки):
tactic *file (filename) = @{ test -f %filename || exit 99 for f in %
- Предлагается парсер сценариев на языке goals и runtime для выполнения языка, построения графа зависимостей и параллельного запуска работ. В состав входит стандартная библиотека вспомогательных функций, которые могут определяться на shell или с использованием специфичного синтаксиса сценариев goals. Функции могут вызываться как по имени, так и по шаблону (по аналогии с языком Пролог)
function wildcard (wc) returning strings = @{ shopt -s nullglob wc=%wc for f in $wc; do echo "$f"; done }
- Из планов на будущее упоминается поддержка типов, отличных от строк, возможность определения значений параметров по умолчанию и поддержка анонимных функций.
goal build (project, bool release = true) = ... build ("foo") build ("foo", false) let hello = { echo "hello" } let f = function (name, version) { CODE } f ("goals", "0.1")
Тем временем, после почти четырёх лет разработки состоялся релиз системы сборки GNU Make 4.3. Кроме исправления ошибок, в новой версии можно отметить следующие улучшения:
- Применение символа «#» внутри макроподстановок или при вызове функций теперь не обрабатывается как комментарий и не требует экранирования (например, теперь нужно писать «foo := $(shell echo ‘#’)», а «foo := $(shell echo ‘#’)» будет приводить к выводу «#»).
- Использование оператора ‘+=’ для добавления к пустой переменной теперь не приводит к подстановке начального пробела, так же как и прикрепление пустой строки вконец переменной не приводит к добавлению финального пробела.
- Добавлена возможность явного определения правил, генерирующих несколько сборочных целей при одном вызове. Для использования данной возможности при определении сборочной цели вместо символа «:» в правилах следует использовать «&:»;
- Реализована переменная «.EXTRA_PREREQS», через которую можно задать необходимые для цели дополнительные компоненты;
- В Makefile теперь допускается выставление опции ‘-j’ в переменных MAKEFLAGS для запуска в параллельном режиме;
- Добавлена возможность использования вызова posix_spawn() вместо fork/exec;
- Применяемый в Windows лимит на 63 параллельные работы (включая субпроцессы, запускаемые через выражения «$(shell)») увеличен до 4095;
- Добавлена опция «—no-silent», отменяющая действие флагов «-s», «—silent» и «—quiet»;
- Добавлен сокращённый вариант опции «—eval» — «-E»;
- Для всех операций раскрытия по маске, включая «$(wildcard …)», теперь применяется сортировка результата (для обеспечения предсказуемого на разных платформах поведения);
- Добавлена поддержка новых версий Си-библиотек Glibc и musl;
- Внесены оптимизации производительности;
- Код перемещён из корня архива в каталог src/*.
Источник: http://www.opennet.ru/opennews/art.shtml?num=52215