I am trying to write a Makefile with my source and object files separated and I can't seem to figure out the proper way to accomplish this. I have two methods that work but I'm hoping someone can point the "correct" way to do this is.
My project is separated into a src
and obj
folder with the Makefile at the same level as these.
The first method uses the wildcard function to find the source files in src
then uses text replacement to determine the corresponding object files.
SRC = $(wildcard src/*.cpp)
OBJ = $(SRC:.cpp=.o)
prog: $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) -o prog $(patsubst src/,obj/,$(OBJ))
%.o: %.cpp
$(CC) $(CFLAGS) -c $< -o $(COMPILE)/$(@F)
This seems to work, however, every time I run make prog
it recompiles all the object files. The OBJ
variable has to have the src/
in front of all the objects or else I get the "no rule to make target". On the plus side, I can easily use the patsubst in the prog
target to specify the object files.
The second method is similar but uses vpaths and text replacement on the OBJ
variable:
vpath = %.cpp src
vpath = %.o obj
SRC = $(wildcard src/*.cpp)
OBJ = $(subst src/,,$(SRC:.cpp=.o))
POBJ = $(patsubst src/,obj/$(SRC:.cpp=.o))
prog: $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) -o prog $(POBJ)
%.o: %.cpp
$(CC) $(CFLAGS) -c $< -o $(COMPILE)/$(@F)
This eliminates the recompiling of object files, but requires me to add another variable POJB
for the prog
target (since I can't do any patsubst on just the object files without a basedir).
Both methods work and each has its advantages over the other but which one is the "correct" approach and if neither, what is the proper way to achieve this type of building?
Your first example is almost there:
SRC = $(wildcard src/*.cpp)
OBJ = $(patsubst src/%.cpp, obj/%.o, $(SRC))
prog: $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) $(OBJ) -o prog
obj/%.o: src/%.cpp
$(CC) $(CFLAGS) -c $< -o $@