내 디렉토리에 .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에 따르면수동:
패턴 규칙을 적용하려면 대상 패턴이 고려 중인 파일 이름과 일치해야 하며 모든 전제 조건(패턴 대체 후)은 존재하거나 생성될 수 있는 파일의 이름을 지정해야 합니다. 이러한 파일은 대상의 전제조건이 됩니다.