Morpheus
Morpheus

Reputation: 3523

c++ makefile not detecting the changes in the .h files

I have a longish make file and the part where it compiles my source code files is here

$(MAINFILE):    $(BINDIR) $(OBJDIR) $(SCIPLIBFILE) $(LPILIBFILE) $(NLPILIBFILE) $(MAINOBJFILES)
        $(LINKCXX) $(MAINOBJFILES) $(LINKCXXSCIPALL) $(LDFLAGS)  -I$(GRBPATH)/mac64/include -L$(GRBPATH)/mac64/lib -lgurobi_c++ -lgurobi81 $(LINKCXX_o)$@

$(OBJDIR)/%.o:  $(SRCDIR)/%.cpp  
        $(CXX) $(FLAGS) $(OFLAGS) $(BINOFLAGS) $(CXXFLAGS) -I$(GRBPATH)/mac64/include -c  $< $(CXX_o)$@

The header file changes take effect only when I clean everything and then compile from scratch. I have tried this:

$(MAINFILE):    $(BINDIR) $(OBJDIR) $(SCIPLIBFILE) $(LPILIBFILE)   $(NLPILIBFILE) $(MAINOBJFILES)
            $(LINKCXX) $(MAINOBJFILES) $(LINKCXXSCIPALL) $(LDFLAGS)  -I$(GRBPATH)/mac64/include -L$(GRBPATH)/mac64/lib -lgurobi_c++ -lgurobi81 $(LINKCXX_o)$@

$(OBJDIR)/%.o:  $(SRCDIR)/%.cpp   (SRCDIR)/%.hpp  (SRCDIR)/%.h
        $(CXX) $(FLAGS) $(OFLAGS) $(BINOFLAGS) $(CXXFLAGS) -I$(GRBPATH)/mac64/include -c  $< $(CXX_o)$@ 

But I was getting the error:

make: *** No rule to make target `obj/static/O.darwin.x86_64.gnu.opt/ColG_main.o

I am a bit new to makefiles and I was wondering if I can fix this issue.

Upvotes: 1

Views: 904

Answers (1)

John Bollinger
John Bollinger

Reputation: 180048

make knows only about the dependencies you designate in your makefile. In general then, the solution to this problem is to name the appropriate headers as additional prerequisites for the object files. That's what this rule appears to be trying to do ...

$(OBJDIR)/%.o:  $(SRCDIR)/%.cpp   (SRCDIR)/%.hpp  (SRCDIR)/%.h
        $(CXX) $(FLAGS) $(OFLAGS) $(BINOFLAGS) $(CXXFLAGS) -I$(GRBPATH)/mac64/include -c  $< $(CXX_o)$@

, but there are both syntactic and semantic problems with it.

Syntactically, you've omitted two $s from expressions that are intended to be variable references, (SRCDIR) instead of $(SRCDIR).

That's easy enough to fix, but it's merely a feeder into the main problem: the (corrected) rule applies only to building object files that have a corresponding .cpp and a corresponding .hpp and a corresponding .h that either exist or can themselves be built. Perhaps that's really the case for all the objects you want to build, but in my experience, it is atypical for a C++ source file to have two corresponding headers. Except where you have some other rule applicable for building an object, make will report an error such as you observed for objects that don't have both corresponding headers

Moreover, if any of your object files depend on headers other than those directly corresponding to them then that rule does not capture those dependencies. Therefore, it will not reliably produce rebuilds of all objects affected by a given header change.

The solution is to correctly specify all the dependencies for each target. You probably cannot do this via your pattern rule, but you can provide addtional, prerequisite-only rules to specify the header dependencies. You can write such rules manually, but if you have a lot of targets or if their dependency lists change frequently then that is painful and error-prone to write and maintain. If you're using a toolchain that supports it, however, then there are ways to generate those dependency rules automatically. There are lots of online resources discussing that, such as

Upvotes: 1

Related Questions