公平警告:我对使用makefile感到陌生,所以可能显而易见。我正在尝试做的是使用make运行第三方代码生成工具,当且仅当该生成工具的源文件(称为.abc文件)发生更改时。我在http://www.cmcrossroads.com/ask-mr-make/6795-rebuilding-when-a-files-checksum-changes引用了一个示例,它展示了如何构建MD5,我稍微调整了一下这个想法:
档案:abc.mk
target = all
files := $(wildcard Abc/*.abc)
bltfiles := $files $(addsuffix .built,$files)
all: $bltfiles
%.built: %.abc %.abc.md5
@echo "Building $*"
@ #Command that generates code from a .abc file
@touch $@
%.md5: FORCE
@echo "Checking $* for changes..."
@ #Command to update the .md5 file, if the sum of the .abc file is different
FORCE:
我打算发生的每个.abc文件都有两个辅助文件:.abc.built& .abc.md5。 .built文件只是一个虚拟目标&上次构建它的时间戳,因为生成工具生成的代码不能轻易地定义为目标。 .md5文件包含.abc文件的最后已知内容的哈希。它只应在文件的哈希值发生变化时更新。
但是,仅当.built文件不存在时才会创建。 .md5规则永远不会运行,即使.abc文件有更新的时间戳,.built规则也不会重新构建。我做错了吗?
更新 对后人来说,这是我开始工作的版本:
档案:abc.mk
# Call this makefile as: make all --file=abc.mk
# Default Target
target = all
COMP_ABC_FILES := $(wildcard Abc/*.abc)
COMP_BLT_FILES := $(COMP_ABC_FILES) $(addsuffix .built, $(COMP_ABC_FILES) )
# This line is needed to keep make from deleting intermediary output files:
.SECONDARY:
# Targets:
.PHONY: all
all: $(COMP_BLT_FILES)
Abc/%.abc.built: Abc/%.abc Abc/%.abc.md5
@echo "Building $*"
@ #Command that generates code from a .abc file
@touch $@
%.md5: FORCE
@echo "Checking $* for changes..."
@$(if $(filter-out $(shell cat $@ 2>/dev/null),$(shell md5sum $*)),md5sum $* > $@)
# Empty rule to force re-build of files:
FORCE:
clean:
@echo "Cleaning .built & .md5 files..."
@rm Abc/*.built
@rm Abc/*.md5
答案 0 :(得分:1)
将makefile修复到三个位置:
target = all
files := $(wildcard Abc/*.abc)
bltfiles := $(files) $(patsubst %.abc,%.built,$(files))
all: $(bltfiles)
#Abc/%.abc.built: Abc/%.abc Abc/%.abc.md5
%.built: %.abc %.abc.md5
@echo "Building $*"
@ #Command that generates code from a .abc file
@touch $@
%.md5: FORCE
@echo "Checking $* for changes..."
@ #Command to update the .md5 file, if the sum of the .abc file is different
FORCE:
请注意更改:
bltfiles := $(files) $(patsubst %.abc,%.built,$(files))
结果在“Abc / a.built Abc / b.built”而不是“Abc / a.abc.built Abc / b.abc.built”中,鉴于%.built
的规则如何,这是必需的定义
all: $(bltfiles)
如上所述,对于$(files)
,'$ bltfiles'必须为$(bltfiles)
,否则make会将其解释为$(f)iles
和$(b)ltfiles
。
提示 :拥有一个带有makefile文件突出显示的编辑器很不错
mkdir -pv Abc; touch Abc/{a,b,c,d,e,f,g}.abc
make -Bs -f abc.mk
输出
Checking Abc/e.abc for changes...
Building Abc/e
Checking Abc/g.abc for changes...
Building Abc/g
Checking Abc/b.abc for changes...
Building Abc/b
Checking Abc/f.abc for changes...
Building Abc/f
Checking Abc/a.abc for changes...
Building Abc/a
Checking Abc/c.abc for changes...
Building Abc/c
Checking Abc/d.abc for changes...
Building Abc/d
答案 1 :(得分:0)
如修正但未解释:Makefile语法与shell语法不同。默认情况下(由于丢失到历史记录的原因),变量只有一个字符长。如果需要更长的变量名,则必须将其放在括号中,以便正确解析。例如,编写$files
实际上会扩展字符串“iles”,因为make会解析并仅扩展“f”变量的值(为空)。
是的,这很奇怪。但这是制作方式。始终将变量放在括号中。