我正在尝试编写包含很多相似之处的作业。
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
有没有办法解决这个问题?
另一方面,以下代码已被拒绝,因为仅在叶子中更改文件时才会生成对leaf,orglyth,cort的更改。
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
答案 0 :(得分:1)
您的宏被扩展了两次。将所有$
符号加倍以退出第一个扩展。
由于您有两个嵌套循环(版本和存储库),因此很难使用模式规则而不是宏。但是您可能可以更有效地使用宏:
# $(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...)
函数,请不要忘记双重扩展...
答案 1 :(得分:0)
感谢@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))))