3

I am try to build a simple, two-stage project Makefile with GNU make.

The logic I want to follow is

  1. First I construct the dependencies (by gcc -M)
  2. I include the generated .dep files into the Makefile in a second stage build.

The relevant part of my project is the following:

MAKEDEP:=$(CXX) $(CXXFLAGS) -M
ALL_SRCS:=$(ALL_OBJS:.o:.cc)
CXX_DEPS:=$(patsubst %.o,.%.dep,$(ALL_OBJS))

-include $(CXX_DEPS)

%.o: %.cc .%.dep
        $(CXX) $(CXXFLAGS) -c -o $@ $<

.%.dep: %.cc
        $(MAKEDEP) -o $@ $<

clean:
        $(RM) -vf $(ALL_OBJS) $(ALL_LIBS) $(ALL_APPS)

dep: $(CXX_DEPS)

Everything works fine, with a single exception: if I run a make clean, it rebuilds the dependencies! As if a clean: dep line would exist instead of a simple clean: line:

$ make clean
g++ -Wall -std=c++11 -M -o .file1.dep file1.cc
g++ -Wall -std=c++11 -M -o .file2.dep file2.cc
g++ -Wall -std=c++11 -M -o .file3.dep file3.cc
rm -vf file1.o file2.o file3.o app
$

What is in the background? Why does it need to rebuild the dependencies before a cleanup? I didn't give such a dependency.

1
  • 1
    Consider running make -d ....
    – ott--
    Aug 27 '15 at 21:20
5

Because you have asked make to include the files, it then follows the rules to build them.

Now I will try to remember how I solved it on my project:

First realise that we do not care about extra dependencies the first time, as we have to build the object file anyway.

Then if we add (or remove) dependencies we must change something that we already depend on ( the .cc or one of the existing .h ).

In summary we do not need the full list of dependencies for the current state, the dependencies for the previous state are good enough. Therefore we can build the .deps at the same time as the .o (this is also quicker as only one CC pass is needed).

[the next bit I am a bit less certain about]

Now we need to bootstrap the dependencies: Write a rule to create some dummy (empty) .dep files (whenever a .cc is created (this can be very quick)).

Now we still have to create these dummy .dep files, and then clean them. If you avoid recursive make, then you should not need clean to work around bugs (only needed to clean-up to save disk space).

The last step was to add one level of recursion (remember recursive make (usually) is considered harmful http://lcgapp.cern.ch/project/architecture/recursive_make.pdf )

Write a simple makefile for clean rules, that calls make on another makefile for any rule it can not do.

You may only need this last step, but I will not delete the beginning of the answer, as it shows you how to improve the makefile.

4
  • It seriously disappoints me that GNU make is unable to do such a trivial thing. Thank you very much the solution.
    – peterh
    Aug 27 '15 at 22:07
  • It is doing what you asked it to do. You give it a makfile (program) it runs this program. Aug 27 '15 at 22:09
  • It would be better if I could include a file only if it exists.
    – peterh
    Aug 27 '15 at 22:10
  • If you forget the bit about dummy-files, will the -include do that. You may need to experiment. I recommend you do the first bit of my answer as it will make it simpler. Then you may figure it out, without the recursion. I can not remember what the final answer was when I did it, I no longer have the code. Aug 27 '15 at 22:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.