这些Makefile结构是什么意思?

4

有人能帮我解决下面的makefile问题吗?

BINS=file1 file2 file3

all: $(BINS)

clean: 
        rm -f $(BINS) *~ 

$*: $@.c
        gcc -g -o $@ $?

以下是我的问题:

  1. -g选项在gcc中是什么意思?
  2. $*和$@分别代表什么?
  3. 它如何知道执行最后一个目标?

谢谢!


你应该给这个问题起一个更好的名字。 - Dana Robinson
这是整个Makefile吗?将$*作为目标看起来相当奇怪。 - Quassnoi
5个回答

5

来自gccmake文档:

  1. "-g 以操作系统的本机格式生成调试信息"。

  2. a. "$* 隐式规则匹配的词干(请参见模式匹配)。如果目标是dir/a.foo.b,目标模式是a.%.b,则词干为dir/foo。词干有助于构建相关文件的名称。在静态模式规则中,词干是与目标模式中的“%”匹配的文件名的一部分。"

    b. "$@ 规则目标的文件名。如果目标是存档成员,则“$@”是存档文件的名称。在具有多个目标的模式规则中(请参见模式规则介绍),“$@”是导致运行规则命令的任何目标的名称。

    c. "$? 所有比目标新的先决条件的名称,它们之间用空格隔开。"(未被要求,但值得添加。)

  3. "'all' 编译整个程序。这应该是默认目标。"

这个示例makefile有点受限,因为它似乎只能构建C程序。 GNU make 有几个更全面的示例,对于学习如何编写makefile非常有用。


3

1.) gcc的-g选项是什么?

-g选项用于生成调试信息。

2.) $*和$@分别代表什么意思?

$*表示规则的主干。当您创建规则时,可以使用它来代表目标文件中的所有依赖项。

$@表示规则的目标文件名。当您创建规则时,可以使用它来代表目标文件。

%.ext: %.otherext
    ext2otherext --input $? --output $@ --logfile $*.log

如果规则试图从file.otherext制作file.ext,则日志将记录到file.log

$@是目标文件名(如上例中的file.ext)。

3.) 它如何知道执行最后一个目标?

这是一个谜。

$*用于中间文件:例如,当您尝试从%.c制作%.so时,您需要一个既不是目标也不是源的中间文件%.o。 您可以放置:

%.so: %.c
    gcc -fPIC -g -c -o $*.o $?
    ld -shared -o $@ $*.o

换句话说,在一个%.extension规则中,$*代表除了.extension之外的所有内容。
作为目标,$*没有意义。
您确定这个规则实际上在某个地方执行吗?当我尝试使用您的Makefile重新生成它时,它应用默认规则(cc -o)而不是gcc -g -o
您需要的规则似乎是:
%: %.c
    gcc -g -o $@ $?

我很好奇这个makefile能否正常工作,但实际上我太懒了不想去尝试。你试过吗? - Jon Ericson
是的,我试过了,但是不起作用 :) 它确实编译了,但是使用的是默认规则而不是 gcc -g。 - Quassnoi

1

1
RTFM并不是一个真正有帮助的答案。 - Jay Conrod
1
这类技术文档通常比较晦涩难懂。想通过文档学习 make 的基础知识是我能想到的最困难的途径之一。 - Jay Conrod
克里斯从阅读手册中学习答案以回答他的一些基础问题所获得的好处远远超过在SO上复制这些手册的内容的任何原因。 - nicerobot
这就是为什么我讨厌来这个网站...像 $* 或 $@ 这样的特殊字符很难在谷歌上搜索到。而且我没有太多时间去阅读手册。 - ChrisDiRulli
@chrisdirulli 但我已经给了你资源,一旦进入那些页面,查找这些字符就很容易了。 - nicerobot

1

第一行代码按照预期生成了一个名称列表,并将其赋值给BIN。接下来,定义了一个名为all的构建目标,它依赖于$BIN中列出的目标(在每个$BIN中的目标构建完成之前,无法构建all)。all是一个特殊的构建目标;如果你只运行make而不是像make clean那样运行,all目标会自动构建。all没有实际命令相关联——它只是确保构建所有它所依赖的内容。最后一个相当简单的命令定义了一个名为clean的构建目标,它会删除$BIN中列出的每个文件(请注意,在这个Makefile中,$BIN既用作构建目标列表,也用作文件列表)和所有备份。

接下来,我们要讲一个神奇的命令。 $* 是一种特殊的构建目标,意思是“任何未被明确定义的内容”。当make试图构建all时,它会找到该目标并开始工作。但当它尝试构建file1时,就没有明确的目标定义了。取而代之的是,它使用$*来构建file1。同样,$@将被构建目标的名称替换,$?将被其依赖项(这个需要查看手册)。因此,当make去构建file1时,$*规则使其表现得好像已定义以下规则:
file1: file1.c
        gcc -g -o file1 file1.c

最后,-g选项只是启用编译调试信息。

$* 不是一个特殊的构建目标,它根本不是一个目标。 - Quassnoi

0

Q1和Q2已经得到了广泛的回答,因此仅对Q3进行简要解释:

Make始终执行第一个目标,除非您指定了其他目标。这也被称为默认目标。通常,默认目标称为“all”。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接