[lug] OT: Makefile oddity

D. Stimits stimits at idcomm.com
Sat Apr 20 15:56:56 MDT 2002


Tom Tromey wrote:
...
> A few comments that might help:
> 
> First of all, if you can assume GNU make (something I recommend if
> possible; experience with automake has shown that writing a portable
> Makefile is painful), then use `$(MAKE) -C DIR' instead of `cd DIR; $(MAKE)'.
> Also, as another nit, I recommend using `&&' instead of `;' in make rules.
> That way you get to find out if anything fails.
> 
> One way to fix your larger problem would be to use a GNU make pattern
> rule for the .o files.  I don't use GNU make features too much, so I'm
> not certain this will work:
> 
>     $(OBJDIR_GLOBAL)/%.o: $(SRCDIR_GLOBAL_SERVER)/%.cpp
>             $(MAKE) -C ../global $@

This pretty much does the job. One thing I will have to do though that
might break this is the use of different defines for subgroups of files
in the global shared sources. Although they are in common to several
subprojects, not all of them are used in all projects, and some of them
are X11 apps, others are not. A particular file in the global will never
be using different defines or flags in different subprojects, which is
the only saving grace. One thing I do expect to change in the future
which could be a serious breakage is defining some with pthread defines
and others remaining single-threaded. What would be nice is a way to
also set a mask for filenames, and provide more than one set of rules
that look like the same rule, yet use different compile lines. Sort of
like C++ function signatures for operator overloading (I know, no such
beast).

[Another wishlist item would be a dependency language based on SQL type
naming, e.g., "${MAKE} -c 'SELECT * FROM ${PROJECT_NAME} WHERE SUFFIX
LIKE %cpp' AND DEPENDENCY_DATED"]. IMHO, this would be really cool
feature for multiple developer setups, placing the data in an SQL
server, and having custom tables to adjust for particular machines or
individuals. It would be a very fun project to research (no sarcasm, the
idea just seems interesting). But any real solution must be based on
existing software which can be expected on other people's machines, so
they don't have to download 10 packages just to build the one (which is
where the clumsier sed/awk/tr type hack works nicely).

> 
> However, there's a bug here.  It is the classic recursive make bug:
> you only have a dependency on the .cpp file.  So if you `touch
> config.h', nothing will be rebuilt -- which is wrong.

I don't really consider this a bug, just a limitation of the technology.
makedepend would almost work, except it is designed for C instead of
C++, and fails to deal properly with .cpp or .cxx extensions. It also
doesn't seem to understand non-.h header suffix of STL, e.g.,
/usr/include/g++-3/vector will never list vector as a dependency, even
if -I is used to name /usr/include/g++-3/ to allow finding it. I'm
tempted to create a line that uses g++ as a preprocess, then a
combination of sed/awk/tr and friends to add the dependencies in the
same way that makedepend does (but have it work right with c++). FYI,
the current project is already terribly broken with respect to
dependencies of headers, so this is in no way a limitation in comparison
to what is already there.

> 
> Putting full dependencies into every Makefile is hard, because the
> maintenance costs are high.  The paper goes into this problem in
> depth.

Yes, this is why I wish makedepend worked with C++ filenames.

> 
> Automake's solution is taken from pre-existing GNU practice (as of
> 1993 or so).  Namely, always recurse into every directory for the
> exported targets.  So:
> 
>     all:
>             for d in $(SUBDIRS); do $(MAKE) -C $$d; done

A different way of doing the same thing, though perhaps a bit more
modular.

> 
> Now, if you go read an automake-generated Makefile.in, you'll see all
> kinds of other stuff surrounding that little piece of code.  For
> instance we correctly deal with `make -k' (or lack of -k).  (Note for
> the record that you can't just copy automake's rules; they have a
> license attached.  See the docs.)
> 
> Another solution would be to have one big Makefile that keeps track of
> everything.  You've already indicated you can't do this though.

Correct. It needs to be broken down and shipped in separate modules,
including a common and then several subpackages as desired. Currently it
all ships, but it has caused problems, it is far from ideal.

> 
> >> It still works, it still ends up with the right thing, but it tries
> >> to do all targets twice, even the ones that were not touched.
> 
> Offhand I don't see why it does them all twice.  That's interesting.
> Perhaps there is also a problem in the Makefile in ../global?

Best I can tell this is solved. It was related to both dependency and
rule being ${SOME_VARIABLE} that was an entire list of files. This was
solved at the same time that the above rule changes were made.

D. Stimits, stimits at idcomm.com

> 
> Tom
> _______________________________________________
> Web Page:  http://lug.boulder.co.us
> Mailing List: http://lists.lug.boulder.co.us/mailman/listinfo/lug



More information about the LUG mailing list