web-dev-qa-db-ja.com

ワイルドカードに関するメイクファイルに問題があります

ディレクトリ.ctests/テストソースファイルがたくさんあります。次に、それらをそれぞれコンパイルしてリンクし、実行可能ファイル*.outtests/に出力します。そこで、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.ctests/にあります)を実行すると、add.outtests/が表示されるはずですが、代わりにエラーが発生します。

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

このmakefileを正しく書き込む方法と、このmakefileが間違っている理由を知りたいです。

1
Charles

パターンルール in 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マクロには偽の_+_ sが含まれており、おそらくそのような名前のファイルがないため、$(TestDir)/%.out:ルールに違反します。

[1] GNU make manual

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

2
mosvy