【问题标题】:Makefile: $(shell find ...) doesn't output correct resultsMakefile: $(shell find ...) 没有输出正确的结果
【发布时间】:2013-09-05 02:15:07
【问题描述】:
ALL_SRC := $(shell find . -name "*.java")
ALL_CLASS = $(shell find . -name "*.class")

all:
    @echo "Compiling..."
    $(JAVAC) $(ALL_SRC)
    echo $(ALL_CLASS)
    find . -name "*.class"

当运行这个makefile 时类文件存在时,$(ALL_CLASS) 被正确设置。

为什么echo $(ALL_CLASS) 打印一个空白,而find . -name "*.class" 返回目录中的所有类文件?

【问题讨论】:

    标签: java makefile


    【解决方案1】:

    如果在make 开始运行时类文件不存在,则ALL_CLASS 将设置为空白,因为在shell find 运行时它们不存在。

    但是,您在最后一行的find 正在运行您编译了所有 Java 文件。

    一个更简单的例子可能会有所帮助,让我们先创建一个文件xyzzy1

    touch xyzzy1
    

    然后使用下面的makefile,就创建和运行的时间而言,它与你的基本相同:

    XYZZY=$(shell ls xyzzy*)
    all:
        echo ===
        touch xyzzy2
        echo $(XYZZY)
        echo ===
        ls xyzzy*
        rm xyzzy2
        echo ===
    

    当您对此运行 make 时,您会看到:

    ===
    xyzzy1
    ===
    xyzzy1 xyzzy2
    ===
    

    这是因为XYZZY=$(shell ls xyzzy*) 的执行发生在all 规则开始之前(所以xyzzy2 还不存在)。

    all 规则中的ls xyzzy* 本身在touch之前rm 之后执行,因此这两个文件都存在于那个时候。

    【讨论】:

    • 感谢您的回复。我认为“=”分配,与“:=”分配相反,是在使用变量时评估的。有没有办法推迟对 ALL_CLASS 变量的评估?
    • @yawnerish,我认为这只是一个误解。 Deferred 意味着直到它在第一遍中需要 或第二遍发生时才被评估。这并不意味着推迟到第二遍使用
    • 还有一个问题...您将如何亲自解决这个问题?我该怎么做才能使 $(ALL_CLASS) 获取最新的文件列表?只需运行find . -name "*.class" 即可,但我想将这样的命令保存在变量的顶部。
    • paxdiablo 上面关于延迟的评论有点误导。这不起作用的原因是 make 在尝试运行配方中的任何命令之前会扩展整个配方中的所有变量。因此,在调用 echo "Compiling..." 语句之前,ALL_CLASS 的值就会被扩展。这就是为什么它是空的。
    • 您可以将命令保存在变量中;将变量设置为:ALL_CLASS = `find . -name "*.class"`。现在,每当使用该变量时,它都会扩展为反引号字符串,shell 将运行该字符串而不是 make。
    猜你喜欢
    • 2020-04-19
    • 1970-01-01
    • 2014-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-01
    相关资源
    最近更新 更多