使用.PHONY规则触发“nothing to be done for”错误的技术咨询
Let's break down why your current setup is failing, then fix it with a clean, reliable Makefile that behaves exactly as you expect.
What's Going Wrong?
Your issues stem from two core mistakes:
- You're targeting actual test files: When you use
tests/%.javaas a target, Make sees these as existing, unmodified files. It assumes they're already "up-to-date" and skips running the test rule, hence the "Nothing to be done" message. - Static wildcard expansion: The
$(wildcard tests/*.java)variable expands once when Make first loads the file. New test files added later won't be picked up unless you force Make to re-parse the file (like runningmake clean).
Fixed Makefile
Here's the corrected version that resolves both problems:
PROG = Test # Generate virtual test targets (not actual files) from test Java files TEST_TARGETS = $(patsubst tests/%.java, tests/%.test, $(wildcard tests/*.java)) .SUFFIXES: .java .class JCC = javac JAR = jar all: $(PROG).jar # Mark test targets as PHONY to ensure they always run .PHONY: test clean $(TEST_TARGETS) test: $(PROG).jar $(TEST_TARGETS) # Rule for virtual test targets - runs the corresponding Java test file tests/%.test: @echo "#### testing tests/$*.java ####" @java -jar $(PROG).jar tests/$*.java @echo "> Passed" $(PROG).jar: Main.class $(JAR) cmf $(PROG)MainClass.txt $(PROG).jar $^ Main.class: Main.java $(JCC) $^ clean: rm -f *.class $(PROG).jar
Key Fixes Explained
Virtual Test Targets:
We use$(patsubst)to convert eachtests/%.javafile into a non-existenttests/%.testtarget. Since these targets don't correspond to real files, Make will always try to run their rules, no matter the state of your test files.Proper PHONY Usage:
Only marktestand the virtual$(TEST_TARGETS)as PHONY. Marking actual test files as PHONY breaks Make's dependency checking logic, which was part of your original problem.Dynamic Test Detection:
If you add new test files and want Make to pick them up withoutmake clean, run:make test -BThe
-Bflag (short for--always-make) forces Make to re-parse the wildcard variable and run all tests, even if it thinks things are up-to-date.
How to Verify
- Run
make test: It will execute all tests in thetests/directory every time, no "Nothing to be done" messages. - Add a new
.javafile totests/, then runmake test -B: The new test will be picked up and executed automatically.
内容的提问来源于stack exchange,提问作者collin.clark

