私のディレクトリには.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
is in)を実行するとinが表示されるtests/
と予想されますが、エラーが発生します。add.out
tests/
> 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によると手動:
パターンルールを適用するには、ターゲットパターンが検討中のファイル名と一致し、すべての前提条件(パターン置換後)が存在または生成できるファイルの名前を指定する必要があります。これらのファイルはターゲットの前提条件になります。