[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: Makefiles



> 
> -> ErrataCorrige: it does NOT the same thing, since it is a target with no dependencies, deps
> are _always_ rebuilt.
> 
> > Does it, actually? ?Shouldn't it simply "mkdir obj" once, when the target doesn't exist,
> > and then happily just double-check for it (w/o any failing 'mkdir's) for all of the other .o targets?
> 
> It appears that directory targets are just not checked, or not considered as files: i get a "no rule to make target DEPS"
> when i set DEPS as a prerequisite.
> Moreover, if no prerequisite is set for the 'dirs:' target, the dependencies are always remade along with their prerequisite:
> This may also lead to infinite loops where all dependencies are contnously generated.
> 
> This makefile executes all deps twice:
> http://freeweb.lombardiacom.it/nightwalker/Makefile
> http://freeweb.lombardiacom.it/nightwalker/main.c


The way to do dependencies is to make the makefile include a .d file
for each .cpp file and have a generic %.d:%.cpp rule which will build
the .d file. Make will execute this the first time through when there
isn't one, and thereafter you make sure it gets rebuilt by making the
.d depend on the same files as the .o does. This means filtering the
.d after makedepend has had a go at it with a sed script. This is
needed because the dependencies for this .o not only change if the
.cpp or the .h for it change, but also if any file they include
changes. This is important because otherwise editing a base header to
(say) include a new file won't cause a build of this file otherwise.

If you can bothered to remember to do a make clean and full rebuild on
the three times in your life when this will make a difference, you can
get away with saying

	echo "$*.d:	$*.cpp" >> $*.d
	echo "$*.d:	$*.h" >> $*.d

at the bottom of the %.d:%.cpp rule. Which is what I do.

You then simply say something like..

	SOURCE_FILES:= ($shell find . -name \*.cpp -print)
	DEP_FILES:= ($SOURCE_FILES:.cpp=.d)
	include $(DEP_FILES)

and everything happens automagically.

The loverly thing about this is that GNU make will check each .d file
for newness at the time of inclusion. If it's out of date it'll go
rebuild it. Then it includes it, *THEN* it begins processing the rest
of the rules -- at which time it now has an up-to-date dependency tree
to begin computing which nodes to rebuild. You don't have to remember
to do a "make depend" any more...

Yes, you end up with a ton of .d files. If having them in the source
tree bothers you, it's fairly easy for them to have a whole mirror
file tree to themselves in your sandpit area.

You can then do the same for the objects and the archives.

Makefiles are not difficult. But if you are going to roll them
yourself, please, for the love of all that is holy in this world,
learn to do it properly. (And by properly I don't mean "it works", I
mean "properly". This difference is apparent in the following way:
anywhere you're getting paid to do software, the makefiles will just
about work and there's no option to have them done properly. Only free
things even have the option of actually doing them so they work. Sad
but true.)

Go do a websearch for a paper called "Recursive Makefiles Considered
Harmful". Excellent guide to building sensible makefiles.