Reputation: 3783
Firstly, here's my Makefile, it's really, really cool. It generates an executable for every 'c' file in the current directory. Trivial with shell, PITA with Make... Did I mention, I haven't 'c'd in a decade so please don't laugh...
CC = gcc
#List all 'c' files by wildcard.
SOURCES=$(wildcard *.c)
#Get the 'exe' equivalent of said file
EXECUTABLES=$(SOURCES:%.c=%)
#For each of the '*.exe' files
#append a 'c' suffix to the target
build: $(EXECUTABLES)
$(CC) -c $(<:%=%.c) -o $<
clean:
find ./ ! -name "*.c" -a ! -name "Makefile" -type f -delete
rebuild: clean build
Here are contents of my directory:
% ls -la
total 32
drwxr-xr-x 2 yomom yomom 4096 2012-01-27 13:38 ./
drwx------ 94 yomom yomom 4096 2012-01-27 13:38 ../
-rw-r--r-- 1 yomom yomom 990 2012-01-27 12:47 array_example.c
-rw-r--r-- 1 yomom yomom 341 2012-01-27 13:38 Makefile
-rw-r--r-- 1 yomom yomom 430 2011-12-05 13:08 pointers.c
-rw-r--r-- 1 yomom yomom 319 2012-01-27 12:45 should_create_warning.c
-rw-r--r-- 1 yomom yomom 1472 2011-12-19 16:16 socket-client.c
-rw-r--r-- 1 yomom yomom 1150 2011-12-19 16:15 socket-server.c
Now I run make
% make
gcc array_example.c -o array_example
gcc pointers.c -o pointers
gcc should_create_warning.c -o should_create_warning
gcc socket-client.c -o socket-client
gcc socket-server.c -o socket-server
gcc -c array_example.c -o array_example
Great, it re-compiled everything, the last line of output looked a bit inconsistent though. How come it's different to the others?
% ls -la
total 68
drwxr-xr-x 2 yomom yomom 4096 2012-01-27 13:38 ./
drwx------ 94 yomom yomom 4096 2012-01-27 13:38 ../
-rw-r--r-- 1 yomom yomom 1428 2012-01-27 13:38 array_example
-rw-r--r-- 1 yomom yomom 990 2012-01-27 12:47 array_example.c
-rw-r--r-- 1 yomom yomom 341 2012-01-27 13:38 Makefile
-rwxr-xr-x 1 yomom yomom 7164 2012-01-27 13:38 pointers*
-rw-r--r-- 1 yomom yomom 430 2011-12-05 13:08 pointers.c
-rwxr-xr-x 1 yomom yomom 7139 2012-01-27 13:38 should_create_warning*
-rw-r--r-- 1 yomom yomom 319 2012-01-27 12:45 should_create_warning.c
-rwxr-xr-x 1 yomom yomom 7515 2012-01-27 13:38 socket-client*
-rw-r--r-- 1 yomom yomom 1472 2011-12-19 16:16 socket-client.c
-rwxr-xr-x 1 yomom yomom 7579 2012-01-27 13:38 socket-server*
-rw-r--r-- 1 yomom yomom 1150 2011-12-19 16:15 socket-server.c
I run make again, expecting it to NOP, after all, I haven't changed anything
% make
gcc -c array_example.c -o array_example
But it producted output, what gives ?
% ls -la
total 68
drwxr-xr-x 2 yomom yomom 4096 2012-01-27 13:51 ./
drwx------ 94 yomom yomom 4096 2012-01-27 13:51 ../
-rw-r--r-- 1 yomom yomom 1428 2012-01-27 13:51 array_example
-rw-r--r-- 1 yomom yomom 990 2012-01-27 12:47 array_example.c
-rw-r--r-- 1 yomom yomom 341 2012-01-27 13:38 Makefile
-rwxr-xr-x 1 yomom yomom 7164 2012-01-27 13:38 pointers*
-rw-r--r-- 1 yomom yomom 430 2011-12-05 13:08 pointers.c
-rwxr-xr-x 1 yomom yomom 7139 2012-01-27 13:38 should_create_warning*
-rw-r--r-- 1 yomom yomom 319 2012-01-27 12:45 should_create_warning.c
-rwxr-xr-x 1 yomom yomom 7515 2012-01-27 13:38 socket-client*
-rw-r--r-- 1 yomom yomom 1472 2011-12-19 16:16 socket-client.c
-rwxr-xr-x 1 yomom yomom 7579 2012-01-27 13:38 socket-server*
-rw-r--r-- 1 yomom yomom 1150 2011-12-19 16:15 socket-server.c
And it's re-compiled that array_example file, why always that one?
THE SOLUTION (Thanks to Eldar Abusalimov)
CC = gcc
#List all 'c' files by wildcard.
SOURCES=$(wildcard *.c)
#Get the 'exe' equivalent of said file
EXECUTABLES=$(SOURCES:%.c=%)
all: $(EXECUTABLES)
.PHONY: all
$(EXECUTABLES): % : %.c
$(CC) -c $< -o $@
.PHONY clean:
clean:
find ./ ! -name "*.c" -a ! -name "Makefile" -type f -delete
rebuild: clean all
FINAL SESSION
Remove all generated files
% make clean
find ./ ! -name "*.c" -a ! -name "Makefile" -type f -delete
% ls -la
total 48
drwxr-xr-x 2 yomom yomom 4096 2012-01-27 18:07 ./
drwx------ 94 yomom yomom 4096 2012-01-27 18:07 ../
-rw-r--r-- 1 yomom yomom 990 2012-01-27 17:38 array_example.c
-rw-r--r-- 1 yomom yomom 428 2012-01-27 17:38 array_of_pointers.c
-rw-r--r-- 1 yomom yomom 274 2012-01-27 17:38 const_ptr.c
-rw-r--r-- 1 yomom yomom 293 2012-01-27 17:38 function_pointers.c
-rw-r--r-- 1 yomom yomom 313 2012-01-27 18:06 Makefile
-rw-r--r-- 1 yomom yomom 430 2012-01-27 17:38 pointers.c
-rw-r--r-- 1 yomom yomom 228 2012-01-27 17:38 pointer_to_constant.c
-rw-r--r-- 1 yomom yomom 253 2012-01-27 17:38 pointer_to_pointer.c
-rw-r--r-- 1 yomom yomom 1472 2012-01-27 17:38 socket-client.c
-rw-r--r-- 1 yomom yomom 1150 2012-01-27 17:38 socket-server.c
Run make again
% make
gcc -c array_example.c -o array_example
gcc -c array_of_pointers.c -o array_of_pointers
gcc -c const_ptr.c -o const_ptr
gcc -c function_pointers.c -o function_pointers
gcc -c pointers.c -o pointers
gcc -c pointer_to_constant.c -o pointer_to_constant
gcc -c pointer_to_pointer.c -o pointer_to_pointer
gcc -c socket-client.c -o socket-client
gcc -c socket-server.c -o socket-server
Now it doesn't do silly things anymore...
% make
make: Nothing to be done for `all'.
Upvotes: 0
Views: 108
Reputation: 25483
Just remove the recipe of build: $(EXECUTABLES)
. First, such rule is not supposed to create a build
file. Second, and answering to your question about why only array_example
is being always recompiled, $(<:%=%.c)
results in the first listed prerequisite, which is likely to be the first one returned by wildcard
(which sorts the result in the lexicographical order, not guaranteed, but usually it does). That is,
SOURCES=$(wildcard *.c)# returns 'array_example.c pointers.c ...'.
EXECUTABLES=$(SOURCES:%.c=%)# is 'array_example pointers ...'.
build: $(EXECUTABLES)
# Here '$<' is the first item of '$(EXECUTABLES)', which is 'array_example'.
# And '$(<:%=%.c)' returns 'array_example.c'
$(CC) -c $(<:%=%.c) -o $<
Finally, don't forget to add .PHONY
target.
.PHONY: build
build: $(EXECUTABLES)
Make builds all programs listed in $(EXECUTABLES)
using an implicit rule to make executables from C sources. There is no need to specify anything else.
In case when the implicit rule is not OK, you can, however, override it, e.g. as follows:
$(EXECUTABLES) : % : %.c
$(CC) -o $@ $<
Upvotes: 3