Makefileのワイルドカードに問題があります。

Makefileのワイルドカードに問題があります。

私のディレクトリには.cテストソースファイルがたくさんありますtests/。それでは別々にコンパイルしてリンクして出力しようと*.outしていますtests/。だからmakefileを書いたが、うまくいきませんでした。

# ...
TestDir := tests
TestSourceFile := $(shell sh -c "ls tests/*.c")
TestTargetFile := $(subst .c,.out,$(TestSourceFile))

TestFrame := testframe.o

TestNeededObjectFile := $(TestFrame) \
    + util.o \
    + tokennames.o \
    + lex.yy.o \
    + hex.o \

.PHONY: test-%

test-%: $(TestDir)/%.out
    $^

.PHONY: test

test: $(TestTargetFile)
    @for t in $(TestTargetFile); do \
        $$t ; \
    done

$(TestDir)/%.out: $(TestDir)/%.o $(TestNeededObjectFile)
    gcc -o $@ $^

%.o : %.c
    gcc -c $(CFLAGS) $^

clean:
    rm -rf *.o lextest *.yy.? *.tab.? *.output $(TokenNameFile) \
        $(TestDir)/*.out

make test-addadd.cis in)を実行するとinが表示されるtests/と予想されますが、エラーが発生します。add.outtests/

> make test-add
make: *** No rule to make target 'tests/add.out', needed by 'test-add'.  Stop.

私はこのメイクファイルを正しく書く方法と、このメイクファイルがなぜ間違っているのかを知りたいです。

答え1

これパターンルールGNU makeは、他のパターンルール[1]を介して直接または再帰的に既存のファイルに解決できない場合、前提条件を考慮しません。

$ make -f <(echo '%.foo: %.bar file.txt;') a.foo
make: *** No rule to make target 'a.foo'.  Stop.

$ touch a.bar
$ make -f <(echo '%.foo: %.bar file.txt;') a.foo
make: *** No rule to make target 'a.foo'.  Stop.

$ touch a.bar file.txt
$ make -f <(echo '%.foo: %.bar file.txt;') a.foo
make: 'a.foo' is up to date.

マクロTestNeededObjectFileにfalse+が含まれており、そのように名前の付いたファイルがない可能性があるため、これはルールに違反します$(TestDir)/%.out:

[1] GNU makeによると手動:

パターンルールを適用するには、ターゲットパターンが検討中のファイル名と一致し、すべての前提条件(パターン置換後)が存在または生成できるファイルの名前を指定する必要があります。これらのファイルはターゲットの前提条件になります。

関連情報