简体   繁体   English

自动变量无法在Makefile中正确扩展

[英]Automatic variable not expanding properly in Makefile

I am using the following code: 我正在使用以下代码:

HELLO_WORLD=hello

$(HELLO_WORLD): $(addsuffix .c,$@)
        gcc $< -o $@

However, when I run the code, I receive the following error, implying that $< is not evaluating to anything: 但是,当我运行代码时,收到以下错误,表示$ <不能算任何值:

gcc  -o hello
gcc: fatal error: no input files

When I use the following code... 当我使用以下代码时...

HELLO_WORLD=hello

$(HELLO_WORLD): $(addsuffix .c,$@)
        gcc $(addsuffix .c,$@) -o $@

...the Makefile evaluates to the following command... ... Makefile中的计算结果为下面的命令......

gcc hello.c -o hello

...which is precisely what I would like. ...这正是我想要的。 However, I do not want to use addsuffix twice. 但是,我不想重复使用addsuffix。 I would like to use $< in the event that I change the prerequisite. 我想用$ <在我改变的前提的事件。 How would I go about doing this? 我将如何去做呢?

The problem is not with the expansion of $< in the recipe. 问题不在于配方中$<的扩展。 The problem is the expansion of $@ in the prerequisite list. 问题是先决条件列表中的$@展开。

Automatic variables, such as $@ , are only defined in the recipe, not in the target or prerequisite lists. 自动变量(例如$@ )仅在配方中定义,而不在目标或先决条件列表中定义。 This is highlighted in the GNU Make manual section on automatic variables : 有关自动变量GNU Make手册部分中对此进行了突出显示:

A common mistake is attempting to use $@ within the prerequisites list; 一个常见的错误是尝试在先决条件列表中使用$@ this will not work. 这是行不通的。

The fact that hello.c is not actually in the prerequisite list does not prevent you from invoking make hello . 这一事实hello.c实际上不是先决条件列表不会阻止你调用make hello It just means that make hello will always invoke the compiler, even if hello.c has not been modified. 它只是意味着make hello总是会调用编译器,即使hello.c没有被修改。 But it does mean the $< will be as empty as the computed prerequisite list. 但这确实意味着$<将与计算的先决条件列表一样空。

GNU make does have a feature to let you do a second expansion of prerequisites; GNU make确实具有一项功能,可以让您扩展前提条件; this is explained in the manual. 手册中对此进行了说明。 But the simpler solution is to simply not rely on $@ in the prerequisite list. 但是,更简单的解决方案是仅不依赖先决条件列表中的$@ If you're trying to create your own generic C compile recipe, use a pattern rule for object file ( .o ) targets. 如果你想创建自己的通用的C编译配方,使用对象文件(图案规则.o )目标。 For the final executable, list all the prerequisites for the final executable (which will almost certainly be more than one file). 对于最终的可执行文件,列出了最终的可执行文件的所有先决条件(这几乎肯定会超过一个文件)。

Typically this is done using separate variable with names like SRCS and OBJS (or SOURCES and OBJECTS if you don't mind typing vowels). 这通常使用不同的变量,如姓名做SRCSOBJS (或SOURCESOBJECTS ,如果你不介意打字元音)。 Normally you make the object files prerequisites for the final executable (which will be a link operation), since each individual source file will have its own header prerequisites. 通常,您将目标文件作为最终可执行文件的先决条件(这将是链接操作),因为每个单独的源文件将具有其自己的标头先决条件。

The fundamental problem is automatic variables are only defined in the recipe. 根本问题是自动变量仅在配方中定义。 So, in the prerequisite, $@ is not defined. 因此,前提条件是未定义$ @。 Because $< will refer to an expression that depends on $@, which does not exist, $< will therefore not exist as well. 因为$ <将引用依赖于$ @的表达式,该表达式不存在,所以$ <也将不存在。

So, there are really two ways to resolve the issue. 因此,实际上有两种方法可以解决此问题。 The first way is a bit clunky, but you can use secondary expansions. 第一种方法比较笨拙,但是可以使用辅助扩展。 This essentially allows us to do what we want without adding much code... 从本质上讲,这使我们无需添加太多代码即可做自己想做的事情。

HELLO_WORLD=hello

SECONDARYEXPANSION:
$(HELLO_WORLD): $(addsuffix .c,$$@)
        gcc $< -o $@

The more proper way to do this involves restructuring the Makefile and using pattern rules. 执行此操作的更适当方法包括重组Makefile和使用模式规则。 This gives us a generic recipe for building any C file. 这为我们提供了构建任何C文件的通用方法。 With the following Makefile, we can either run "make" or "make hello" to build the executable. 使用以下Makefile,我们可以运行“ make”或“ make hello”来生成可执行文件。

HELLO_WORLD=hello

all:
        $(MAKE) $(HELLO_WORLD)

%: %.c
        gcc $< -o $@

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM