如果文件存在,如何执行配方?

如果文件存在,如何执行配方?

我正在编写一个 Makefile 配方,当且仅当某个文件存在时才需要执行......

这是我所拥有的:

clean:
    $(if $(shell test -s ${MFN_LSTF}), \
        $(foreach mfn, $(shell cat ${MFN_LSTF}), \
            $(MAKE) -f mfd/${mfn} clean;), )
.PHONY: clean

${MFN_LSTF} 保存一个文件名,其中包含一列 makefile 名称列表,假定这些名称与此 makefile 配方位于同一本地目录。

我遇到的问题是,该foreach语句总是执行。我希望它仅在文件名${MFN_LSTF}存在时执行。

我也尝试过这个:

clean:
    [ test -s ${MFN_LSTF} ] &&
        for mfn in $(shell cat ${MFN_LSTF}); do
            $(MAKE) -f mfd/${mfn} clean
        done
.PHONY: clean

答案1

您可以将 shell 部分写在 recipie 中。

clean:
        F="$MF_NAMES_LIST" ;\
        if [ -e "$$F" ] ; then \
                for mfn in $$(cat "$$F") ; do \
                         $(MAKE) -f mfd/$${mfn} clean;\
                done ; \
        fi

需要注意的是,如果您希望 shell 看到一美元,则需要将其加倍,并且您希望程序成为一个逻辑行,因此 make 将其提供给单个 shell。

GNUmake 有一个扩展,允许您在单个 shell 中运行整个食谱。

使用 cat 将文件读入 for 循环并不是最佳实践,例如,如果文件中存在空格,就会出错,但我不会在此处修复该问题以保持代码接近原始代码。

答案2

这可能是一个可能且更简单的解决方案,模拟 shell:

    $(eval mfn_lstf := $(shell cat ${MFN_LSTF}))
    $(foreach mfn, ${mfn_lstf}, $(MAKE) -f mfd/${mfn} clean;)

并且,以下工作无需模拟 shell:

    if [ -s "$${MFN_LSTF}" ]; then \
        while IFS= read -r mfn; do \
            $(MAKE) -f "mfd/$${mfn}" clean; \
        done < "$${MFN_LSTF}"; \
    fi

相关内容