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.