Reputation: 441
What I have is a directory with 3 sub-directories. src/ for .c and .h files, bin/ where the compiled executable is supposed to go and obj/ where I want the .obj files to go.
Now I want the makefile to compile every .c file from src (without me having to list them all in the makefile) and put the .o files in obj and the executable built from foo.c saved as bin/foo.
Can someone help me out? Whenever I use wildcards, make complains about rules not being there and when I use implicit rules, it doesn't put the object files in a separate folder.
Upvotes: 23
Views: 30214
Reputation: 99094
To build foo.o
from foo.c
, locally:
foo.o: foo.c
$(CC) -c $< -o $@
To do the same, but with any needed header files in src/
:
SRC := src
foo.o: foo.c
$(CC) -I$(SRC) -c $< -o $@
To do the same, but with the source file in src/
:
SRC := src
foo.o: $(SRC)/foo.c
$(CC) -I$(SRC) -c $< -o $@
To do that, but put the object file in obj/
:
SRC := src
OBJ := obj
$(OBJ)/foo.o: $(SRC)/foo.c
$(CC) -I$(SRC) -c $< -o $@
A pattern rule that will do that for any such object file (obj/foo.o
, obj/bar.o
, ...):
SRC := src
OBJ := obj
$(OBJ)/%.o: $(SRC)/%.c
$(CC) -I$(SRC) -c $< -o $@
To create the list of desired objects:
SOURCES := $(wildcard $(SRC)/*.c)
OBJECTS := $(patsubst $(SRC)/%.c, $(OBJ)/%.o, $(SOURCES))
And a rule to cover them all:
all: $(OBJECTS)
Putting it all together:
SRC := src
OBJ := obj
SOURCES := $(wildcard $(SRC)/*.c)
OBJECTS := $(patsubst $(SRC)/%.c, $(OBJ)/%.o, $(SOURCES))
all: $(OBJECTS)
$(CC) $^ -o $@
$(OBJ)/%.o: $(SRC)/%.c
$(CC) -I$(SRC) -c $< -o $@
Note that this has one big shortcoming: is does not track dependencies on header files. This can be done automatically, but it's a subtle trick; it can wait until you've mastered this much.
Upvotes: 59