ディレクトリ.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-add
(add.c
はtests/
にあります)を実行すると、add.out
にtests/
が表示されるはずですが、代わりにエラーが発生します。
> make test-add
make: *** No rule to make target 'tests/add.out', needed by 'test-add'. Stop.
このmakefileを正しく書き込む方法と、このmakefileが間違っている理由を知りたいです。
パターンルール 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 :
パターンルールを適用するには、そのターゲットパターンが検討中のファイル名と一致する必要があり、そのすべての前提条件(パターン置換後)は、存在するファイルまたは作成可能なファイルに名前を付ける必要があります。これらのファイルは、ターゲットの前提条件になります。