help-make
[Top][All Lists]
Advanced

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

Remaking when some "parameter" changes value


From: Nick Patavalis
Subject: Remaking when some "parameter" changes value
Date: Mon, 13 Feb 2006 01:54:08 +0200
User-agent: Mutt/1.5.9i

My problem, in a nutshell, is this: How can I force a project be
remade, when one of the parameters passed to Make changes?  When, for
example, the flags to the compiler, or to the linker, change?

Let's use this simple makefile as an example:

  CC := $(ARCH)gcc -c
  CFLAGS := -Wall -g
  
  LD := $(ARCH)gcc
  LDFLAGS := -g
  LDLIBS := -lm
  
  OBJS1 := file1.o file2.o ...
  OBJS2 := fileA.o fileB.o ...
  
  program1 : $(OBJS1)
        $(LD) $(LDFLAGS) -o "$@" $+ $(LDLIBS)
  
  program2 : $(OBJS2)
        $(LD) $(LDFLAGS) -o "$@" $+ $(LDLIBS)
  
  %.o : %.c
        $(CC) $(CFLAGS) "$<" -o "$@"

When I say:

  $ make

it does the right thing. It also does the right thing when I say:

  $ touch file1.c
  $ make

It compiles ``file1.c`` to produce ``file1.o`` and then relinks
``program1``. But if, after having built everything, or after I have
built a part of the project, if I say:

  $ make ARCH=ppc-linux-

Then, instead of rebuilding everything---which would be the only safe
and reasonable thing to do---I either get "Nothing to be done...", or
a partial build that mixes "arm" and "ppc" objects and binaries. The
same goes if I say, for instance:

  $ make CFLAGS=-Wall -Winline -O2

I think you can understand the trouble this can lead to.

Here's the best solution I could find to this problem. I rewrite the
Makefile above, adding the following lines at the end:


  $(OBJS1) $(OBJS2) : signature
  $(shell ./mksignature.sh \
        "$(ARCH)" \
        "$(CC)" \
        "$(CFLAGS)" \
        "$(LD)" \
        "$(LDFLAGS)" \
        "$(LDLIBS) \
        ... etc ... )

Whereby ``mksignature.sh`` is a script like the following:

  #!/bin/sh
  SIG=signature
  for v in "$@"; do
    echo "$v" >> "$SIG".new
  done
  if ! cmp -s "$SIG".new "$SIG"; then
    mv "$SIG".new "$SIG"
  fi
  rm -f "$SIG".new

This solves the problem in a reliable, though not terribly efficient,
way: It forces make to rebuild everything when some of the "hidden"
dependencies change (hidden in the sense that they are not captured in
files, hence Make does not normally know about them). What would,
though, be ideal is a way to force make rebuild what is absolutely
necessary. Like for example, if I change LDFLAGS, to relink the
executables, without recompiling the objects. The technique shown
above can be easily extended to accommodate this (by using multiple
"signature" files) but, to my taste, the resulting makefile gets way
too complicated, and it doesn't worth the trouble for most real-world
cases.

Any better solutions?

/npat

-- 
After they make styrofoam, what do they ship it in?
  -- Stephen Wright




reply via email to

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