【问题标题】:How to determine if Make target is a PHONY?如何确定 Make 目标是否为 PHONY?
【发布时间】:2018-04-11 17:11:07
【问题描述】:

我有一个依赖于变量的 make 目标,该变量包含 PHONY 和真实目标。

这个目标只需要依赖于变量中的真实目标。

如何测试变量以确定它是否是 PHONY,以便过滤掉它们?

(我可以测试配方中是否存在文件,但我不希望我的目标因执行任何 PHONY 目标而被触发。)

谢谢!

【问题讨论】:

  • target: $(filter-out $(list_of_phony_targets),$(variable_with_targets))
  • 每个虚假目标都出现在以.PHONY: 开头的行中,而不是将它们从变量中过滤掉,我建议您使用一个从不包含它们开始的变量。
  • 感谢您的建议,但我无法控制变量。我从另一个我无法控制的 Make 上下文中接收它。另外,我没有虚假目标列表。如果我这样做了,那就容易了。我想避免使用 grepping 或解析 Makefile 来查找 PHONY 目标。使解析器成为棘手的事情。 ;) 我希望 Make 提供一个 PHONY 目标列表或提供一些测试/功能来区分 PHONY 和真实目标。

标签: makefile gnu-make


【解决方案1】:

有办法做到这一点,但我强烈建议不要这样做。首先,虚假目标也可以是文件目标。并且没有办法区分假文件目标和非假文件目标。 看起来这个问题暗示作者想要忽略的虚假目标都是非文件目标。在这种情况下,请参见下面的示例。

.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

如您所见,它仅在文件目标更新时触发最终目标。

在您批评之前 - 以下是此实现的缺陷:

  1. make 总是被调用两次,每次运行都会更新生成的 detect_phony.inc 包含文件
  2. 如果 detect_phony.inc 以某种方式损坏,make 执行将被语法错误锁定,直到您手动删除它。
  3. 它无法处理我之前提到的虚假文件目标
  4. 如果在此 makefile 中添加了另一个生成的包含,需要在 detect_phony.inc 之前再次重新启动,则此功能将中断。

所以这种方法很hacky并且有几个陷阱。我不会在生产环境中使用它。我会坚持首先更改顶级 Makefile。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-07
    • 2011-05-08
    • 1970-01-01
    • 2017-11-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多