make -B всегда печатает "актуально" для задачи оболочки - PullRequest
0 голосов
/ 15 января 2020

Рассмотрим этот Makefile

test.txt: foo.bar
        $(shell grep ^hello $< >$@)

Чтобы проверить его, нужно создать файл foo.bar, содержащий, например,

hello
hello 2

make всегда печатает

make: 'test.txt' is up to date.

Это происходит, даже если файл test.txt отсутствует. В этом случае make работает правильно и создает test.txt, но все равно печатает указанное выше сообщение. Даже использование make -B выдает то же сообщение.

Я использую GNU Make 4.2.1.

Почему это поведение?

1 Ответ

1 голос
/ 20 января 2020

Это происходит потому, что на самом деле это пустой рецепт, поэтому бежать нечего. Функция

$(shell) оценивается при разборе рецепта Makefile, а ее вывод рассматривается как содержимое рецепта. Бывает, что этот оператор генерирует выходной файл как побочный продукт, но вывод оператора пустой, поэтому make не имеет ничего общего и делает вывод, что цель актуальна. На самом деле, всегда будет так, если рецепт окажется пустым:

$ ls
Makefile  foo.bar
$ cat Makefile
test.txt: foo.bar
        $(info Making $@ from $<)
$ make
Making test.txt from foo.bar
make: 'test.txt' is up to date.
$ ls
Makefile  foo.bar

Обратите внимание, что в приведенном выше примере не было создано test.txt, make только что пришел к выводу, что он выполнил (пустой) рецепт для обновите его, так что теперь он актуален.

Для правильной работы, вы должны вообще отказаться от функции $(shell). make рецепты уже вызываются в оболочке:

$ cat Makefile
test.txt: foo.bar
        grep ^hello $< >$@
$ make
grep ^hello foo.bar >test.txt
$ make
make: 'test.txt' is up to date.
$ make -B
grep ^hello foo.bar >test.txt
$ ls
Makefile  foo.bar  test.txt
...