Makefile: как объявить зависимость для всех целей, которые соответствуют шаблону? - PullRequest
2 голосов
/ 29 марта 2019

Некоторые файлы в моей цели имеют зависимости от других целей. Я могу обеспечить правильную сборку, добавив явные правила, подобные этому:

static/app.mjs: js2/.legacy_app.built.mjs
static/admin_unit.mjs: js2/.legacy_admin.built.mjs
static/admin_source.mjs: js2/.legacy_admin.built.mjs
static/admin_module.mjs: js2/.legacy_admin.built.mjs

Но это означает изменение моего Makefile каждый раз, когда я добавляю новый источник "admin_X" в свой проект. То, что я хотел бы сделать, это иметь правило шаблона всеохватывающего типа:

static/app.mjs: js2/.legacy_app.built.mjs
static/admin_%.mjs: js2/.legacy_admin.built.mjs

Но это не работает, как объяснено https://stackoverflow.com/a/3734705/179583:

Шаблонные правила без рецептов вообще задокументированы как означающие нечто совершенно иное […:] они отменяют любое ранее существующее неявное правило

Есть ли чистый способ указать, что "любая цель, соответствующая определенному шаблону", зависит от какой-то конкретной другой цели?

Ответы [ 2 ]

1 голос
/ 29 марта 2019

Если все эти файлы уже существуют в файловой системе (т. Е. Не должны создаваться с нуля), вы можете использовать $(wildcard ...):

$(wildcard static/admin_*.mjs): js2/.legacy_admin.built.mjs
0 голосов
/ 29 марта 2019

Как вы знаете, шаблонное правило, например:

static/admin_%.mjs: js2/.legacy_admin.built.mjs
    recipe...

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

Так что в вашем make-файле должно быть что-то else , определяющее цели.Давайте предположим, что это просто список, как в:

$ cat Makefile
MJS_STEMS := app admin_unit admin_source admin_module
MJS_FILES := $(addprefix static/,$(MJS_STEMS:%=%.mjs))

.PHONY: all clean
all: $(MJS_FILES)

$(MJS_FILES): js2/.legacy_admin.built.mjs

static/%.mjs: | static
    @echo $< > $@
    @echo "$@ depends on $<"

js2/.legacy_admin.built.mjs: | js2
    touch $@

static js2:
    mkdir -p $@

clean:
    $(RM) $(MJS_FILES) js2/.legacy_admin.built.mjs

Здесь

$(MJS_FILES): js2/.legacy_admin.built.mjs

говорит, что каждый из $(MJS_FILES) зависит от js2/.legacy_admin.built.mjs.Это самый краткий способ сделать это без правила шаблона.Make работает так:

$ make
mkdir -p static
mkdir -p js2
touch js2/.legacy_admin.built.mjs
static/app.mjs depends on js2/.legacy_admin.built.mjs
static/admin_unit.mjs depends on js2/.legacy_admin.built.mjs
static/admin_source.mjs depends on js2/.legacy_admin.built.mjs
static/admin_module.mjs depends on js2/.legacy_admin.built.mjs

Если вы хотите, вы можете переместить список поддержки MJS_STEMS из файла makefile в другой файл:

$ cat ./mjs_stems
app
admin_unit
admin_source
admin_module

$ cat Makefile
MJS_STEMS := $(shell cat ./mjs_stems)
MJS_FILES := $(addprefix static/,$(MJS_STEMS:%=%.mjs))

.PHONY: all clean
all: $(MJS_FILES)

$(MJS_FILES): js2/.legacy_admin.built.mjs

static/%.mjs: | static
    @echo $< > $@
    @echo "$@ depends on $<"

js2/.legacy_admin.built.mjs: | js2
    touch $@

static js2:
    mkdir -p $@

clean:
    $(RM) $(MJS_FILES) js2/.legacy_admin.built.mjs


$ make clean
rm -f static/app.mjs static/admin_unit.mjs static/admin_source.mjs static/admin_module.mjs js2/.legacy_admin.built.mjs

$ echo "admin_foobar" >> mjs_stems
$ make
touch js2/.legacy_admin.built.mjs
static/app.mjs depends on js2/.legacy_admin.built.mjs
static/admin_unit.mjs depends on js2/.legacy_admin.built.mjs
static/admin_source.mjs depends on js2/.legacy_admin.built.mjs
static/admin_module.mjs depends on js2/.legacy_admin.built.mjs
static/admin_foobar.mjs depends on js2/.legacy_admin.built.mjs

Или вы можете просто получитьMJS_STEMS список из окружения:

$ cat Makefile
MJS_STEMS := $(strip $(MJS_STEMS))
MJS_FILES := $(addprefix static/,$(MJS_STEMS:%=%.mjs))

.PHONY: all clean
all: $(MJS_FILES)

$(MJS_FILES): js2/.legacy_admin.built.mjs

static/%.mjs: | static
    @echo $< > $@
    @echo "$@ depends on $<"

js2/.legacy_admin.built.mjs: | js2
    touch $@

static js2:
    mkdir -p $@

clean:
    $(RM) $(MJS_FILES) js2/.legacy_admin.built.mjs


$ make clean
rm -f static/app.mjs static/admin_unit.mjs static/admin_source.mjs static/admin_module.mjs static/admin_foobar.mjs js2/.legacy_admin.built.mjs

$ export MJS_STEMS=$(cat ./mjs_stems)
$ make
touch js2/.legacy_admin.built.mjs
static/app.mjs depends on js2/.legacy_admin.built.mjs
static/admin_unit.mjs depends on js2/.legacy_admin.built.mjs
static/admin_source.mjs depends on js2/.legacy_admin.built.mjs
static/admin_module.mjs depends on js2/.legacy_admin.built.mjs
static/admin_foobar.mjs depends on js2/.legacy_admin.built.mjs

$ make clean
rm -f static/app.mjs static/admin_unit.mjs static/admin_source.mjs static/admin_module.mjs static/admin_foobar.mjs js2/.legacy_admin.built.mjs

$ export MJS_STEMS="aa bb cc"
$ make
touch js2/.legacy_admin.built.mjs
static/aa.mjs depends on js2/.legacy_admin.built.mjs
static/bb.mjs depends on js2/.legacy_admin.built.mjs
static/cc.mjs depends on js2/.legacy_admin.built.mjs

$ make clean
rm -f static/aa.mjs static/bb.mjs static/cc.mjs js2/.legacy_admin.built.mjs

Но так или иначе, где-то, вы должны указать список целей, а для добавления новых целей вам нужно что-то обновить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...