makefile中target的重要性是什么?

时间:2016-09-01 10:10:42

标签: makefile

我正在学习如何在Linux发行版上创建makefile。 我正在使用以下代码(我知道它可以用小写形式编写,但长形式是有意的)来正确理解makefile的行为

test: test.o
        cc -o test test.o 
test.o: test.c
        cc -c test.c
clean:
        rm test.o

现在,当我在shell中使用makemake clean时,它们按预期工作。

但是,我想知道targetmakefile中的重要性。因此,首先将test.o: test.c行更改为test2.o: test.c并在shell中键入make;我最初的猜测是我的home目录中有一个名为test2.o的文件,但事实并非如此,我仍然看到test.o再次被创建。

所以,上述行为引出了我的问题,targetmakefile组件的重要性是什么?

4 个答案:

答案 0 :(得分:1)

'target'是Make检查以确定是否需要执行与目标关联的命令的文件。

即。如果您将test.o: test.c更改为test2.o: test.c,则会看到test2.o不存在,因此执行命令cc -c test.c - 它仍然只创建test.o。因此,如果重新运行make,您将看到编译器再次执行 ,因为test.o仍然不存在。

在原始版本test.o: test.c中,只有test.o不存在,或test.c的修改时间比{{1}更新时,才会执行编译器}。

答案 1 :(得分:1)

目标在命令部分中可用作变量$@,可用于定义构建的内容。

在你的makefile中你有:

test2.o: test.c
    cc -c test.c

因为您没有告诉编译器输出作为cc命令的一部分,它从test.o创建了test.c,这是默认行为。如果您运行cc -c file.c,默认情况下会生成file.o

您需要将目标文件指定为用于生成目标的命令的一部分,因此:

test2.o: test.c
    cc -c test.c -o $@

会使编译器适当地生成test2.o文件。

从根本上讲,makefile只不过是一组目标,目标的依赖关系以及用于制作这些目标的命令集。您必须确保作为构建过程的一部分,来自一组命令的最终产品是目标,以便具有正常运行的makefile。

编译器对在makefile中运行它的事实一无所知。

默认的make系统预先创建了一堆自动规则。这些包括从.o文件制作.c文件的规则 - 它知道它需要使用以下规则和命令编译文件:

%.o: %.c
#  commands to execute (built-in):
        $(COMPILE.c) $(OUTPUT_OPTION) $<

其中COMPILE.c

COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c

OUTPUT_OPTION是:

OUTPUT_OPTION = -o $@

CC默认为ccCFLAGS默认为空,CPPFLAGS默认为空,TARGET_ARCH默认为空。您可以使用make -p

查看这些定义

结果命令是:

cc -c -o $@ $<

其中$@是目标的名称,$<是依赖项列表中的第一项。此模式匹配名为<something>.o的所有目标文件,其中存在名为<something>.c现有文件。如果有test.o作为目标的请求,那么它将编译一个名为test.c的文件,因为该文件存在并符合这些规则。

答案 2 :(得分:0)

cc -c test.c的默认输出文件是test.o。如果您想要创建test2.o,则需要明确说明:

test2.o:test.c         cc -o test2.o -c test.c

ccmakefile或其正在运行的目标一无所知。

目标的重要性在于它们用于查找所有依赖项。因此,makefile中的第一条规则表明test依赖于test.o:在创建test之前,首先需要创建test.o,如果test.o }已更改,您需要重建test

目标下方的命令可以执行创建目标所需的任何操作。但是你必须明确地编写代码(尽管有一些宏可以自动将目标和依赖项替换到命令行中 - 当目标包含通配符模式时,这些宏非常有用)。

答案 3 :(得分:0)

<强> TL;博士

您的test2.o规则永远不会执行。 test.o由make的隐式规则创建。

让我们把它分开。

test.o: test.c
        cc -c test.c

这是规则

规则的一般语法是:

targets : prerequisites
        recipee

因此,test.o目标test.c先决条件

如果:

  • 目标(文件)不存在,或
  • (其中一个)先决条件是较新而不是目标,

执行 recipee (应该,但不必,创建目标)。

那么,让我们来看看你的Makefile:

test: test.o
        cc -o test test.o 
test.o: test.c
        cc -c test.c

当您说make test时,您想要创建目标test。此目标以test.o为先决条件。

对于test.o,存在另一条规则,其中test.c为先决条件。因此 规则首先检查并执行(编译源代码到目标代码),然后检查test先决条件,并在需要时运行recipee(将目标代码链接到可执行格式)

  

因此,首先将test.o: test.c行更改为test2.o: test.c并在shell中键入make;我最初的猜测是我的主目录中有一个名为test2.o的文件,但事实并非如此,我仍然看到test.o再次被创建。

没有目标具有test2.o先决条件,并且您没有要求具体构建(make test2.o),因此永远不会执行test2.o的配方。

test仍有test.o作为先决条件。由于Makefile中没有明确的该名称目标规则,make会将其替换为implicit rule,以便从现有.o文件创建.c文件。