我有一个依赖于变量的make目标,该变量同时包含PHONY和真实目标。
此目标只需要依赖于变量中的实际目标。
如何测试变量以确定它是否是 PHONY,以便过滤掉它们?
(我可以测试文件在配方中是否存在,但我不希望我的目标通过执行任何 PHONY 目标来触发。
谢谢!
有一种方法可以做到这一点,但我强烈建议不要这样做。首先,虚假目标也可以是文件目标。并且无法区分虚假文件目标和非虚假文件目标。 看起来这个问题暗示作者想要忽略的虚假目标都是非文件目标。在这种情况下,请参阅下面的示例。
.PHONY: phony_target .FORCE
.FORCE:
ALL_TARGETS = phony_target file_target undetermined_target
-include detect_phony.inc
all: final_target
# All done
final_target: $(REAL_TARGETS)
# create $@ triggered by $?
@touch $@
ifeq (,$(MAKE_RESTARTS))
# Generate the list of real file targets in make include file
detect_phony.inc: .FORCE
@echo 'REAL_TARGETS = ' `ls $(ALL_TARGETS) 2>/dev/null` > $@ |:
endif
file_target:
touch $@
undetermined_target phony_target:
# process $@
clean:
rm -f file_target final_target
以下是测试结果:
$make clean
rm -f file_target final_target
$ make
# create final_target triggered by
# All done
$ touch file_target
$ make
# create final_target triggered by file_target
# All done
$ make
# All done
如您所见,它仅在文件目标更新时触发最终目标。
在你批评之前 - 这是这个实现的缺陷:
- make 总是被调用两次,每次运行时都会更新生成的 detect_phony.inc 包含文件
- 如果 detect_phony.inc 以某种方式损坏,则 make 执行将被语法错误锁定,直到您手动删除它。
- 它无法处理我之前提到的虚假文件目标
- 如果在此生成文件中添加了另一个生成的包含,并且需要在 detect_phony.inc 之前再次重新启动,则此功能将中断。
所以这种方法很笨拙,有几个陷阱。我不会在生产环境中使用它。我会坚持先更改顶级 Makefile。