理解Makefile语法和变量

理解Makefile语法和变量,makefile,gnu-make,Makefile,Gnu Make,我正在读一个大的Makefile,其中一部分我不明白: $(IREJECTION): $(IREJECTION:%$(MACH64).o=%.cpp) $(CPP) $(CPPDLIBOPTS) -c $(@:%$(MACH64).o=%.cpp) -o $@ 在这个脚本中(请注意,我删除了不必要的变量以避免冗长),下面是什么意思 $(IREJECTION:%%$(MACH64.o=%.cpp)(在第一行) $(@:%%(MACH64.o=%.cpp)?(在第二行) 还有,

我正在读一个大的Makefile,其中一部分我不明白:

$(IREJECTION): $(IREJECTION:%$(MACH64).o=%.cpp)
        $(CPP) $(CPPDLIBOPTS) -c $(@:%$(MACH64).o=%.cpp) -o $@
在这个脚本中(请注意,我删除了不必要的变量以避免冗长),下面是什么意思

  • $(IREJECTION:%%$(MACH64.o=%.cpp)
    (在第一行)
  • $(@:%%(MACH64.o=%.cpp)
    ?(在第二行)
还有,这种形式
A:B
是什么意思?例如:

 $(IREJECTION): $(IREJECTION:%$(MACH64).o=%.cpp)   #on the first line
 <---- A ---->  <------------ B --------------->   #first instance of A: B
                <--- A ----> <-------- B ------>   #second instance of A: B

请帮助我理解这一点。

A:B
意味着您添加了一个依赖于B的make目标A。这意味着当B被更改时,必须在A完成之前运行它。
您可以通过调用
生成一个

来使用目标A,我认为您得到了一个非常复杂的示例。里面有很多东西

规则/配方 将
bar
设置为
a.c b.c.c

在您的例子中,
$(IREJECTION:%%$(MACH64).o=%.cpp)
,它使用名为
IREJECTION
的变量,尝试在单词末尾找到
$(MACH64).o
(它也引用变量
MACH64
),并将其替换为
.cpp



自动变量
$@
称为自动变量。 它是对“目标”的引用



进一步阅读 我将一步一步地说:

假设您有一些对象文件
irejection.mach64.o
和源文件
irejection.cpp

要从源代码生成对象,通常需要编写一个规则smth,如

irejection.mach64.o : irejection.cpp # means target : dependencies
    $(CC) irejection.cpp -o $@ # $@ is a special variable - the target (output)
现在让我们假设
$(MACH64)
.MACH64
$(IREJECTION)
IREJECTION$(MACH64.o
,即
IREJECTION.MACH64.o

$(IREJECTION:%%(MACH64).o=%.cpp)
将扩展到
IREJECTION.cpp

$(@:%$(MACH64.o=%.cpp)
将扩展到相同的范围,因为
$@
$(IREJECTION)

本质上,给定具有体系结构扩展名的对象文件目标,将文件名重写为其源文件对应项

对我来说,似乎不必要地令人费解。更清洁的方式是smth,如:

%$(MACH64).o : %.cpp
    $(CC) -c $@ $<
%$(MACH64.o:%.cpp
$(CC)-c$@$<

%
是“通配符”,
$这些是子项插入/重写规则:。基本上
$(var:%.foo=%.bar)
意味着用
.foo
替换
var
的所有元素的扩展。bar
@Anycorn:我想你的意思是:用
.foo
替换
var
的所有元素的
.bar
扩展?我明白为什么会混淆,但不,是这样form@Anycorn:你是说,在
%$(MACH64).o=%.cpp
.cpp
文件是从
.o
文件生成的?依赖项是从目标(.o)文件生成的。我会写一个详细的答案。现在我明白了替换的意思。相反的方向有点奇怪,因为替换后生成的
cpp
文件可能不是要编译的实际文件(在磁盘上)。无论如何,为了使其工作,目标文件应该与源文件具有完全相同的前缀。@Nawaz replace thingy更多的是
将foo转换为bar
,而不是bar is foo`。更一般地说,模式规则需要存在一些公共根work@Nawaz顺便说一句,在编写规则命令时,总是使用TAB,否则会出现奇怪的错误。实际上,目标/依赖项部分是规则,shell命令是配方。一个目标可以出现在多个规则中,但这些规则最多只能有一个配方。
 foo := a.o b.o c.o
 bar := $(foo:%.o=%.c)
irejection.mach64.o : irejection.cpp # means target : dependencies
    $(CC) irejection.cpp -o $@ # $@ is a special variable - the target (output)
%$(MACH64).o : %.cpp
    $(CC) -c $@ $<