Makefile--基本规则(零)
【版权声明:转载请保留出处:周学伟:http://www.cnblogs.com/zxouxuewei/】
一般一个稍大的linux项目会有很多个源文件组成,最终的可执行程序也是由这许多个源文件编译链接而成的。编译是把一个.c或.cpp文件编译成中间代码.o文件,链接是就使用这些中间代码文件生成可执行文件。比如在当前项目目录下有如下源文件:
# ls
common.h debug.c debug.h ipc.c ipc.h main.c tags timer.c timer.h tools.c tools.h
#
以上源代码可以这样编译:
# gcc -o target_bin main.c debug.c ipc.c timer.c tools.c
如果之后修改了其中某一个文件(如tools.c),再执行一下上一行代码即可,但如果有成千上万个源文件这样编译肯定是不够合理的。此时我们可以按下面步骤来编译:
然后在命令行上执行命令:
# make
gcc -c main.c
gcc -c debug.c
gcc -c ipc.c
gcc -c timer.c
gcc -c tools.c
gcc -o target_bin main.o debug.o ipc.o timer.o tools.o
#
# ls
common.h common.h~ debug.c debug.h debug.o ipc.c ipc.h ipc.o main.c main.o Makefile Makefile~ tags target_bin timer.c timer.h timer.o tools.c tools.h tools.o
#
可见在该目录下生成了.o文件以及target_bin可执行文件。现在我们只需要执行一个make命令就可以完成所有编译工作,无需像之前一样手动执行所有动作,make命令会读取当前目录下的Makefile文件然后完成编译步骤。从编译过程输出到屏幕的内容看得到执行make命令之后所做的工作,其实就是我们之前手动执行的那些命令。现在来说一下什么是Makefile?
所谓Makefile我的理解其实就是由一组组编译规则组成的文件,每条规则格式大致为:
target ... : prerequisites ...
>---command
...
其中target是目标文件,可以为可执行文件、*.o文件或标签。Prerequisites是产生target所需要的源文件或*.o文件,可以是另一条规则的目标。commond是要产生该目标需要执行的操作系统命令,该命令必须以tab(文中以>---标示tab字符)开头,不可用空格代替。
说白了就是要产生target,需要依赖后面的prerequisites文件,然后执行commond来产生来得到target。这和我们之前手动执行每条编译命令是一样的,其实就是定义好一个依赖关系,我们把产生每个文件的依赖文件写好,最终自动执行编译命令。
比如在我们给出的Makefile例子中target_bin main.o等就是target,main.o debug.o ipc.o timer.o tools.o是target_bin的prerequisites,gcc -o target_bin main.o debug.o ipc.o timer.o tools.o就是commond,把所有的目标文件编译为最终的可执行文件target,而main.c common.h是main.o的prerequisites,其gcc -c main.c命令生成target所需要的main.o文件。
在该例子中,Makefile工作过程如下:
1. 首先查找第一条规则目标,第一条规则的目标称为缺省目标,只要缺省目标更新了就算完成任务了,其它工作都是为这个目的而做的。 该Makefile中第一条规则的目标target_bin,由于我们是第一次编译,target_bin文件还没生成,显然需要更新,但此时依赖文件main.o debug.o ipc.o timer.o tools.o都没有生成,所以需要先更新这些文件,然后才能更新target_bin。
2. 所以make会进一步查找以这些依赖文件main.o debug.o ipc.o timer.o tools.o为目标的规则。首先找main.o,该目标也没有生成,该目标依赖文件为main.c common.h,文件存在,所以执行规则命令gcc -c main.c,生成main.o。其他target_bin所需要的依赖文件也同样操作。
3. 最后执行gcc -o target_bin main.o debug.o ipc.o timer.o tools.o,更新target_bin。
在没有更改源代码的情况下,再次运行make:
# make
make: `target_bin' is up to date.
#
得到提示目标target_bin已经是最新的了。
如果修改文件main.c之后,再运行make:
# vim main.c
# make
gcc -c main.c
gcc -o target_bin main.o debug.o ipc.o timer.o tools.o
#
此时make会自动选择受影响的目标重新编译:
首先更新缺省目标,先检查target_bin是否需要更新,这需要检查其依赖文件main.o debug.o ipc.o timer.o tools.o是否需要更新。
其次发现main.o需要更新,因为main.o目标的依赖文件main.c最后修改时间比main.o晚,所以需要执行生成目标main.o的命令:gcc -c main.c更新main.o。
最后发现目标target_bin的依赖文件main.o有更新过,所以执行相应命令gcc -o target_bin main.o debug.o ipc.o timer.o tools.o更新target_bin。
总结下,执行一条规则步骤如下:
1. 先检查它的依赖文件,如果依赖文件需要更新,则执行以该文件为目标的的规则。如果没有该规则但找到文件,那么该依赖文件不需要更新。如果没有该规则也没有该文件,则报错退出。
2. 再检查该文件的目标,如果目标不存在或者目标存在但依赖文件修改时间比他要晚或某依赖文件已更新,那么执行该规则的命令。
由此可见,Makefile可以自动发现更新过的文件,自动重新生成目标,使用Makefile比自己手动编译比起来,不仅效率高,还减少了出错的可能性。
Makefile中有很多目标,我们可以编译其中一个指定目标,只需要在make命令后面带上目标名称即可。如果不指定编译目标的话make会编译缺省的目标,也就是第一个目标,在本文给出的Makefile第一个目标为target_bin。如果只修改了tools.c文件的话,我们可能只想看看我们的更改的源代码是否有语法错误而又不想重新编译这个工程的话可以执行如下命令:
# make tools.o
gcc -c tools.c
#
编译成功,这里又引出一个问题,如果继续执行同样的命令:
# make tools.o
make: `tools.o' is up to date.
#
我们先手动删掉tools.o文件再执行就可以了,怎么又是手动呢?我们要自动,要自动!!好吧,我们加一个目标来删除这些编译过程中产生的临时文件,该目标为clean。
我们在上面Makefile最后加上如下内容:
可见clean目标被执行到了,再执行make时make就会重新生成所有目标对应的文件,因为执行make clean时,那些文件被清除了。
clean目标应该存在与你的Makefile当中,它既可以方便你的二次编译,又可以保持的源文件的干净。该目标一般放在最后,不可放在最开头,否则会被当做缺省目标被执行,这很可能不是你的意愿。
最后总结一下,Makefile只是告诉了make命令如何来编译和链接程序,告诉make命令生成目标文件需要的文件,具体的编译链接工作是你的目标对应的命令在做。
给一个今天完整的makefile:
target_bin : main.o debug.o ipc.o timer.o tools.o
>---gcc -o target_bin main.o debug.o ipc.o timer.o tools.o main.o: main.c common.h
>---gcc -c main.c debug.o: debug.c debug.h common.h
>---gcc -c debug.c ipc.o: ipc.c ipc.h common.h
>---gcc -c ipc.c timer.o: timer.c timer.h common.h
>---gcc -c timer.c tools.o: tools.c tools.h common.h
>---gcc -c tools.c clean:
>---rm *.o target_bin
Makefile--基本规则(零)的更多相关文章
- [Erlang34]erlang.mk的源码阅读1-入门makefile
通过erlang.mk项目,掌握基本的makefile语法,可以自己定制makefile. 1. makefile 基本规则: 1. 所有的源文件没有被编译过,则对各个源文件进行编译并进行链接,生成最 ...
- makefile中重载与取消隐藏规则示例
学习<跟我一起写Makefile-陈皓>后一直不懂,如何重载或取消隐藏规则 为了博客版面整洁,何为隐藏规则,Makefile基本规则编写等基础支持请自行百度. 需要声明的是:这些知识可能在 ...
- 关于makefile的那些事儿
最近越来越感觉到,在linux下面身为一个程序员,不会makefile就不是一个合格的程序员,所以今天我们介绍下常用的makefile编写. 了解知识: 编译:把高级语言书写的代码转换为机器可识别的机 ...
- Makefile的使用
Makefile 使用 一.实验说明 课程说明 在先前的课程中,我们已经学习了 gcc 和 gdb 的使用.本节课程中,我们将介绍 Makefile 的使用.Makefile带来的好处就是--&quo ...
- linux C编程 Makefile的使用
Makefile的作用就是"自动化编译" 一.Makefile基本规则 下面给出几个简单实例: 第一步:分别用vim创建prog.c code.c code.h三个文件 prog. ...
- Makefile学习一
上次随着信号学习告一段落,也标志着linux系统编程相关的知识学完了,而学了这么多知识点,是需要用一个综合的项目来将其进行串起来的,这样学习的技术才会不那么空洞,所以接下来会以一个实际例子来综合运用下 ...
- gcc编译的四个阶段:预处理,编译,汇编,链接
1:gcc编译的四个阶段:预处理,编译,汇编,链接 #vi file.c #gcc -E file.c -o file.i//-E查看且预处理后停止编译,-o生成目标文件,-i表示已预处理 #gcc ...
- LINUX信息安全系统设计基础第二周学习总结
1 Linux命令 2 man命令 1.Terminal(终端) Linux 系统还提供了一个叫做终端模拟器的程序(Terminal),下面几个比较常见的终端模拟器,例如 gnome-terminal ...
- Linux 读书笔记 二
一.实验说明 1. 环境登录 无需密码自动登录,系统用户名shiyanlou,密码shiyanlou 若不小心登出后,直接刷新页面即可 2. 环境使用 完成实验后可以点击桌面上方的“实验截图”保存并分 ...
- Linux 下 make 命令 及 make 笔记
Linux 下 make 命令是系统管理员和程序员用的最频繁的命令之一.管理员用它通过命令行来编译和安装很多开源的工具,程序员用它来管理他们大型复杂的项目编译问题.本文我们将用一些实例来讨论 make ...
随机推荐
- 每日英语:Stressed at Work? Reflect on the Positive
Feeling the pinch of work stress in the evening? Before heading home for the night, take a moment to ...
- hdoj 1166 敌兵布阵 线段数和树状数组
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- cvs history,CVS中查询目录下所有文件的提交记录
我们习惯用eclipse svn中查看一个目录下,甚至整个工程下,所有的文件的变更列表:操作为:右键工程 -> Team -> Show History. 最近在使用CVS,eclipse ...
- 游戏开发tips之RTTI(1)
首先说明标题的含义,怎么感觉就和定义一种语言一样,需要有一个规约呢..... 标题定义如下:游戏开发tip之+内容+(总tips的第几篇) 扩展如下:内容(一,二,三.....) 新手可怜,大神每一句 ...
- Date函数基础知识整理
Date类型:1.Date.parse()接收一个表示日期的字符串参数,然后再根据这个字符串返回响应的日期的毫秒数:如:创建一个日期: <script> // var someDate=n ...
- nginx正向代理http(一)
nginx实现正向代理,下面以http为例说明: (1)nginx配置: server { listen 8080; resolver 114.114.114.114; access_log logs ...
- Java程序员应该了解的10个设计原则
引用: http://www.cnblogs.com/leehongee/archive/2012/03/18/2404760.html 面向对象设计原则是OOPS(Object-Oriented P ...
- sql 判断
sql server select expertId,mail= ( CASE mail WHEN '' THEN ' ' else mail end ) from Siemens.dbo.tblEx ...
- Intellij idea上传项目到github
操作前提 1.安装了 git for windows客户端 2.配置了rsa公钥 3.设置了邮箱和用户名 详情请看上一篇博客http://www.cnblogs.com/520playboy/p/66 ...
- Adnroid 反编译APK
http://blog.csdn.net/vipzjyno1/article/details/21039349 http://blog.csdn.net/zx19899891/article/deta ...