ファイルが存在する場合、レシピをどのように実行できますか?

ファイルが存在する場合、レシピをどのように実行できますか?

特定のファイルが存在する場合にのみ実行する必要がある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

レシピにシェル部分を書いてください。

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

シェルにドルが表示されるようにするには、それを2倍にする必要があり、プログラムが1つの論理行になりたいので、makeはそれを単一のシェルに提供します。

GNUmakeには、単一のシェルで完全なレシピを実行できる拡張機能があります。

catを使用してforループでファイルを読み取るのはベストプラクティスではありません。たとえば、ファイルにスペースがあるとエラーが発生しますが、コードをソースに近づけるためにここでは修正しません。

答え2

これはシェルをシミュレートするための可能でシンプルなソリューションです。

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

また、以下はシェルをエミュレートすることなく機能します。

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

関連情報