Инкрементное создание завершается неудачно, когда исходный файл удален - PullRequest
0 голосов
/ 18 мая 2019

У меня есть простая программа на C с двумя исходными файлами, и Makefile автоматически генерирует зависимости, как описано в разделе 4.14 Руководства по GNU Make :

all: main

%.d: %.c
        @set -e; rm -f $@; \
         $(CC) -MM $(CPPFLAGS) $< > $@.$$$$; \
         sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
         rm -f $@.$$$$

include main.d
include hello.d

main: main.o hello.o

Это создает файлы типа main.d, которые выглядят так:

main.o main.d : main.c hello.h

Проблема возникает, если я внесу изменения в исходный код (и Makefile), чтобы удалить hello.c и hello.h. При следующем инкрементном перестроении make завершается ошибкой:

make: *** No rule to make target `hello.h', needed by `main.d'.  Stop.

Файл main.d устарел, но make не может восстановить его, поскольку (согласно устаревшему main.d) он по-прежнему зависит от уже не существующего hello.h.

В этой ситуации чистая сборка будет успешной. Как я могу получить инкрементную сборку, чтобы добиться успеха?

1 Ответ

0 голосов
/ 18 мая 2019

Я изменил рецепт %.d, чтобы зависимости учитывались только в том случае, если файл все еще существует.Новое правило Makefile:

%.d: %.c
        @set -e; rm -f $@; \
         $(CC) -MM $(CPPFLAGS) $< > $@.$$$$; \
         sed --in-place 's,\($*\)\.o[ :]*,\1.o $@ : ,g' $@.$$$$ ; \
         sed 's^: \(.*\)^: $$(foreach t,\1,$$(if $$(wildcard $$t),$$t,))^g' < $@.$$$$ > $@; \
         rm -f $@.$$$$

Второй sed изменяет main.d так, чтобы он выглядел следующим образом:

main.o main.d : $(foreach t,main.c hello.h,$(if $(wildcard $t),$t,))

Таким образом, если какой-либо из зависимых файлов должен исчезнуть, makeне будет жаловаться.

Одним из недостатков этого подхода является то, что инкрементная сборка может быть успешной в ситуациях, когда чистая сборка не удалась.Например, если hello.h было удалено без надлежащего удаления #include из main.c, то инкрементная сборка будет выполнена успешно (поскольку она не будет пытаться перестроить main.o), а полная сборка не удастся.

Есть ли другие недостатки этого подхода?Например, есть ли случаи, когда инкрементная сборка была бы неполной?

...