Цель не привязана к автоматической переменной в задании Makefile, расширенном макросом - PullRequest
0 голосов
/ 23 ноября 2018

Я пытаюсь написать задания, которые имеют много общего, как показано ниже.

EMACS_VERS     := 22.1 23.4 24.5 25.3 26.1
LOCAL_LISPDIRS := $(patsubst %,local/%/site-lisp,$(EMACS_VERS))

$(addsuffix /leaf, $(LOCAL_LISPDIRS)): site-lisp/leaf
    mkdir -p $(@D)
    cp -rf site-lisp/$(@F) $@
    $(MAKE) --no-print-directory -C $(dir $(@D)) .make-repo-$(@F)

$(addsuffix /orglyth, $(LOCAL_LISPDIRS)): site-lisp/orglyth
    mkdir -p $(@D)
    cp -rf site-lisp/$(@F) $@
    $(MAKE) --no-print-directory -C $(dir $(@D)) .make-repo-$(@F)

$(addsuffix /cort, $(LOCAL_LISPDIRS)): site-lisp/cort
    mkdir -p $(@D)
    cp -rf site-lisp/$(@F) $@
    $(MAKE) --no-print-directory -C $(dir $(@D)) .make-repo-$(@F)

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

define build_repo
$1: $2
    mkdir -p $(@D)
    cp -rf site-lisp/$(@F) $@
    $(MAKE) --no-print-directory -C $(dir $(@D)) .make-repo-$(@F)
endef

$(eval $(call build_repo,$(addsuffix /leaf,$(LOCAL_LISPDIRS)),site-lisp/leaf))
$(eval $(call build_repo,$(addsuffix /orglyth,$(LOCAL_LISPDIRS)),site-lisp/orglyth))
$(eval $(call build_repo,$(addsuffix /cort,$(LOCAL_LISPDIRS)),site-lisp/cort))

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

mkdir -p
usage: mkdir [-pv] [-m mode] directory ...
make: *** [Makefile:72: local/22.1/site-lisp/leaf.el] Error 64

Есть ли способ решить эту проблему?

С другой стороны, следующеекод был отклонен, так как изменения в листе, орглите, корте все генерируются, когда файлы изменений только в листе.

REPOS       := leaf orglyth cort
REPODIRS    := $(addprefix site-lisp/, $(REPOS))
LOCAL_REPOS := $(foreach repo, $(REPOS), $(addsuffix /$(repo), $(LOCAL_LISPDIRS)))
$(LOCAL_REPOS): $(REPODIRS)
    mkdir -p $(@D)
    cp -rf site-lisp/$(@F) $@
    $(MAKE) --no-print-directory -C $(dir $(@D)) .make-repo-$(@F)

Дерево каталогов:

local
├── 22.1
│   └── site-lisp
│       ├── cort
│       ├── leaf
│       └── orglyth
├── 23.4
│   └── site-lisp
│       ├── cort
│       ├── leaf
│       └── orglyth
├── 24.5
│   └── site-lisp
│       ├── cort
│       ├── leaf
│       └── orglyth
├── 25.3
│   └── site-lisp
│       ├── cort
│       ├── leaf
│       └── orglyth
└── 26.1
    └── site-lisp
        ├── cort
        ├── leaf
        └── orglyth
site-lisp
├── cort
├── leaf
└── orglyth

Ответы [ 2 ]

0 голосов
/ 23 ноября 2018

Ваш макрос раскрывается дважды.Удвойте все знаки $, чтобы избежать первого расширения.

Поскольку у вас есть два вложенных цикла (версии и репозитории), было бы сложно использовать шаблонные правила вместо макросов.Но вы, вероятно, можете использовать макросы немного эффективнее:

# $(1): repo
# $(2): version
define build_repo
local/$(2)/site-lisp/$(1): site-lisp/$(1)
    mkdir -p $$(@D)
    cp -rf site-lisp/$$(@F) $$@
    $$(MAKE) --no-print-directory -C $$(dir $$(@D)) .make-repo-$$(@F)
endef
$(foreach r,$(REPOS),$(foreach v,$(EMACS_VERS),$(eval $(call build_repo,$(r),$(v)))))

Или:

# $(1): repo
# $(2): version
define build_repo
local/$(2)/site-lisp/$(1): site-lisp/$(1)
    mkdir -p local/$(2)/site-lisp
    cp -rf site-lisp/$(1) local/$(2)/site-lisp/$(1)
    $(MAKE) --no-print-directory -C local/$(2) .make-repo-$(1)
endef
$(foreach r,$(REPOS),$(foreach v,$(EMACS_VERS),$(eval $(call build_repo,$(r),$(v)))))

Вторая версия не требует экранирования $, потому что все корректно и полностью раскрывается впервое расширение.Да, даже $(MAKE), который, скорее всего, в вашем случае, расширяется одинаково во время первого или второго расширения.

Но помните, что это особый случай.Если вы продолжаете использовать функцию $(eval...), не забудьте двойное расширение ...

0 голосов
/ 23 ноября 2018

Спасибо @Renaud Pacelet за хороший ответ!

define build_repo
$1: $2;
    mkdir -p $$(@D)
    cp -rf site-lisp/$$(@F) $$@
    $$(MAKE) --no-print-directory -C $$(dir $$(@D)) .make-repo-$$(@F)
endef

$(call build_repo,$(addsuffix /leaf,$(LOCAL_LISPDIRS)),site-lisp/leaf)
$(call build_repo,$(addsuffix /orglyth,$(LOCAL_LISPDIRS)),site-lisp/orglyth)
$(call build_repo,$(addsuffix /cort,$(LOCAL_LISPDIRS)),site-lisp/cort)

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

[Дополнительные примечания]

Я посмотрел на ответ @Renaud Pacalet и пересмотрел.

Собственно, когда хранилищаменяются, я должен построить на всех версиях, поэтому я могу сделать один цикл следующим образом.

LOCALDIRS := $(addprefix local/, $(EMACS_VERS))

define build_repo
$(addsuffix /site-lisp/$(1), $(LOCALDIRS)): $(LISPDIR)/$(1)
    mkdir -p $$(@D)
    cp -rf site-lisp/$$(@F) $$@
    $$(MAKE) --no-print-directory -C $$(dir $$(@D)) .make-repo-$$(@F)
endef
$(foreach repo, $(REPOS), $(eval $(call build_repo,$(repo))))
...