Make не распознает изменения в косвенных зависимостях

Рассмотрим этот простой make-файл:

all: output.txt

# The actual build command won't be this simple.
# It'll more be like "some-compiler file1.txt",
# which includes file2.txt automatically.
output.txt: file1.txt
    cat file1.txt file2.txt > output.txt

file2.txt:
    echo "heyo" > file2.txt

file1.txt: file2.txt

При первом запуске Make распознает, что file2.txt это зависимость file1.txt и поэтому он должен быть построен для output.txt быть построенным. Таким образом, он работает echo "heyo" > file2.txt а потом cat file1.txt file2.txt > output.txt,

Однако при последующих запусках, если file2.txt изменено, Make не перестраивается! Если file1.txt меняется, но не для file2.txt, Это просто дает страшный make: Nothing to be done for 'all'. сообщение.

Люди, которые я видел, предлагают одно хакерское решение - сделать следующее:

all: output.txt

output.txt: file1.txt file2.txt
    cat file1.txt file2.txt > output.txt

Тем не менее, это не возможно в моем случае, так как мои вторичные зависимости (такие строки, как file1.txt: file2.txt) динамически генерируются с использованием include,

Как сделать так, чтобы проверки выполнялись на всех уровнях дерева, если у меня несколько уровней зависимостей?

2 ответа

Решение

Я думаю, что проблема в том, что ваш make-файл немного слишком прост.

Позволять a -> b обозначать a depends on b, Из вашего make-файла у вас есть...

output.txt -> file1.txt -> file2.txt

когда make пытается обновить output.txt он видит, что output.txt зависит от file1.txt, Затем он замечает, что file1.txt зависит от file2.txt, В этот момент цепочка зависимостей останавливается. Если make видит, что file2.txt новее чем file1.txt он выполнит команду (и), связанную с file1.txt: file2.txt delendency. В этом случае, однако, нет никаких команд - только сама зависимость. Это нормально, как идут дела, но это означает, что даже если file2.txt обновляется file1.txt не будет Следовательно, когда make перемещается вверх по цепочке зависимостей к...

output.txt: file1.txt

он видит, что output.txt все еще новее, чем file1.txt поэтому нет необходимости запускать какие-либо команды, связанные с этой зависимостью.

Если вы добавите touch команда...

file1.txt: file2.txt
        touch $@

затем file1.txt будет обновлена, и поэтому цепочка зависимостей будет работать так, как вы ожидаете.

Ваш makefile не генерирует и не обновляет file1.txt на всех (то есть: file1.txt должен существовать в момент запуска make). Он не содержит рецепт для генерации file1.txt от file2.txt, У него просто пустое правило (т.е. правило без рецепта):

file1.txt: file2.txt

поскольку file1.txt обязательное условие output.txtэто пустое правило просто подразумевает, что file2.txt должен существовать для output.txt быть построенным, он даже не обновляется file1.txt когда file2.txt генерируется.

поскольку file1.txt является единственным условием output.txt а также file1.txt никогда не обновляется make, один раз output.txt генерируется, он всегда остается актуальным (при условии file1.txt внешне не обновляется).

file2.txt быть измененным никогда не вызывает output.txt быть восстановленным, потому что:

  • это не является обязательным условием output.txt,
  • это не обновляет file1.txt (которая является единственной предпосылкой output.txt).

Решение

Учитывая ваш текущий output.txt правило:

output.txt: file1.txt
    cat file1.txt file2.txt > output.txt

Если ты хочешь output.txt быть построенным каждый раз file2.txt изменения, то вам нужно file1.txt быть построенным каждый раз file2.txt изменения. Это может быть достигнуто с помощью правила, рецепт которого фактически обновляется file1.txt и имеет file2.txt в качестве предварительного условия, например:

file1.txt: file2.txt
    touch $@
Другие вопросы по тегам