Вообще говоря, GNU make не поддерживает цели с несколькими выходами. Однако есть исключение из этого правила: шаблонные правила. Если вы можете структурировать ваш make-файл так, чтобы он использовал шаблонные правила для генерации объектных файлов, вы сможете достичь своих целей. Например:
.DELETE_ON_ERROR:
all: foo.o
%.o %.d: %.c
@touch $*.d
@touch $*.o
@exit 1
Вы увидите, что в этом make-файле при обнаружении «ошибки» в правиле удаляются как файл .d, так и файл .o. Преимущество этого подхода состоит в том, что он более точно выражает граф зависимостей, описывая, как должен быть создан файл .d и какое правило будет его генерировать.
В качестве альтернативы, общая парадигма в этом случае такая же, как вы предложили: GCC генерирует файл .d во временное имя файла и перемещает его на место только после успешного выполнения команды GCC. Обычно это достигается с помощью хитрости оболочки:
all: foo.o
%.o: %.c
gcc -o $@ -MMD -MF $(basename $@).d.tmp -c $< \
&& mv $(basename $@).d.tmp $(basename $@).d
Здесь «магический трюк» - это использование флагов GCC -MMD
, который генерирует файл зависимостей как побочный эффект компиляции, и -MF
, который позволяет указать имя вывода для файла зависимостей; и использование синтаксиса оболочки cmd1 && cmd2
, который заставляет оболочку выполнять cmd2
, только если cmd1
успешно завершается.