help-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Target dependent on input maybe rebuilt by recursive make


From: Britton Kerin
Subject: Re: Target dependent on input maybe rebuilt by recursive make
Date: Tue, 27 Jan 2015 13:33:16 -0900

On Tue, Jan 27, 2015 at 12:35 PM, Jonathan Lennox <address@hidden> wrote:
> Hi —
>
> I’m trying to structure a Makefile for a situation where a target depends on 
> inputs that are in a subdirectory, which can be rebuilt by recursive make.
>
> The specific case is a top-level Makefile which builds a binary, which links 
> with static libraries built in a subdirectory.  The top-level Makefile 
> doesn’t have visibility into the inputs to the libraries, so it needs to 
> invoke the recursive make always.
>
> The problem I’m having is that Make’s decision as to whether or not to 
> rebuild the binary seems to depend on whether the files are old *before* the 
> subdirectory make is invoked, not afterwards.  Thus, if an input to a library 
> changes, I have to invoke make

This is as expected.  Make has no way of knowing what the recursive make does,
as the targets it build aren't knows to the top-level instance.  build-bin-libs
is .PHONY afterall (even explicitly declared as such in your Makefile).

Recursive make is bad, basically because by definition it
necessarily breaks the dependency graph artificially into pieces.
See http://aegis.sourceforge.net/auug97.pdf for details.  The easiest
solution is probably the build-too-much strategy from the top level: arrange
for build-bin-libs to always be invoked from the top level, and ensure that
it's an inexpensive mostly-no-op a level down if the libs are up-to-date.
So, lose the order-only prerequisite, and have bin depend on build-bin-libs
instead, so its clear that they are always rebuilt.  Alternately you could
use a stamp target in the top-level dir that depends on the sources (NOT
the targets) in the subdir, with a recipe that invokes the recursive make
to rebuild them then touches the stamp.

Britton

>
> Here is my top-level Makefile:
>
> all: bin
>
> bin_libs = lib/libfoo.a lib/libbar.a lib/libbaz.a
>
> bin: bin.o $(bin_libs)
> $(CC) -o $@ $^
>
> $(bin_libs) : | build-bin-libs
>
> .PHONY: build-bin-libs
>
> build-bin-libs:
> $(MAKE) -C lib $(notdir $(bin_libs))
>
> clean:
> rm -f bin *.o
> $(MAKE) -C lib clean
>
> And here is lib/Makefile:
>
> all: libfoo.a libbar.a libbaz.a libquux.a
>
> ARFLAGS = cru
>
> %.o: %.c
> $(CC) $(CFLAGS) -c $< -o $@
>
> lib%.a: %.o
> rm -f $@
> $(AR) $(ARFLAGS) $@ $^
>
> clean:
> rm -f *.o *.a
>
> (Obviously this is a simplification of my real build environment.)
>
> When I do an initial build, everything’s fine:
>
> $ make
> cc    -c -o bin.o bin.c
> make -C lib libfoo.a libbar.a libbaz.a
> make[1]: Entering directory 
> `/home/jonathan/Cvs/scratch/Make-Recursive-Test/lib'
> cc  -c foo.c -o foo.o
> rm -f libfoo.a
> ar cru libfoo.a foo.o
> cc  -c bar.c -o bar.o
> rm -f libbar.a
> ar cru libbar.a bar.o
> cc  -c baz.c -o baz.o
> rm -f libbaz.a
> ar cru libbaz.a baz.o
> rm baz.o foo.o bar.o
> make[1]: Leaving directory 
> `/home/jonathan/Cvs/scratch/Make-Recursive-Test/lib'
> cc -o bin bin.o lib/libfoo.a lib/libbar.a lib/libbaz.a
>
> However, a change that causes one of the libraries to be rebuilt doesn’t 
> cause bin to be rebuilt, so I have to invoke make twice.
>
> $ touch lib/foo.c
> $ make
> make -C lib libfoo.a libbar.a libbaz.a
> make[1]: Entering directory 
> `/home/jonathan/Cvs/scratch/Make-Recursive-Test/lib'
> cc  -c foo.c -o foo.o
> rm -f libfoo.a
> ar cru libfoo.a foo.o
> make[1]: `libbar.a' is up to date.
> make[1]: `libbaz.a' is up to date.
> rm foo.o
> make[1]: Leaving directory 
> `/home/jonathan/Cvs/scratch/Make-Recursive-Test/lib'
> $ make
> make -C lib libfoo.a libbar.a libbaz.a
> make[1]: Entering directory 
> `/home/jonathan/Cvs/scratch/Make-Recursive-Test/lib'
> make[1]: `libfoo.a' is up to date.
> make[1]: `libbar.a' is up to date.
> make[1]: `libbaz.a' is up to date.
> make[1]: Leaving directory 
> `/home/jonathan/Cvs/scratch/Make-Recursive-Test/lib'
> cc -o bin bin.o lib/libfoo.a lib/libbar.a lib/libbaz.a
>
> What can I do about this?  What’s the best (most idiomatic) way to structure 
> my makefile such that it does what I want — always rebuild both the relevant 
> library and the binary whenever one of the inputs to a library changes?
>
> Note that I don’t just want to do a ‘make all’ in lib — I want it to only 
> build the libraries needed by bin, not (in the example) lib/libquux.a.  (In 
> our actual development environment, some irrelevant libraries may be 
> temporarily broken by other developers, or just take a long time to build.)
>
> I’m using GNU Make 3.81, on Ubuntu 14.04, if that’s relevant.
>
> Thank you for any help!
>
>
> Jonathan Lennox
>
>
> _______________________________________________
> Help-make mailing list
> address@hidden
> https://lists.gnu.org/mailman/listinfo/help-make



reply via email to

[Prev in Thread] Current Thread [Next in Thread]