Сделать излишне перекомпилировать цель - PullRequest
0 голосов
/ 27 января 2012

Во-первых, вот мой Makefile, это действительно очень круто. Он генерирует исполняемый файл для каждого файла 'c' в текущем каталоге. Тривиально с оболочкой, PITA с Make ... Я уже упоминал, я не смог бы через десять лет, поэтому, пожалуйста, не смейтесь ...

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

Вот содержимое моего каталога:

% 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

Теперь я запускаю 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

Отлично, все перекомпилировано, последняя строка вывода выглядела немного непоследовательной. Почему это отличается от других?

% 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

Я снова запускаю make, ожидая, что это NOP, ведь я ничего не изменил

% make
gcc -c array_example.c -o array_example

Но он выдает результат, что дает?

% 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

И он повторно скомпилировал этот файл array_example, почему всегда этот?

РЕШЕНИЕ (Спасибо Эльдару Абусалимову)

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

ЗАКЛЮЧИТЕЛЬНАЯ СЕССИЯ

Удалить все сгенерированные файлы

% 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

Запустить make снова

% 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

Теперь это больше не делает глупостей ...

% make
make: Nothing to be done for `all'.

1 Ответ

3 голосов
/ 27 января 2012

Просто удалите рецепт build: $(EXECUTABLES). Во-первых, такое правило не должно создавать файл build. Во-вторых, и отвечая на ваш вопрос о том, почему всегда перекомпилируется только array_example, $(<:%=%.c) приводит к первому перечисленному предварительному условию, которое, вероятно, будет первым, возвращаемым wildcard (который сортирует результат в лексикографическом порядке , не гарантируется, но обычно ). То есть

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 $<

Наконец, не забудьте добавить .PHONY target.

.PHONY: build
build: $(EXECUTABLES)

Make собирает все программы, перечисленные в $(EXECUTABLES), используя неявное правило для создания исполняемых файлов из C-источников. Больше ничего не нужно указывать.

В случае, если неявное правило не в порядке, вы можете, однако, переопределить его, например, следующим образом:

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