CXX := g
CXX_FLAGS := -std=c 17
SRC_DIR := ./src
LIB_DIR := $(SRC_DIR)/lib
OBJ_DIR := $(SRC_DIR)/obj
BIN_DIR := $(SRC_DIR)/bin
BIN_DEBUG := $(BIN_DIR)/Test-debug
BIN_RELEASE := $(BIN_DIR)/Test
SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp)
LIB_FILES := $(wildcard $(LIB_DIR)/*.cpp)
OBJ_FILES := $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRC_FILES)) $(patsubst $(LIB_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(LIB_FILES))
$(BIN_RELEASE): $(OBJ_FILES)
$(CXX) $(CXX_FLAGS) -o $@ $^
$(OBJ_FILES): $(SRC_FILES) $(LIB_FILES)
$(CXX) $(CXX_FLAGS) -c -o $@ $<
clean:
rm ./src/obj/*.o
rm ./bin/*
run:
$(BIN_RELEASE)
This is my Makefile and it is doing the same g -c command in a row and then failing in the linking because it tries to link the a file to it self. Or can someone say how you debug a Makefile.
CodePudding user response:
This is wrong:
$(OBJ_FILES): $(SRC_FILES) $(LIB_FILES)
$(CXX) $(CXX_FLAGS) -c -o $@ $<
Say you have src/foo.cpp
and src/bar.cpp
in SRC_FILES
. Now OBJ_FILES
is src/obj/foo.o
and src/obj/bar.o
. Now the above rule expands like this:
src/obj/foo.o src/obj/bar.o: src/foo.cpp src/bar.cpp
$(CXX) $(CXX_FLAGS) -c -o $@ $<
It's not the case that make will intuit what you want to do here and match up each object file with the source file, or something like that. The above means exactly the same thing as if you'd written these rules:
src/obj/foo.o: src/foo.cpp src/bar.cpp
$(CXX) $(CXX_FLAGS) -c -o $@ $<
src/obj/bar.o: src/foo.cpp src/bar.cpp
$(CXX) $(CXX_FLAGS) -c -o $@ $<
Now you can see why every compile line compiles the same source file: the $<
variable expands to the first prerequisite, and for every object file the first prerequisite is always the same (here, src/foo.cpp
).
You need to use a pattern rule here, telling make how to build one single file. And since you're building things in two different ways, you actually need two pattern rules.
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CXX) $(CXX_FLAGS) -c -o $@ $<
$(OBJ_DIR)/%.o: $(LIB_DIR)/%.cpp
$(CXX) $(CXX_FLAGS) -c -o $@ $<