【问题标题】:What do these Makefile constructs mean?这些 Makefile 结构是什么意思?
【发布时间】:2009-01-29 20:24:38
【问题描述】:

谁能帮我找出下面的make文件?

BINS=file1 file2 file3

all: $(BINS)

clean: 
        rm -f $(BINS) *~ 

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

这是我的问题:

  1. gcc 的 -g 选项是什么?
  2. 什么是 $* 和 $@
  3. 它如何知道执行最后一个目标?

谢谢!

【问题讨论】:

  • 你应该给这个问题一个更好的名字。
  • 这是整个makefile吗? $* 作为目标很奇怪

标签: gcc makefile


【解决方案1】:

来自gccmake 文档:

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

  2. 一个。 "$* 与隐式规则匹配的词干(参见模式如何匹配)。如果目标是 dir/a.foo.b 并且目标模式是 a.%.b,那么词干就是 dir/foo。词干是用于构造相关文件的名称。在静态模式规则中,词干是与目标模式中的 '%' 匹配的文件名的一部分。"

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

    c。 “$?所有比目标新的先决条件的名称,它们之间有空格。” (未问,但值得添加。)

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

这个示例 makefile 有点受限,因为它似乎只构建 C 程序。 GNU make 有几个更广泛的示例,可用于学习如何编写 makefile。

【讨论】:

    【解决方案2】:

    1.) gcc的-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 是否有效,但我懒得实际尝试。你有吗?
    • 是的,我做到了,它不起作用 :) 它确实有效,但使用默认规则而不是 gcc -g。
    【解决方案3】:

    【讨论】:

    • RTFM 并不是一个真正有用的答案。
    • 这样的技术文档可能非常不透明。通过文档学习 make 的基础知识是我能想到的最难的方法。
    • 克里斯从阅读手册以了解他的几个基本问​​题的答案所获得的好处远远超过了在 SO 中复制这些手册中的内容的任何理由
    • 这就是我讨厌来这个网站的原因...Google 很难找到像 $* 或 $@ 这样的特殊字符。而且我没有太多时间花在阅读手册上。
    • @chrisdirulli 但我给了你资源,一旦在这些页面上,搜索这些字符很容易。
    【解决方案4】:

    第一行正如你所期望的那样——它创建了一个名称列表并将其分配给BIN。接下来,定义了一个名为all 的make 目标,它依赖于$BIN 中列出的目标(直到$BIN 中的每个目标都构建完毕,才能构建all)。 all 是一个特殊的构建目标;如果您只运行make 而不是make clean,则会自动构建all 目标。没有与all 关联的实际命令——它只是确保构建其所有依赖项。最后一个相当简单的命令定义了一个名为clean 的构建目标,它删除了$BIN 中列出的每个文件(注意$BIN 被用作构建目标列表和此makefile 中的文件列表)和所有备份。

    接下来,我们得到一条基本上是魔法的线。 $* 是一个特殊的构建目标,意思是“任何未明确定义的东西”。当make 尝试构建all 时,它会找到目标并开始处理其依赖项。但是当它尝试构建file1 时,没有明确定义目标。相反,它使用$* 来构建file1。同样,$@ 被替换为构建目标的名称,$? 被替换为它的依赖项(有点;你最好查看手册)。当make 去构建file1 时,$* 规则使其表现得就像定义了以下规则一样:

    file1: file1.c
            gcc -g -o file1 file1.c
    

    最后,-g 选项只允许编译调试信息。

    【讨论】:

    • $* 不是一个特殊的构建目标,它根本不是一个目标。
    【解决方案5】:

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

    Make 总是执行第一个目标,除非您指定了不同的目标。这也称为默认目标。通常默认目标称为“all”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-09
      • 2021-02-15
      • 2019-02-20
      • 2011-01-10
      相关资源
      最近更新 更多