How to Force a Makefile to Rebuild a Target

How do you force a makefile to rebuild a target?

You could declare one or more of your targets to be phony.

A phony target is one that is not really the name of a file; rather it
is just a name for a recipe to be executed when you make an explicit
request. There are two reasons to use a phony target: to avoid a
conflict with a file of the same name, and to improve performance.

...

A phony target should not be a prerequisite of a real target file; if
it is, its recipe will be run every time make goes to update that
file. As long as a phony target is never a prerequisite of a real
target, the phony target recipe will be executed only when the phony
target is a specified goal

How to force make to always rebuild a file

The classic way to do it is:

version.o:   .FORCE

.FORCE:

(and you might add .PHONY: .FORCE). The file '.FORCE' is presumed not to exist, so it is always 'created', so version.o is always out of date w.r.t it, so version.o is always compiled.

I'm not sure that making version.o into a phony file is correct; it is actually a real file, not a phony one.

Is there a way to force rebuilding a target (make -B) without rebuilding its dependencies?

One way is to use the -o option for all targets you don't want to be remade:

-o FILE, --old-file=FILE, --assume-old=FILE
Consider FILE to be very old and don't remake it.

EDIT

I think you're misreading the documentation for -B; it says:

  -B, --always-make
Unconditionally make all targets.

Note, the all targets here; huge is certainly a target, and so if you use -B it will be remade.

However, I also misread your question a bit. I thought you wanted to rebuild small without rebuilding huge even though huge is new, but you're trying to get small to be rebuilt even though huge has not changed, right?

You definitely don't want to use -B. That option is not at all what you are looking for.

Normally people would do that by deleting small:

rm -f small
make small

It might be useful to have an option that forced a given target to be recreated, but that option doesn't exist.

You could use -W huge, but again this means you need to know the name of the prerequisite not just the target you want built.

How do I force make to clean and recompile after changes to Makefile itself?

What you have can't work because after make clean the $(EXEC) file won't exist, so it's always out of date, so it's always rebuilt, and the rebuild will run clean then re-exec itself, so again it will be out of date, so again make will run clean then re-exec itself, etc.

To do what you want you need to list the makefile as a prerequisite of all of the targets. Then you don't need to run clean or re-run make, because all the targets will be out of date when the makefile changes, just as they'd be out of date if the source file changed. So, as an example, add Makefile as a prerequisite to your object file targets:

%.o : %.c Makefile
$(CC) $(CFLAGS) -c -o $@ $<

Without knowing anything about the rest of your makefile we can't give more specific advice than that.

How do I force a target to be rebuilt if a variable is set?

Here is a general solution to your specific problem.

You want to be able to depend on a variable as a prerequisite. That is, you can make it a prerequisite to any target in your makefile, and when the value of the variable changes, you rebuild those targets.

Here is a function that does that, you use this function to declare a variable to be dependable, and then you can use it as a prerequisite.

Note that if the variable is not used on the command line, it will still mean that variable still has a value, namely, the empty string.

define DEPENDABLE_VAR

.PHONY: phony
$1: phony
@if [[ `cat $1 2>&1` != '$($1)' ]]; then \
echo -n $($1) > $1 ; \
fi

endef

#declare ARGS to be dependable
$(eval $(call DEPENDABLE_VAR,ARGS))


foo:foo.c ARGS
$(CC) $(CFLAGS) $(ARGS) -c foo.c -o foo

In fact, we could omit the need for "declaration", and just write a similar function that will make all variables dependable by default. But I don't like that. I prefer that the users that modify makefiles I write, declare their intentions explicitly. It is good for them :)

How the forcing rebuild in my Makefile actually work?

From the manual:

One file can be the target of several rules. All the prerequisites mentioned in all the rules are merged into one list of prerequisites for the target. If the target is older than any prerequisite from any rule, the recipe is executed.

In your case you have two rules for the app target. The prerequisite .force_rebuild from the first rule is marked as .PHONY, which makes your app target always older than .force_rebuild. This triggers execution of the recipe for the app target. That recipe is in the second rule.

Just in case, also pointing out the paragraph following the above quote:

There can only be one recipe to be executed for a file. If more than one rule gives a recipe for the same file, make uses the last one given and prints an error message.

Force gnu make to rebuild objects affected by compiler definition

I use a file to remember the last value of such options, like this:

.PHONY: force
compiler_flags: force
echo '$(CC_FLAGS)' | cmp -s - $@ || echo '$(CC_FLAGS)' > $@

The cmp || echo bit means the file compiler_flags is only touched when the setting changes, so now you can write something like

$(OBJECTS): compiler_flags

to cause a rebuild of $(OBJECTS) whenever the compiler flags change. The rule for compiler_flags will be executed every time you run make, but a rebuild of $(OBJECTS) will be triggered only if the compiler_flags file was actually modified.



Related Topics



Leave a reply



Submit