下面的Makefile必须创建(多个)输出目录,并从上面目录中的输入生成这些目录中的输出。因此,在输入时,dir n 存在,并且dir n /file.foo存在。构建必须创建dir n /out/file.bar。
此Makefile在作为单个作业运行时有效(请注意,它会在$(shell)
中创建两个必需的源目录和文件)。它可能有效,因为makedirs
是all
的第一个/最左边的先决条件。但是,它不适用于多作业(即make -j4
/无论如何)。
有关如何修复依赖项以确保输出目录在需要之前生成的任何想法?
修改
我应该已经明确表示我已尝试过各种仅限订单的先决条件解决方案,但我无法做到这一点并保证目标实际重建(仅限订单点通常是阻止重建,不强制执行依赖顺序)。如果您有OO解决方案,请检查它!感谢。
# expected output:
# made directories
# copying dir1/out/../file.foo to dir1/out/file.bar
# copying dir2/out/../file.foo to dir2/out/file.bar
# created all output files
# done
$(shell mkdir dir1 >& /dev/null; touch dir1/file.foo; \
mkdir dir2 >& /dev/null; touch dir2/file.foo)
OUTDIRS = dir1/out dir2/out
OUTPUTS = dir1/out/file.bar dir2/out/file.bar
.DEFAULT_GOAL := all
.PHONY: makedirs $(OUTDIRS)
.SUFFIXES: .foo .bar
%.bar : ../%.foo
@echo "copying $< to $@"
@cp $< $@
all : makedirs outputs
@echo "done"
outputs : $(OUTPUTS)
@echo "created all output files"
makedirs : $(OUTDIRS)
@mkdir -p $(OUTDIRS)
@echo "made directories"
clean :
@rm -rf dir1 dir2
答案 0 :(得分:2)
make $(OUTPUTS)
对目录本身有order-only依赖:
$(OUTDIRS) :
mkdir -p $@
$(OUTPUTS) : | $(OUTDIRS)
这将保证在$(OUTPUTS)
之前创建目录,但如果目录比目标更新,则不会导致输出重建(这很重要,因为每次设置目录的时间戳时都会设置文件被添加到它...)。
注意:您还可以在输出配方中添加mkdir -p
,如果每次运行输出规则时都不会创建目录,但我更喜欢上述方法。
注意2:在现有的makefile中,您还可以添加一行:$(OUTPUTS): makedirs
,这将强制makedirs
规则在构建任何输出之前运行,但同样,我更喜欢以上解决方案: - )
----编辑:-----
当时有点奇怪 - 您使用的是什么版本的品牌?我刚刚运行了以下内容:在创建目录时注意sleep 1
,这意味着如果存在并发问题,它肯定会命中:
$(shell mkdir dir1 >& /dev/null; touch dir1/file.foo; \
mkdir dir2 >& /dev/null; touch dir2/file.foo)
OUTDIRS = dir1/out dir2/out
OUTPUTS = dir1/out/file.bar dir2/out/file.bar
.DEFAULT_GOAL := all
$(OUTPUTS) : | $(OUTDIRS)
$(OUTDIRS) :
@echo "making $@"
sleep 1
mkdir -p $@
@echo "done making $@"
%.bar : ../%.foo
@echo "copying $< to $@"
@cp $< $@
all : outputs
@echo "done $@"
outputs : $(OUTPUTS)
@echo "created all output files"
clean :
@rm -rf dir1 dir2
输出结果为:
~/sandbox/tmp20> make -j -f Makefile2
making dir1/out
making dir2/out
sleep 1
sleep 1
mkdir -p dir1/out
mkdir -p dir2/out
done making dir1/out
done making dir2/out
copying dir1/out/../file.foo to dir1/out/file.bar
copying dir2/out/../file.foo to dir2/out/file.bar
created all output files
done all
请注意,它会同时构建dir1/out
和dir2/out
,并且在两者都完成之前不会运行模式规则。我还验证了我在note2中提到的解决方案也有效(至少在我的机器上......)。
在执行模式规则时,您可以指定模式之外的依赖关系,因此您可以执行以下操作:
foo.o: foo.h
%.o: %.c
recipe here...
如果foo.o
较新,则会重建foo.h
,如果在构建foo.h
之前不存在foo.o
,则会尝试构建smb_username
。