I'm currently trying to build a proper Makefile.
What I want is full control of what's happening, so I don't want any third party software.
My current attempt seems logic to me, but since the dependency generation is not valid, I'm kind of stuck.
For better readabilty, the full Makefile is broken into little pieces. I would appreciate any comment on any section if there's something to improve.
First of all, I have the following static definitions
CXX = g++
CXXFLAGS = -Wall \
-Wextra \
-Wuninitialized \
-Wmissing-declarations \
-pedantic \
-O3 \
-p -g -pg
LDFLAGS = -p -g -pg
DEPFLAGS = -MM
Afaik this should be fine. It would be perfect to make the profiling flags optional but that's not important.
SRC_DIR = ./src
OBJ_DIR = ./obj
SRC_EXT = .cpp
OBJ_EXT = .o
TARGET = ./bin/my_target
SRCS = $(wildcard $(SRC_DIR)/*$(SRC_EXT))
OBJS = $(subst $(SRC_DIR), $(OBJ_DIR), $(SRCS:$(SRC_EXT)=$(OBJ_EXT)))
DEP = depend.main
Basically, this should just extract all the *.cpp
files out of the subfolder src
and additionally replace ./src
with ./obj
and .cpp
with .o
as names of the objects.
.PHONY: clean all depend
all: $(TARGET)
$(TARGET): $(OBJS)
@echo "-> linking $@"
@$(CXX) $^ $(LDFLAGS) -o $@
$(OBJ_DIR)/%.$(EXT_OBJ):
@echo "-> compiling $@"
@$(CXX) $(CXXFLAGS) -c $< -o $@
Afaik, this block - provided a valid dependency file exists - should do all necessary compiling and linking.
clean:
@echo "removing objects and main file"
@rm -f $(OBJS) $(TARGET)
Should be self-explanatory and correct, or am I missing something here?
$(SRC_DIR)/%.$(SRC_EXT):
$(CXX) $(DEPFLAGS) -MT \
"$(subst $(SRC_DIR),$(OBJ_DIR),$(subst $(SRC_EXT),$(OBJ_EXT),$@))" \
$(addprefix ,$@) >> $(DEP);
clear_dependencies:
@echo "-> (re-)building dependencies";
@$(RM) $(DEP)
depend: clear_dependencies $(SRCS)
This is the non-functional part. What I intend to do is using the g++
Compiler flag -MM
to auto-create dependencies and using -MT
to use a different path than the default one.
The resulting dependency should look like
./obj/main.o: ./src/main.cpp ./src/some_header_file.h
Unfortunately, this will never be called and I lack the knowledge why this is the case.
In a similar question, user Beta gladly provided a temporary solution by adding a .Phony
but this has the side effect on rebuilding every object without any change.
Finally, there is just the one line
-include $(DEP)
to include the dependency file, once created.
Any answer providing some hints about any part are very welcome. So my question is: What can I do better or maybe "cleaner" and why doesn't the dependency generation work?