I don\'t know why the Make recompiles all the files every time including the unchanged files, it takes a long time. I searched the Stack Overflow and found some solutions, b
You've not specified any dependencies for each object. Make doesn't have any way of knowing whether the headers that source files depend on have changed or any other dependencies of a source file. For example if some 'definition' file changes, you might need to regenerate headers, which in turn requires re-compilation of dependent source files.
In order to have Make conditionally compile based on dependents you must tell Make what the dependencies are. Be warned though, if you get this wrong you can end up in a nasty situation where you make changes that are not picked up because your dependency list is incorrect, or only partially picked up by some files.
I'd suggest looking at these topics on auto generation of dependencies. Manually managing them is OK for very tiny projects but scales poorly with many files. In addition, maintaining complex Makefiles is a task very few enjoy.
Makefile (Auto-Dependency Generation)
Makefile, header dependencies
For MAKE reference see: http://kirste.userpage.fu-berlin.de/chemnet/use/info/make/make_4.html
You're repeating yourself a lot in that Makefile – that's what make
is supposed to avoid.
Consider the following
MODULES=parser compiler test token lex util main
COMPILER_OBJS=$(MODULES:%=$(OBJ)/%.o)
$(OBJ)/%.o: %.c
@test -d $(OBJ) || mkdir $(OBJ)
$(CXX) $(CXXFLAGS) -c -o $@ $<
compiler: $(COMPILER_OBJS)
$(CXX) $(CXXFLAGS) -o $(COMPILER) $(COMPILER_OBJS)
That is, you're using a ‘pattern rule’ to tell Make how to make an object file from a .c
file and, slightly non-standardly but reasonably, having that file placed in another directory.
Using the pattern-based variable reference to set COMPILER_OBJS
means that you only have to specify the list of modules in one place.
The end result should be (I haven't tested this) that make compiler
(or indeed just make
, as long as compiler
remains the first target in the file) will build the compiler
binary, rebuilding whichever .o
files are out of date at that point.
There's a constant tendency to make Makefiles over-complicated, but using pattern rules and pattern-based variable references are useful core functionality, so you should make sure you understand how those lines work (though note that both of these features are specific to GNU Make).
Just to be very clear: your makefile is broken in various ways which djgandy and Norman Gray have correctly diagnosed. But the specific answer to your specific question of why files are being constantly rebuilt is this:
token.o:
$(dir_guard)
$(CXX) $(CXXFLAGS) -o $(OBJ)/token.o -c $(TOKEN_CPP)
Leaving aside all the other issues, here you tell make: "if you want to build a file token.o
, then you can do it with this recipe". But the recipe doesn't build token.o
, it builds $(OBJ)/token.o
. This is wrong, because after the recipe is run the target (token.o
) still doesn't exist. So the next time you run make, it says "oh, I need to build token.o
... gee, it doesn't exist so I guess I have to build it... oh, here's a rule that can build it...` which still doesn't actually build it.
Your makefile is violating the second rule of Makefiles: Every non-.PHONY rule must update a file with the exact name of its target.
Your rules should always build $@
as that always has the path to the target that make believes that you should be building.