Multi-Binary Makefile for Multiple Executables
Create a Makefile that builds multiple executables from separate source directories, using foreach and call functions for DRY target generation.
Detailed Explanation
Building Multiple Binaries
Projects that produce multiple executables (e.g., a server and a CLI client) need a Makefile that avoids duplicating build rules for each binary.
Using foreach
BINARIES = server client worker
BIN_DIR = bin
all: $(addprefix $(BIN_DIR)/,$(BINARIES))
$(BIN_DIR)/%: cmd/%/main.go
@mkdir -p $(BIN_DIR)
go build -o $@ ./cmd/$*/...
The addprefix function prepends bin/ to each binary name. The % pattern matches any binary name, and $* gives the matched stem. This single rule builds all three binaries from their respective cmd/ directories.
Using define and call (Advanced)
define BUILD_BINARY
$(BIN_DIR)/$(1): $$(wildcard cmd/$(1)/*.go)
@mkdir -p $(BIN_DIR)
go build -o $$@ ./cmd/$(1)/...
endef
$(foreach bin,$(BINARIES),$(eval $(call BUILD_BINARY,$(bin))))
The define block creates a template. The call function substitutes $(1) with each binary name. The eval function treats the result as Makefile syntax. Note the $$ escaping — variables inside define that should be expanded during rule execution (not during eval) need double-dollar escaping.
Separate Build Configurations
server: CFLAGS += -DSERVER_MODE
client: CFLAGS += -DCLIENT_MODE
server client: %: src/%.c src/common.c
$(CC) $(CFLAGS) -o $(BIN_DIR)/$@ $^
Target-specific variable assignments let you add flags for individual binaries without affecting others. The static pattern rule %: src/%.c applies only to the listed targets.
Key Techniques
addprefixandaddsuffixmanipulate lists of file names- Static pattern rules (
targets: pattern: prereqs) restrict pattern matching - Target-specific variables provide per-target configuration
- The
foreach/eval/callpattern generates rules dynamically
Use Case
Building a microservices monorepo where multiple Go or C binaries share common source code but need separate executables with different build configurations.