I think I understand that line $(objects) : %.o : %.c produces line cc -c foo.c when the target is foo.o. This is because
$(objects) : %.o : %.c is converted into foo.o : foo.c right?
But I cannot see the process that produces the second line: cc -o foo foo.o.
I think you are reporting the use of a static rule, followed by an implicit rule. If you run make on the Makefile as described at Static Usage - GNU `make' , then I think you will generate the object files foo.o and bar.o. If you then run make foo the implicit rule will be invoked, and you will get the executable foo, as noted here:
#!/usr/bin/env bash
# @(#) s1 Demonstrate static GNU make rule.
# See:
# http://www.gnu.org/software/make/manual/html_node/Static-Usage.html#Static-Usage
# Utility functions: print-as-echo, print-line-with-visual-space, debug.
# export PATH="/usr/local/bin:/usr/bin:/bin"
pe() { for _i;do printf "%s" "$_i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }
db() { ( printf " db, ";for _i;do printf "%s" "$_i";done;printf "\n" ) >&2 ; }
db() { : ; }
C=$HOME/bin/context && [ -f $C ] && $C make
FILE=${1-Makefile}
pl " Input data file $FILE:"
head $FILE
rm -f *.o foo bar
pl " Results for running command \"make\":"
make
pl " Results for running command \"make foo\":"
make foo
rm -f *.o foo bar
pl " Results for running command \"make foo\", no extant .o files:"
make foo
exit 0
producing:
$ ./s1
Environment: LC_ALL = C, LANG = C
(Versions displayed with local utility "version")
OS, ker|rel, machine: Linux, 2.6.26-2-amd64, x86_64
Distribution : Debian GNU/Linux 5.0.8 (lenny)
bash GNU bash 3.2.39
make GNU Make 3.81
-----
Input data file Makefile:
objects = foo.o bar.o
all: $(objects)
$(objects): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
-----
Results for running command "make":
cc -c foo.c -o foo.o
cc -c bar.c -o bar.o
-----
Results for running command "make foo":
cc foo.o -o foo
-----
Results for running command "make foo", no extant .o files:
cc -c foo.c -o foo.o
cc foo.o -o foo