Попытка использовать следующее правило Makefile не сработала (GNU Make 4.0):
foo: [email protected] other.o
bar: bar.o other.o
Файл foo.c
был скомпилирован (в foo.o
), но команда компоновки была cc -o .o
.
Напротив, bar
был скомпилирован и скомпонован правильно как cc bar.o other.o -o bar
.
Кто может объяснить разницу (или проблему)?
решение1
Это рассматривается в разделеАвтоматические переменныев руководстве GNU Make:
Очень важно, чтобы вы осознавали ограниченную область, в которой доступны значения автоматических переменных: они имеют значения только в пределах рецепта. В частности, вы не можете использовать их где-либо в целевом списке правила; они не имеют там значения и будут расширяться до пустой строки. Кроме того, к ним нельзя получить прямой доступ в списке предварительных условий правила. Распространенной ошибкой является попытка использовать
$@
в списке предварительных условий; это не сработает.
Остальная часть абзаца дает одно из возможных решений, хотя и специфичное для GNU Make:вторичное расширение. Написание вашего Makefile как
.SECONDEXPANSION:
foo: [email protected] other.o
bar: bar.o other.o
позволяет $$@
присвоить соответствующее значение, а затем
$ make foo
cc -c -o foo.o foo.c
cc -c -o other.o other.c
cc foo.o other.o -o foo
делает то, на что вы надеетесь.
(По моему опыту, обычно существуют лучшие способы решения проблемы, чем прибегать к вторичному расширению, но это можно определить, только понимая общую цель того, что вы пытаетесь сделать.)