Why is my make test
not working?
I have this simple makefile and when running
# make test
make: 'test' is up to date.
Where comes 'test' is up to date.
from!?
makefile
BINARY_HTTP=http
build:
@go build -o bin/${BINARY_HTTP} cmd/${BINARY_HTTP}/main.go
run: build
ifdef skip-user
@./bin/${BINARY_HTTP}/main -skip-user
else
@./bin/${BINARY_HTTP}/main
endif
test:
@echo "test"
@go test -count=1 ./test
If the test
command in the makefile is changed to something else like wee
the command works? Why??
# make wee
test
makefile
BINARY_HTTP=http
build:
@go build -o bin/${BINARY_HTTP} cmd/${BINARY_HTTP}/main.go
run: build
ifdef skip-user
@./bin/${BINARY_HTTP}/main -skip-user
else
@./bin/${BINARY_HTTP}/main
endif
wee:
@echo "test"
@go test -count=1 ./test
As evidenced by the last line of your Makefile
, you have a file called test
lying next to it.
For make, a rule specifies a target output file, in your case: test
.
Your test
rule also doesn't have any prerequisites.
So what will happen is when you call make test
is that make will check if there's already a file called test
which is newer than its prerequisites (there are none).
This condition is satisfied and make will happily tell you that it doesn't need to do any work at all.
Once you rename your rule's target into anything that's not an existing file, the rule will run in a futile attempt to create a file wee
.
Your recipe doesn't create such a file so this will always run.
The correct solution is to add the following line to your Makefile
:
.PHONY: test
Quoting from make's doc:
A phony target is one that is not really the name of a file; rather it is just a name for a recipe to be executed when you make an explicit request. There are two reasons to use a phony target: to avoid a conflict with a file of the same name, and to improve performance.
Running on request it what you want to do. Avoiding conflict with a file is what you need to do.
The same logic applies, by the way, to the run
target in your Makefile
.
And your build
target should rather specify the output file as in the following untested file! I also omitted the BINARY_HTTP
variable for clarity.
Please see this as a possible next step towards a clean and idiomatic makefile, not as the end result.
bin/http: cmd/http/main.go
@go build -o $@ $<
.PHONY: run
run: bin/http
ifdef skip-user
@./bin/${BINARY_HTTP}/main -skip-user
else
@./bin/${BINARY_HTTP}/main
endif
.PHONY: test
test: bin/http
@echo "test"
@go test -count=1 ./test