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-add( add.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에 따르면수동:

패턴 규칙을 적용하려면 대상 패턴이 고려 중인 파일 이름과 일치해야 하며 모든 전제 조건(패턴 대체 후)은 존재하거나 생성될 수 있는 파일의 이름을 지정해야 합니다. 이러한 파일은 대상의 전제조건이 됩니다.

관련 정보