Beta's answer gives you a solution to your problem but doesn't explain why your solution can't work:
DIRS =$(filter %/, $(wildcard */))
I'm not sure what the filter
is for here. It doesn't seem to do anything.
This will evaluate to a list of all the subdirectories, not just the subdirectories containing .go
files, on most systems. However some systems don't list only directories if you give just /
. A more reliable way to list all subdirectories would be:
DIRS := $(patsubst %/.,%,$(wildcard */.))
Note also I used :=
so this is evaluated only once per make invocation, instead of every time the DIRS
variable is evaluated.
build: $(DIRS)
export GO111MODULE=on
This declares a target build
which depends on all DIRS
, but the recipe here is useless. It starts a shell, runs that export in the shell, then the shell exits and the export is gone again. It's not possible for a program (any program, not just make) to modify the environment of its parent process.
bin/%: %/$(wildcard *.go)
env GOARCH=amd64 GOOS=linux go build -ldflags="-s -w" -o bin/$@ $@/*.go
First, the $(wildcard *.go)
is expanded when the makefile is parsed, like all targets and prerequisites. So this expands to the list of all .go
files in the current directory. I assume there are none and so this expands to nothing. If there were some it would be even worse; suppose you had foo.go
and bar.go
in the current directory; then this would expand to:
bin/%: %/foo.go bar.go
which is clearly wrong.
Second, you are using $@
in the recipe but $@
expands to the entire target, which is bin/foo
for whatever directory foo
you have. So bin/$@
expands to bin/bin/foo
which is not what you want.