我正在使用以下代码:
HELLO_WORLD=hello
$(HELLO_WORLD): $(addsuffix .c,$@)
gcc $< -o $@
但是,当我运行代码时,出现以下错误,表示$ <不能算任何值:
gcc -o hello
gcc: fatal error: no input files
当我使用以下代码时...
HELLO_WORLD=hello
$(HELLO_WORLD): $(addsuffix .c,$@)
gcc $(addsuffix .c,$@) -o $@
... Makefile评估为以下命令...
gcc hello.c -o hello
...这正是我想要的。但是,我不想重复使用addsuffix。如果要更改先决条件,我想使用$ <。我将如何去做?
答案 0 :(得分:4)
问题不在于配方中$<
的扩展。问题是先决条件列表中$@
的扩展。
自动变量(例如$@
)仅在配方中定义,而在目标或先决条件列表中未定义。 GNU Make manual section on automatic variables中突出显示了此内容:
一个常见的错误是尝试在先决条件列表中使用
$@
;这是行不通的。
hello.c
实际上不在先决条件列表中这一事实并不妨碍您调用make hello
。这仅意味着make hello
将始终调用编译器,即使hello.c
未被修改。但这确实意味着$<
将与计算的先决条件列表一样空。
GNU make确实具有一项功能,可让您进行前提条件的第二扩展。手册中对此进行了说明。但是,更简单的解决方案是仅不依赖先决条件列表中的$@
。如果要创建自己的通用C编译配方,请对目标文件(.o
)目标使用模式规则。对于最终可执行文件,请列出最终可执行文件的所有先决条件(几乎可以肯定不止一个文件)。
通常,这是通过使用名称分别为SRCS
和OBJS
(如果您不介意键入元音,则分别使用SOURCES
和OBJECTS
)的变量来完成的。通常,您将目标文件作为最终可执行文件的先决条件(这将是链接操作),因为每个单独的源文件都有其自己的标头先决条件。
答案 1 :(得分:1)
基本问题是自动变量仅在配方中定义。因此,前提条件是未定义$ @。因为$ <将引用不依赖$ @的表达式,所以$ <也将不存在。
因此,实际上有两种方法可以解决此问题。第一种方法比较笨拙,但是可以使用辅助扩展。从本质上讲,这使我们无需添加太多代码即可做自己想做的事情。
HELLO_WORLD=hello
SECONDARYEXPANSION:
$(HELLO_WORLD): $(addsuffix .c,$$@)
gcc $< -o $@
更合适的方法是重组Makefile和使用模式规则。这为我们提供了构建任何C文件的通用方法。使用以下Makefile,我们可以运行“ make”或“ make hello”来生成可执行文件。
HELLO_WORLD=hello
all:
$(MAKE) $(HELLO_WORLD)
%: %.c
gcc $< -o $@