Makefile - Сделать зависимость только в том случае, если файл не существует

Как и в названии, я хотел бы сделать зависимость только в том случае, если определенный файл не существует, НЕ каждый раз, когда он обновляется.

У меня есть корневой каталог (тот, у которого есть файл makefile), а в нем есть подкаталог "example". В моем корневом каталоге находятся четыре файла.h(functions.h, parser.h, node.h и exception.h), которые я хотел бы скопировать в подкаталог "example", если эти.h файлы еще не существуют в "примерах".

К сожалению, я не могу просто установить стандартную зависимость для проверки файлов заголовков в "примере", потому что каждый раз, когда я копирую файлы заголовков от root до "example", заголовочные файлы в "примере" будут считаться обновленными и будут вызывать эту зависимость каждый раз, когда я запускаю make. Я хотел бы, чтобы мой makefile копировал файлы заголовков из корневого каталога в "example", только если они не существуют в "примере".

Ответы

Ответ 1

Для этого необходимы только предварительные условия/зависимости:

Однако иногда возникает ситуация, когда вы хотите ввести конкретный порядок в правилах, которые вызывают, не заставляя цель обновляться, если выполняется одно из этих правил. В этом случае вы хотите определить предварительные условия только для заказа. Предварительные требования только для заказа могут быть указаны путем помещения символа трубы (|) в список предварительных условий: любые предпосылки слева от символа трубы являются нормальными; любые предварительные условия справа - это только порядок.

В твоем случае:

examples/%.h : | %.h
    cp $| [email protected]

См. Также: Предварительные требования только для заказа не отображаются в $^ или $+.

Ответ 2

Вы должны выражать зависимости в терминах относительного возраста файлов.

Обычно используется обходной путь - использовать фиктивный ("дозорный") файл, который обозначает завершение операции:

examples/%.h.hasbeencopied: %.h
    if [ -f example/[email protected] ] || cp -p $< examples/[email protected]; \
    then touch [email protected]; \
    else rm -f [email protected]; \
    fi

и сделать любое правило зависит от example/foo.h также зависит от example/foo.h.hasbeencopied.