【问题标题】:Makefile first rule targetMakefile 第一规则目标
【发布时间】:2014-03-31 16:18:30
【问题描述】:

我正在尝试仅使用三个文件来学习 make

foo.h

#ifndef __foo_H_
#define __foo_H_

void print();

#endif

foo.c

#include <stdio.h>
#include "foo.h"


void print()
{
    printf("Hello World !");
}

main.c

#include "foo.h"

int main()
{
    print();
    return 0;
}

当我使用以下 makefile 时,一切正常

制作文件

CC = gcc
CFLAGS = -I.
DEPS = foo.h
OBJ = foo.o main.o 

.PHONY: clean

main: $(OBJ)
        gcc -o $@ $^ $(CFLAGS)

%.o: %.c $(DEPS)
        $(CC) -c -o $@ $< $(CFLAGS)

clean:
        rm *.o

上面的工作是因为make 默认运行第一个目标(我基本上到处都读过)。

如果我使用下面的makefile

CC = gcc
CFLAGS = -I.
DEPS = foo.h
OBJ = foo.o main.o 

.PHONY: clean

clean:
        rm *.o

main: $(OBJ)
        gcc -o $@ $^ $(CFLAGS)

%.o: %.c $(DEPS)
        $(CC) -c -o $@ $< $(CFLAGS)

在上述 makefile 上调用 make 仅运行 make clean,因为默认情况下 make 运行第一条规则。

问题在于这个makefile

CC = gcc
CFLAGS = -I.
DEPS = foo.h
OBJ = foo.o main.o 

.PHONY: clean

%.o: %.c $(DEPS)
        $(CC) -c -o $@ $< $(CFLAGS)

main: $(OBJ)
        gcc -o $@ $^ $(CFLAGS)

clean:
        rm *.o

在上面的makefile中使用make我得到了

gcc -c -o foo.o foo.c -I.
gcc -c -o main.o main.c -I.
gcc -o main foo.o main.o -I.

为什么make 不只是构建.o 文件并停止,因为它是第一个目标,为什么它还要继续构建main?我在第一条规则中没有指定构建 main 的位置。

【问题讨论】:

  • 大概的规则是第一个特定的目标将被制作。像 %.o: %.c $(DEPS) 这样的隐式模式规则没有指定特定的目标。
  • @j_random_hacker 但是该模式不是有效目标吗?因此,如果我要使用仅使用上述模式构建目标文件的 makefile,那么 make 预计不会发生任何事情,这不是很奇怪吗?
  • @j_random_hacker 是的,如果我只指定模式,那么 make 会说“制作:*** 没有目标。停止。”
  • 隐式模式规则未指定目标。它只能匹配并因此应用于已经以其他方式指定的目标——通过“普通”目标规则,或在make 命令行上指定的目标,或作为依赖于其中之一。 (想象一下,如果你唯一的规则以 %.o: %.c $(DEPS) 开头——make 怎么知道用什么替换 %?应该用 yabbadabbadoo 替换它吗?)

标签: c++ c makefile


【解决方案1】:

“第一个目标”规则仅计算 显式 目标。它不计算隐式目标,例如后缀规则或模式规则。

考虑:make 如何确定它应该构建.o 文件?它应该构建哪些.o 文件?如何理解它应该在变量 OBJ 中构建变量,而不是任何其他变量?

【讨论】:

  • 但是该模式不能用作一个单一的衬垫来为所有.c 文件创建目标文件吗?
  • 该模式规则将应用于与%.o 匹配的所有请求/需要的目标,但该规则本身并未指定任何需要构建的显式目标。具体来说,make 不会去寻找要构建的目标。它只构建你告诉它构建的东西(以及它确定需要构建的东西)。
  • @Kartik Anand:不。那个模式说“如果你有一个 .c 并且你想构建一个 .o,你可以用这个食谱来做”。这是一个抽象的陈述。 Make 无法理解 all .c files 的含义。它永远不会(单独)查看目录中的所有文件并选择似乎与某种模式匹配的文件,然后构建它。 Make 只会构建您明确要求它构建的目标,无论是通过 makefile 中的明确目标还是从命令行(例如,make foo.o)。
  • 更具体地说,该模式可以用作为所有.c 文件创建目标文件的解决方案的一部分。但是您仍然需要明确说明您要构建哪些对象。
【解决方案2】:

我一直在寻找手册的一个很好的部分来指导您,但没有找到任何具体和具体的使用方法。据我所知,该问题的答案是模式规则不是目标,而默认目标必须是目标,正如其名称所示。

如果您使用的是静态模式规则(它确实定义了目标),那么您的期望几乎是正确的,因为 make 会选择第一个这样的文件并在这种情况下构建它(并非所有您可能期望的只是第一个)。

【讨论】:

  • 即使我也是这么想的,但我在任何地方都找不到明确的写法。
  • 如果您仔细阅读,您会注意到手册中明确地讨论了目标和规则,并谈到了默认目标、定义目标和定义模式规则。我相信这是手册最接近具体说明的方式。
猜你喜欢
  • 2021-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多