刚开始用make的时候,以为makefile中名字叫做main的target就是make默认执行的target(中文翻译叫做标的(di,四声),下面统一称呼为标的),然后曾经很天真地犯过这样的错误,就一个.c文件(名字叫做main.c),功能是打印helloworld,然后我写了这样的makefile来编译:

main:
gcc -o main main.c

  结果第一次make命令能编译,后面如果还想再用make命令编译的话,就会出现这样的错误:

  

  即使更改了main.c中的代码,也会出现这样的错误。当时我一直想不通,为什么第一次能编译,后面编译就会报错呢,后来学习了一下makefile的语法,才知道makefile是这样定义的。

target ...: prerequisites
command
command

  target代表的是一个 标的,prerequisites代表的是这个标的所依赖的标的,下面那个command就是生成这个标的的命令。

  那么那个标的代表的是什么呢?其实它就是代表了一个与他同名的文件,编译之后生成的.o文件,编译链接之后生成的可执行文件或者其他任何类型的文件,例如main这个标的代表的就是main这个可执行文件。

  可能这样将有点晦涩,就拿我上面那个错误来举例,在上面那个例子中,执行make之后,它做的工作是这样的:

    1.查找makefile,默认执行第一个标的(即main)。

    2.检查main这个文件存不存在或者需不需要更新。

    3.如果main文件不存在,则执行下面那个gcc命令来生成这个文件。

    4.如果main文件已经存在,且它的修改时间要早于依赖文件的修改时间(即这个main文件过期了),那么执行下面的gcc命令来生成这个文件。

  看了上面那个步骤,大家应该就能理解为什么我上面会报错了吧,就是由于我那个main标的所依赖的文件为空,所以那个main文件永远不会过期,所以,每回执行make命令都会提示main is up to date.(意思是这个文件是最新的,不需要更新了)

  那么该怎么做才是对的呢,我们可以改成这种形式:

main: main.c
gcc -o main main.c

  这里给main这个标的添加了一个依赖,依赖于main.c这个文件,如果main.c这个文件的修改时间晚于main这个文件的修改时间,那么就执行下面的gcc命令来生成main这个文件。

  OK,分析完了这个,我们再来分析一下另一个经典的标的,clean,还是上面的栗子,我添加上clean的标的,就是删除生成的main这个可执行文件,如下所示:

main: main.c
gcc -o main main.c
clean:
rm main

  此时如果我运行了make clean命令,那么就会删除main这个可执行文件,那么这个标的的原理是什么呢?其实当我们运行了make clean命令之后,它的执行步骤是这样的:

  由于clean标的没有依赖的文件,所以它就是检查clean这个文件是否存在,如果不存在,那么执行clean标的下面的命令来生成clean文件。但是下面的rm命令又不会生成clean文件,所以导致的结果就是每回我们运行make clean命令,都会执行下面的rm命令。如下图所示:

  

  那么如果我们在当前目录下添加上一个clean文件会怎么样呢,就会出现下面的效果了:

  

  这次,clean标的下面的命令都不会被执行了。

  为了解决这种冲突,我们可以把clean定义成一个伪目标文件。具体如下:

  

  这样,即使当前目录下面存在clean这个文件,make clean命令也会照常执行,如下图所示:

  

  还有一点需要注意的是,clean标的的命令中,rm前面那个-号表示如果中途出错,则会忽略错误,继续执行。例如如果main.o,不存在,make clean会报错,但不会停止,如下图所示:

      

  OK,我想聊的makefile的内容就是这些,最后来总结一下吧。

  1.makefile中的每个标的都代表了一个文件。

  2.如果只运行make命令,那么默认执行第一个标的。

  3.执行一个标的时,会做两件事情:

    3.1.查看与这个标的同名的文件是否存在,如果不存在,那么就运行这个标的下面的命令。

    3.2.如果与这个标的同名的文件已经存在,那么就检查与这个标的同名的文件是否需要更新(即标的文件的修改时间是否早于依赖文件的修改时间),如果需要更新,那么就运行这个标的下面的命令。

makefile中的target到底代表什么?的更多相关文章

  1. Makefile中 的 phony target,empty target

    phony target Makefile的语法很简单 <target> : <prerequisites> [tab] <commands> 目标.先决条件.命令 ...

  2. makefile 中 $@ $^ %< 使用【转】

    转自:http://blog.csdn.net/kesaihao862/article/details/7332528 这篇文章介绍在LINUX下进行C语言编程所需要的基础知识.在这篇文章当中,我们将 ...

  3. makefile中一些符号的含义

    关于gnu make的详细介绍参看http://www.gnu.org/software/make/manual/make.html   规则 让我们先来粗略地看一看Makefile的规则. targ ...

  4. makefile 中 $@ $^ %< 使用

    这篇文章介绍在LINUX下进行C语言编程所需要的基础知识.在这篇文章当中,我们将会学到以下内容: 源程序编译 Makefile的编写 程序库的链接 程序的调试 头文件和系统求助 1.源程序的编译 在L ...

  5. Makefile中通过sed命令生成文件系统的selinux的配置文件vendor_filesystem_config.txt

    今天在编译android-O(8.0)的时候,我自己新增加了一个ext4格式的分区,在编译这个分区的时候,需要对应的生成文件系统的配置文件xxxx_filesystem_config.txt,发现了生 ...

  6. makefile中的wildcard和notdir和patsubst

    转自:https://blog.csdn.net/srw11/article/details/7516712 1.wildcard : 扩展通配符 2.notdir : 去除路径 3.patsubst ...

  7. .PHONY makefile中的伪目标

    我的理解: 拿clean举例,如果make完成后,自己另外定义一个名叫clean的文件,再执行make clean时,将不会执行rm命令. 为了避免出现这个问题,需要.PHONY: clean === ...

  8. 关于makefile中自动产生依赖的理解

    本博文是在学习了<GNU Make中文手册>后记录下来的自己的关于自动产生makefile依赖的语句的理解,向大家分享. <GNU make中文手册>中的相关章节见一下链接: ...

  9. Makefile中的$(@:_config=)什么意思?【转】

    本文转载自:https://blog.csdn.net/a8082649/article/details/24252093 已经编译出bin文件了,现在研究一下makefile,把遇到的问题记录下来: ...

随机推荐

  1. 怎么安装phpcms?PHPCMS V9安装图文教程

    Phpcms是国内领先的网站内容管理系统, 同时也是一个开源的PHP开发框架.PHPCMS V9目前已提供文章.图片.下载等内容模型,在此基础上可非常方便的扩展出信息.房产.交友.点评等功能.已有的模 ...

  2. java中使用正则表达式

    1.用正则表达式分割字符串 Pattern SPLIT2 = Pattern.compile("[,]"); String[] tmpStrings1 = SPLIT2.split ...

  3. dede如何按自己写的ID进行排序

    点评:dede排序问题:如何按自己写的ID排序,更改一下函数.即可轻松实现,下面有个具体的示例,大家可以参考下. 更改一下函数,实现排序方式根据自己写的ID排序就好了. 方法: 1.打开include ...

  4. Redis使用详细教程(转)

    一.Redis基础部分: 1.redis介绍与安装比mysql快10倍以上 *****************redis适用场合**************** 1.取最新N个数据的操作 2.排行榜应 ...

  5. POJ 2352 【树状数组】

    题意: 给了很多星星的坐标,星星的特征值是不比他自己本身高而且不在它右边的星星数. 给定的输入数据是按照y升序排序的,y相同的情况下按照x排列,x和y都是介于0和32000之间的整数.每个坐标最多有一 ...

  6. 分布式消息队列的使用kakfa

    作用: 1.系统解耦 2.通过消息可以减少系统的处理压力,做一个缓冲 3.原理基于生存者消费者的模式 4.两种场景:队列(端对端 一对一).主题(一对多,广播模式) 5.消息:header.body构 ...

  7. 读写ZIP文件

    String zipFile = /D:/+ ".zip";   StringOperator.zip(filePath, zipFile);   InputStream is = ...

  8. 在 angularjs 中集成 bootstrap typeahead

    问题 在使用 typeahead 的时候,有这样一个需求,当用户选中其中一项的之后,将项目对应的 id 保存到另外一个变量中,以后在提交表单的时候,将这个 id 发送到服务器中. 但是,在 typea ...

  9. Android 基础控件 TextView

    一TextView介绍: TextView是UI最基本的组件,使用TextView可以显示丰富的文本信息.设置添加TextView最常见的方法就是在xml中添加TextView元素,并指定属性.Tex ...

  10. python核心编程 第二天

    1.标准输入输出: import sys saveout=sys.stdout#保存当前输出状态 logfile=open('E://log.txt','r')# 打开文件 sys.stdout=lo ...