why do echo work in %: foo.o rule but not in %: %.o? - makefile

This is my current makefile
.PHONY = all clean
all: foo
#echo "Dependencies: $<"
%: %.o
#echo "Checking.. $#, <- $<"
gcc -lm foo.o -o foo
#echo "\n"
%.o: %.c
#echo "Creating object.. $#, <- $<"
gcc -c foo.c
#echo "\n"
clean:
#echo "Cleaning up..."
rm -rvf foo.o foo
When I run make, it doesn't print out any echoed strings, but I still get the executable file. This is all the things that get printed to the terminal
gcc foo.c -o foo
echo "Dependencies: foo"
When I replace %: %.0 rule with %: foo.o, everything is printed to the terminal normally
Creating object.. foo.o, <- foo.c
gcc -c foo.c
Checking.. foo, <- foo.o
gcc -lm foo.o -o foo
Dependencies: foo
rm foo.o
In both cases, I still get the executable file foo and it works normally, but why do I get 2 different results in the terminal?

When I run make, it doesn't print out any echoed strings, but I still get the executable file.
Since you do not have an explicit rule for building foo, (GNU) make performs an implicit rule search, by which it attempts to find a chain of one or more pattern rules, whether user-provided or built-in, by which it can build foo. Although it could choose to apply your rule to build foo.o from foo.c and then your rule to build foo from foo.o, it has a shorter chain available: a built-in rule for building foo directly from foo.c. It chooses the latter because it's shorter.
When I replace %: %.0 rule with %: foo.o, everything is printed to the terminal normally
This is a bit of a quirk of the implicit rule search procedure. When you make that change, make identifies the revised rule as "applicable" for building foo on account of the only prerequisite having an explicit name (this is item 5.3 in the algorithm described in the manual). The built-in rule for building directly from %.c is also applicable, but the one given in the makefile has precedence (among rule chains of the same length). The fact that make has to figure out separately how to make foo.o doesn't enter into consideration in this case (this is the quirky part, but follows clearly from the docs).
Of course, this particular quirk is rarely triggered, because a rule of the form of your revised one is almost always inappropriate. It says that whatever target is to be built, it can be built from foo.o, via the provided recipe, but that recipe really works only for building foo. Instead of %: foo.o, then, you really ought to make it foo: foo.o:
.PHONY = all clean
all: foo
#echo "Dependencies: $<"
foo: foo.o
#echo "Checking.. $#, <- $<"
gcc -o $# $< -lm
#echo "\n"
%.o: %.c
#echo "Creating object.. $#, <- $<"
gcc -c foo.c
#echo "\n"
clean:
#echo "Cleaning up..."
rm -rvf foo.o foo
Additional notes:
link library options such as -lm should come at the end of the link line. The relative order of these and object files on the command line matters.
Avoid repeating yourself. Rules' recipes should use automatic variables where possible to avoid repeating the target or prerequisite names.

Related

How to write Make rules for *.h files as dependencies

I'm trying to understand how to handle header file dependencies in Make rules. Let me give you a specific example.
I'm building application called myap using GNU Make. It consists of various *.h and *.c files.
Directory inc/ contains defs.h and util.h header files.
Directory src/ contains main.c, cmd.c and win.c files.
Directory obj/ contains all generated object files.
I have multiple applications that need different build options. So I don't want to rely on any implicit rules and would like to specify my own rules for all object files, etc.
I would like to specify the following rules:
Object files depend on specific *.h and *.c files. If any of them change, all object files must be regenerated. However, even though *.h files are part of the prerequisites list, I don't want to pass them to the compiler. I only want to compile *.c files.
Executable myapp depends on specific *.o files. If any of them change, executable file must be regenerated.
So far, the following Makefile with a static pattern rule seems to work correctly:
myapp_inc := inc/defs.h inc/util.h
myapp_src := src/main.c src/cmd.c src/win.c
myapp_obj := $(patsubst src/%.c,obj/%.o,$(myapp_src))
myapp_bin := obj/myapp
.PHONY: all
all:
# Create obj/main.o obj/cmd.o and obj/win.o from various *.c files
# If any *.h files in $(myapp_inc) list change, all objects are regenerated.
# If any *.c files in $(myapp_src) list change, all objects are regenerated.
$(myapp_obj): obj/%.o: src/%.c $(myapp_inc) $(myapp_src)
gcc -c -o $# $<
# Create obj/myapp from various *.o files
# If any *.o files in $(myapp_obj) list change, executable is regenerated.
$(myapp_bin): $(myapp_obj)
gcc -o $# $^
all: $(myapp_bin)
.PHONY: clean
clean:
rm -f obj/*
I don't quite understand how Make rules should be written correctly in order to handle such use case. Is the above static pattern rule, the only way that works correctly?
Specifically, I have tried the following combinations, as given in various simple examples on the Internet, and they all failed for various reasons.
This rule causes $< to always pass the name of the first prerequisite, which doesn't work with multiple *.c files:
$(myapp_obj): $(myapp_src) $(myapp_inc)
gcc -c -o $# $<
$ make
gcc -c -o obj/main.o src/main.c
gcc -c -o obj/cmd.o src/main.c
gcc -c -o obj/win.o src/main.c
gcc -o obj/myapp obj/main.o obj/cmd.o obj/win.o
/bin/ld: obj/cmd.o: in function `main':
main.c:(.text+0x0): multiple definition of `main'; obj/main.o:main.c:(.text+0x0): first defined here
/bin/ld: obj/win.o: in function `main':
main.c:(.text+0x0): multiple definition of `main'; obj/main.o:main.c:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
make: *** [Makefile:18: obj/myapp] Error 1
This rule causes $^ to always pass the names of all prerequisites, which fails:
$(myapp_obj): $(myapp_src) $(myapp_inc)
gcc -c -o $# $^
$ make
gcc -c -o obj/main.o src/main.c src/cmd.c src/win.c inc/defs.h inc/util.h
gcc: fatal error: cannot specify ‘-o’ with ‘-c’, ‘-S’ or ‘-E’ with multiple files
compilation terminated.
make: *** [Makefile:13: obj/main.o] Error 1
Now I understand the difference between $< and $^ variables, but a lot of documentation is not clear on how they should be used when dealing with a list of multiple *.c and *.h files as prerequisites.
What are the recommended usage pattern for this?
Why is it that when using $< only *.c files get passed to the recipe, but not *.h files? Is Make doing some internal filtering? Is this documented anywhere? Is it possible to modify this behavior for custom suffixes?
Is the above static pattern rule, the only way to make objects depend on *.h and *.c files, but exclude *.h files during compilation?
I don't understand the goal of trying to avoid implicit rules. But in any event, it doesn't matter to the recipe you write whether the rule was implicit or explicit: the same automatic variables are set either way. The $< automatic variable is always the first prerequisite, so if you write your rules such that the first prerequisite is the appropriate .c file then you can always use $< in your recipe to mean the .c file and no other files. All the following will work:
%.o : %.c $(headers)
gcc -c -o $# $<
foo.o: foo.c $(headers)
gcc -c -o $# $<
foo.o : %.o : %.c $(headers)
gcc -c -o $# $<
%.o : %.c
gcc -c -o $# $<
$(srcs) : $(headers)
and others.
Does this mean that all of the prerequisites apply, but only those that match the pattern get passed to the recipe?
I don't understand the question, really. The value of variables and the expansion of the recipe happens only AFTER make has decided to run the rule and is not really related (except for some special automatic variables like $?). Once make has decided that the target is out of date and the recipe needs to be run, it will assign the appropriate automatic variables, expand the recipe, then pass the recipe to the shell to be run.
The automatic variables are assigned as described in the manual: $# is the target, $< is the first prerequisite, $^ is all the prerequisites, etc.
ETA
You still haven't really explained why you don't want to use static pattern rules. They are a perfectly fine and reasonable way to do things.
If you explain what you don't like about static pattern rules, or what you wish you could do differently, then we can probably suggest alternatives that meet those requirements.
Specifically, I have tried the following combinations, as given in various simple examples on the Internet,
$(myapp_obj): $(myapp_src) $(myapp_inc)
Wherever you found this as a recommended example on the Internet, you should immediately delete from any bookmarks as that site doesn't know anything about make.
We see this paradigm at least once a week on SO. I've never really understand why people think it will work: I guess they think make is much more "magical" than it is. Consider, what does the above expand to? Suppose myapp_obj contained foo.o bar.o biz.o and myapp_src contained foo.c bar.c biz.c and myapp_inc contained foo.h bar.h, then make sees:
foo.o bar.o biz.o: foo.c bar.c biz.c foo.h bar.h
I suppose some people think make will intuit that the ".o" files should somehow match up with the ".c" files and will generate a bunch of rules that make that true. That's not what make does. The above line is exactly identical to writing this:
foo.o: foo.c bar.c biz.c foo.h bar.h
bar.o: foo.c bar.c biz.c foo.h bar.h
biz.o: foo.c bar.c biz.c foo.h bar.h
That is, if you have multiple targets make creates one copy of the rule for each target, with the same prerequisites and recipe.
This is obviously not what you want, and that's why none of the examples that try to do things this way can ever work properly.
Why is it that when using $< only *.c files get passed to the recipe, but not *.h files? Is Make doing some internal filtering? Is this documented anywhere? Is it possible to modify this behavior for custom suffixes?
None of that is the case. As I described above, the $< expands to the first prerequisite. That's all. It doesn't matter whether the first prerequisite is a .c file, a .h file, or some other file; whatever it is, $< will be that value. If you write your rule as:
foo.o : foo.c foo.h ; $(CC) -c -o $# $<
then your compiler will be invoked with foo.c. If you write your rule as:
foo.o : foo.h foo.c ; $(CC) -c -o $# $<
then your compiler will be invoked with foo.h. There's no magic here.

Match patten rule before explicit rule

I'm trying to generically add some behaviour to every target in a Makefile, without modifying the targets.
My current attempt is thus:
%: $*
#echo 'Logging $* target'
.PHONY: test
test:
#echo 'Inside explicit test target'
When I run make test, I'd like to match the % pattern rule, which would execute test as a prerequisite ($* expanding to the pattern stem), and then log the target that was run.
$ make test
Inside explicit test target
Logging test target
Instead, what happens is that make test matches the explicit test target (presumably since it's a closer match):
$ make test
Inside explicit test target
How can I get this to work, without changing the explicit test target?
EDIT:
Another attempt...
.SECONDEXPANSION:
%: $$*
#echo 'Logging $* target'
results in
$ make test
make: Circular Makefile <- Makefile dependency dropped.
inside actual test target
I appears from your own answer, which has beaten me to the punch, that
you're concerned only to trigger a preliminary action for targets that are
mentioned on the commandline - $(MAKECMDGOALS). From the posting I took
it that you wanted such an action for "every target in a Makefile", which
would include all targets that are prerequisite to the commandline targets or,
if there are no commandline targets, to the default target.
Anyhow, you may still be interested in a solution to the more general problem.
You want a preliminary action to be executed before the recipe for every target.
Your question is: how to match a patten rule before explicit rule?
This is an XY way of posing the problem, because make will consult pattern
rules to find a way of making a target only if you don't give it an explicit
recipe. You know, for example, that make has a pre-defined pattern rule for
making an .o file from a .c file. Even so, if my makefile is:
test.o:
#echo $#
then make prints test.o, without any attempt to find test.c and compile it.
And if my make file is:
test.o: test.c
#echo $#
test.c:
#echo $#
then make prints:
test.c
test.o
needing no resort to the pattern rule. But if my makefile is:
test.o: test.c
Then make says:
make: *** No rule to make target 'test.c', needed by 'test.o'. Stop
So you can't do what you're after in the way your question supposes,
because the preliminary action you want to provoke from the pattern
rule could be provoked only if there were no other action for the target.
In that case the reasons for the failures of your two posted attempts are fairly academic,
and you may wish to scroll to The Chase.
In your first attempt, with:
%: $*
#echo 'Logging $* target'
The pattern rule - which is unemployed by make test - is equivalent to:
%:
#echo 'Logging $* target'
because $* only assumes a value in the recipe, not in the pattern rule. You
can make this pattern rule be employed by making any target for which the
makefile does not provide a recipe, e.g. make nonsuch will print Logging nonsuch target;
but that is of no use.
The second attempt, with:
.SECONDEXPANSION:
%: $$*
#echo 'Logging $* target'
does the right thing to create the rule you intend to create. But the
meaning of that rule is:
<target>: <target>
#echo 'Logging <target> target'
making every target to which this rule is applied a prerequisite of itself.
Inevitably this will result in a circular dependency error for all such targets.
As you saw, this circularity does not affect the your test target because
it has an explicit recipe and does not employ the rule. But it does provoke
the surprising error:
make: Circular Makefile <- Makefile dependency dropped.
That happens because the first target that make automatically considers is
the makefile itself. Unlike the test target, you have no recipe for
the makefile; so the pattern rule applies to it, making the makefile dependent
on itself.
The Chase
You can achieve what you want by a different approach. In a actual project
it is more than likely that in any makefile you can compute a list of
all possible targets. From this you can generate a corresponding list of
auxiliary targets, say, target => target.prelim, where the
sole purpose of target.prelim is to provoke, when it should and not
otherwise, the required preliminary action for target; and you can get make
to generate a list of order-only rules, target: | target.prelim,
for each target, such that target.prelim will not be considered in determining whether target
must be made, but will be made before target whenever target needs to be made.
Here is an illustration:
SRCS := main.c foo.c
OBJS := $(SRCS:.c=.o)
TARGETS := all prog $(OBJS)
PRELIMS := $(patsubst %,%.prelim,$(TARGETS))
define prelim_rule =
$(1): | $(1).prelim
endef
$(foreach target,$(TARGETS),$(eval $(call prelim_rule,$(target))))
.PHONY: all
all: prog
prog: $(OBJS)
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $# $(OBJS) $(LIBS)
clean:
rm -f $(OBJS) $(PRELIMS) prog
%.prelim:
#echo "Logging target $(#:%.prelim=%)"
#touch $#
And a sample session:
$ make
Logging target all
Logging target main.o
cc -c -o main.o main.c
Logging target foo.o
cc -c -o foo.o foo.c
Logging target prog
cc -o prog main.o foo.o
$ make
make: Nothing to be done for 'all'.
$ make clean
rm -f main.o foo.o all.prelim prog.prelim main.o.prelim foo.o.prelim prog
$ make main.o
Logging target main.o
cc -c -o main.o main.c
$ make main.o
make: 'main.o' is up to date.
$ # A prelim can't out-date its target...
$ touch main.o.prelim
$ make main.o
make: 'main.o' is up to date.
I realise that this isn't answering my question as asked, but it has the effect I want - executing a shell command as late in the Makefile processing as possible.
MYVAR?=foo
.PHONY: test
test:
#echo 'Inside test target'
LOG=$(shell echo 'Logging $(MAKECMDGOALS), myvar=$(MYVAR)' > log)
.SECONDEXPANSION:
force: $$(LOG)
LOG is a deferred variable, so is not expanded until Make evaluates the prerequisite list of the force target.
In a single Makefile, the .SECONDEXPANSION: part is not needed, since the force target is evaluated after MYVAR is set.
However, if I move the LOG variable and force variable into a sub-makefile, it would be easy to include subMakefile before the MYVAR?= line - which would not work.
By specifying .SECONDEXPANSION for force, the reliance on ordering is removed.

Makefile trick to get dependencies of a rule

Is there any trick in GNU Makefiles to get all dependencies of a rule?
Example:
rule1: dep1_1 dep1_2 dep1_3
rule2: dep2_1 dep2_2 rule1
dump_deps:
echo "Dependencies of rule1: $(call do_the_trick, $(rule1))"
echo "Dependencies of rule2: $(call do_the_trick, $(rule2))"
install: $(prefix install-,$(call do_the_trick, $(rule1)))
I'd like to be able to call make dump_deps and see:
dep1_1 dep1_2 dep1_3
dep2_1 dep2_2 dep1_1 dep1_2 dep1_3
Or automatically install dependencies with make install and things like.
Is it possible?
EDIT:
I changed the example to show better that I want something automatic, and not having to hardcode dependency lists myself.
You can't show the transitive dependencies, only the direct ones, however, you can take the output generated below and feed it into the programs dot (part of graphviz) to make sense of the these transitive relationships.
Edit: I guess you could also post-process the results in other ways to just list the deps, but I think pretty pictures are better; feel free to downvote if you disagree ;)
Here's a sample makefile (watch for missing tabs when c&p!):
# Makefile that demonstrates how to dump dependencies.
# The macros we use for compiling stuff.
CC_OBJ=$(CC) -o $# -c $(CFLAGS) $<
CC_BIN=$(CC) -o $# $(CFLAGS) $(LDFLAGS) $^
# If we get "DUMP_DEPS=1 DUMP_DOT=1" on the command line, then instead of
# make-style dependencies, we'll output 'dot' syntax.
# Note: normally, DUMP_DOT_TAIL is undefined, so it doesn't generate any noise.
ifeq ($(DUMP_DOT),1)
DUMP_DOT_HEAD=digraph dependencies {
DUMP_DOT_TAIL=#echo "}"
$(info $(DUMP_DOT_HEAD))
list_dep=#for f in $^; do echo " \"$#\" -> \"$$f\";"; done
else
list_dep=#echo "$#: $^"
endif
# If we get "DUMP_DEPS=1" on the command line, then
# instead of building the code, just print the dependencies.
ifeq ($(DUMP_DEPS),1)
CC_OBJ=$(list_dep)
CC_BIN=$(list_dep)
endif
# An implicit rule that builds *.c -> *.o.
%.o:%.c
$(CC_OBJ)
# Variables for stuff we wanna build.
target=hello
objects=main.o
objects+=stuff.o
objects+=yeah.o
# The top-level 'all' target.
.PHONY: all
all: $(target)
$(DUMP_DOT_TAIL)
# Builds our final executable
$(target): $(objects)
$(CC_BIN)
# A standard clean target.
.PHONY: clean
clean:
-rm -f $(target) $(objects)
Now, you can do this:
make -B DUMP_DEPS=1
And it will go through and list all your pre-requisites is make style of "target: pre-requisite". Sample outputs:
Normal run:
cc -o main.o -c main.c
cc -o stuff.o -c stuff.c
cc -o yeah.o -c yeah.c
cc -o hello main.o stuff.o yeah.o
With make -B DUMP_DEPS=1:
main.o: main.c
stuff.o: stuff.c
yeah.o: yeah.c
hello: main.o stuff.o yeah.o
With make -B DUMP_DEPS=1 DUMP_DOT=1:
digraph dependencies {
"main.o" -> "main.c";
"stuff.o" -> "stuff.c";
"yeah.o" -> "yeah.c";
"hello" -> "main.o";
"hello" -> "stuff.o";
"hello" -> "yeah.o";
}
You could then run the following to output a pretty picture to an SVG image:
make -B DUMP_DEPS=1 DUMP_DOT=1 | dot -Tsvg > deps.svg
Here's what it looks like (this is actually a png, generated with -Tpng > deps.png):
I think this would need some extra work to produce accurate results in all situations, but the principle is sound (e.g. if you use gcc-generated dependency files, you'll need to create them first).
This should list all of the dependencies:
DEPEND = dep1 dep2 dep3
.PHONY: $(DEPEND)
dump_deps: $(DEPEND)
#printf "%s\n" $^
You should remove the line with .PHONY target for your needs. It is used for the sake of the example. And please note that there is a tab between the beginning of the line and printf.
use the buit in variables available with the make utility , $^ -- this represents all the dependencies of the rule.
also looking thru your code , i did make the rule1 into a variable / macro form to suit my purpose ......
rule1 := dep1 dep2 dep3

What are double-colon rules in a Makefile for?

Section 4.13 of the GNU Make manual describes the so-called double-colon rules:
Double-colon rules are rules written with ‘::’ instead of ‘:’ after the target names. They are handled differently from ordinary rules when the same target appears in more than one rule.
When a target appears in multiple rules, all the rules must be the same type: all ordinary, or all double-colon. If they are double-colon, each of them is independent of the others. Each double-colon rule's commands are executed if the target is older than any prerequisites of that rule. If there are no prerequisites for that rule, its commands are always executed (even if the target already exists). This can result in executing none, any, or all of the double-colon rules.
Double-colon rules with the same target are in fact completely separate from one another. Each double-colon rule is processed individually, just as rules with different targets are processed.
The double-colon rules for a target are executed in the order they appear in the makefile. However, the cases where double-colon rules really make sense are those where the order of executing the commands would not matter.
Double-colon rules are somewhat obscure and not often very useful; they provide a mechanism for cases in which the method used to update a target differs depending on which prerequisite files caused the update, and such cases are rare.
Each double-colon rule should specify commands; if it does not, an implicit rule will be used if one applies. See section Using Implicit Rules.
I kinda grok the meaning of each sentence of this section individually, but it's still not clear to me what double-colon rules are for. As for being rare, I have not yet seen any open-source project whose Makefile did not begin with
all::
Therefore: What's the intended purpose of double-colon rules in Makefiles?
Each :: rule is processed independently, so it can be simpler. For example, the single rule:
libxxx.a : sub1.o sub2.o
ar rv libxxx.a sub1.o
ar rv libxxx.a sub2.o
can be replaced with two simpler rules:
libxxx.a :: sub1.o
ar rv libxxx.a sub1.o
libxxx.a :: sub2.o
ar rv libxxx.a sub2.o
Utilities like AutoMake have an easier time spitting out many simple rules than a few complex ones.
A great answer with more examples was posted, then taken down, then found here:
https://web.archive.org/web/20180122002430/http://owen.sj.ca.us/~rk/howto/slides/make/slides/makecolon.html
Thanks to R.K. Owen for writing it, and Edward Minnix for finding it again!
There are 3 situations where the double colon are useful:
Alternate between the compile rules based on which prerequisite is newer than the target. The following example is based on "Example 19-3. Double-colon rules" from http://books.gigatux.nl/mirror/cinanutshell/0596006977/cinanut-CHP-19-SECT-3.html
Sample .c file:
c#desk:~/test/circle$ cat circle.c
#include <stdio.h>
int main (void)
{
printf("Example.\n");
return 0;
}
Makefile used:
c#desk:~/test/circle$ cat Makefile
# A makefile for "circle" to demonstrate double-colon rules.
CC = gcc
RM = rm -f
CFLAGS = -Wall -std=c99
DBGFLAGS = -ggdb -pg
DEBUGFILE = ./debug
SRC = circle.c
circle :: $(SRC)
$(CC) $(CFLAGS) -o $# -lm $^
circle :: $(DEBUGFILE)
$(CC) $(CFLAGS) $(DBGFLAGS) -o $# -lm $(SRC)
.PHONY : clean
clean :
$(RM) circle
Outcome:
c#desk:~/test/circle$ make circle
gcc -Wall -std=c99 -o circle -lm circle.c
make: *** No rule to make target 'debug', needed by 'circle'. Stop.
c#desk:~/test/circle$ make circle
gcc -Wall -std=c99 -o circle -lm circle.c
gcc -Wall -std=c99 -ggdb -pg -o circle -lm circle.c
c#desk:~/test/circle$ vim circle.c
c#desk:~/test/circle$ make circle
gcc -Wall -std=c99 -o circle -lm circle.c
c#desk:~/test/circle$ vim debug
c#desk:~/test/circle$ make circle
gcc -Wall -std=c99 -ggdb -pg -o circle -lm circle.c
Make a pattern rule terminal.
The following example explains this situation: the a.config file is obtained from a.cfg, which in turn is obtained from a.cfg1 (a.cfg being the intermediate file).
c#desk:~/test/circle1$ ls
a.cfg1 log.txt Makefile
c#desk:~/test/circle1$ cat Makefile
CP=/bin/cp
%.config:: %.cfg
#echo "$# from $<"
#$(CP) $< $#
%.cfg: %.cfg1
#echo "$# from $<"
#$(CP) $< $#
clean:
-$(RM) *.config
Outcome (as the %.config rule is terminal, make inhibits the creation of the intermediate a.cfg file from a.cfg1):
c#desk:~/test/circle1$ make a.conf
make: *** No rule to make target 'a.conf'. Stop.
Without the double colon for the %.config, the outcome is:
c#desk:~/test/circle1$ make a.config
a.cfg from a.cfg1
a.config from a.cfg
rm a.cfg
Make a rule that executes always (useful for clean rules). The rule must not have prerequisites!
c#desk:~/test/circle3$ cat Makefile
CP=/bin/cp
a.config::
#echo "Always" >> $#
a.config::
#echo "Always!" >> $#
clean:
-$(RM) *.config
Outcome:
c#desk:~/test/circle3$ make a.config
c#desk:~/test/circle3$ cat a.config
Always
Always!
c#desk:~/test/circle3$ make a.config
c#desk:~/test/circle3$ cat a.config
Always
Always!
Always
Always!
They are handy for non-recursive makefiles and targets like clean. That is, an individual .mk file can add its own commands to the clean target already defined elsewhere.
Documentation gives an answer:
Double-colon rules are somewhat obscure and not often very useful; they provide a mechanism for cases in which the method used to update a target differs depending on which prerequisite files caused the update, and such cases are rare.
Just as the documentation says, double-colon rules are rarely very useful. They are a nice, little way of not naming the individual targets of a composite phony target (like all::), but not really necessary in this role. I can only form one contrived example where they are necessary:
Suppose you have a logfile L that is concatenated from several other logfiles L1, L2, .... You formulate a number of double-colon rules like:
L :: L1
cat $< >> $# && rm $<
L :: L2
cat $< >> $# && rm $<
Nowadays in GNU make, you would of course use $^ for this kind of magic, but it is listed as an inspired feature on GNU make's feature tab.
I'll contribute a simple example to hopefully make the usage clear:
Experiment with the following makefile:
a.faux:: dep1.fake
$(info run a dep1.fake)
touch a.faux
a.faux:: dep2.fake
$(info run a dep2.fake)
touch a.faux
dep1.fake:
touch dep1.fake
dep2.fake:
touch dep2.fake
Run make a.faux, it will causes dep1.fake and dep2.fake to run. Delete dep1.fake and run make a.faux again, only dep1.fake will run.

Running Makefile targets

I am trying to 'fire' off the compilation by making all dependencies in a list of items, which are themselves targets.
From the answer (last, posted by Carl..) given in seems to suggest that something like this is possible.
Wildcard targets in a Makefile
all: $(OBJECTS)
OBJECTS = foo.o bar.o
bar.o: bar.c
#echo make $#
foo.o: foo.c
#echo make $#
.PHONY: all
My question is, when I run make I get the following, I cannot seem to get it to compile.
make: Nothing to be done for `all'.
Reverse the order of the first two lines, like so:
OBJECTS = foo.o bar.o
all: $(OBJECTS)
In your example, when Make gets to the all rule, OBJECTS has not yet been defined, so it resolves to this:
all:
Make sees a rule with no commands and no prerequisites-- nothing to be done.
You can do something like
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
This means:
To make a .o file, we need a .c file with the same name ( represented by %). The command to make the .o file is the name of the C compiler $(CC), followed by any compiler flags $(CFLAGS), then -c, etc. $< is the name of the first prerequisite ($^ is the names of all prerequisites, if you want that), and $# is the name of the target.

Resources