学习理解 makefile

学习理解 makefile

模拟个应用的例子:

有个工程包括头文件 001.h、002.h、003.h、004.h、005.h、006.h、007.h 共7个;程序文件 001.c、002.c、003.c、004.c、005.c、006.c、007.c、008.c、009.c、010.c 共10个文件。看着头大吧,先不关心具体内容。

现在来编译该工程。如下:

# cd example/

# gcc 001.c 002.c 003.c 004.c 005.c 006.c 007.c 008.c 009.c 010.c -o myresult

结果在编译完成后,一个奇思妙想猛然来袭,要是修改3个小文件,程序会有些改善。那就修改后重新编译。只是总共17个文件在仅仅修改了3个小文件的情况下需要统统地编译一次,这个不符合我们计算机领域的思维方式。由此我们选择另外的方式来编译这个工程。

我们首先编译生成目标文件,再连接成二进制文件。

# gcc -c 001.c

# gcc -c 002.c

# gcc -c 003.c

# gcc -c 004.c

# gcc -c 005.c

# gcc -c 006.c

# gcc -c 007.c

# gcc -c 008.c

# gcc -c 009.c

# gcc -c 010.c

# gcc 001.o 002.o 003.o 004.o 005.o 006.o 007.o 008.o 009.o 010.o -o myresult

如果修改了:001.c 002.c 003.c 三个文件。再次编译如下:

# gcc 001.c 002.c 003.c -c

# gcc 001.o 002.o 003.o 004.o 005.o 006.o 007.o 008.o 009.o 010.o -o myresult

可是如果涉及到头文件,影响就会更复杂,随着文件数量、编译时间的增加,对于源代码的修改,将会麻烦不尽。于是,对于编译一个工程,人们有些设想:对工程再次编译自动编译修改过的文件、涉及到头文件改动的文件。

编辑一个 makefile 文件。如下:

myresult:001.o 002.o 003.o 004.o 005.o 006.o 007.o 008.o 009.o 010.o

gcc -o myresult 001.o 002.o 003.o 004.o 005.o 006.o 007.o 008.o 009.o 010.o

001.o:001.c 003.h 004.h 007.h

gcc -c 001.c

002.o:002.c 001.h 002.h 003.h 006.h 007.h

gcc -c 002.c

003.o:003.c 002.h 004.h

gcc -c 003.c

004.o:004.c 006.h

gcc -o 004.c

005.o:005.c 006.h 007.h

gcc -o 005.c

006.o:006.c 004.h 005.h

gcc -c 006.c

007.o:007.c 001.h 002.h

gcc -c 007.c

008.o:008.c 001.h 002.h

gcc -c 008.c

009.o:009.c 001.h 002.h 006.h

gcc -c 009.c

010.o:010.c 001.h 002.h 005.h

gcc -c 010.c

clean:

rm *.o

rm myresult

把以上内容编辑在名字为“Makefile”的文件下,置于工程目录“example/”下。

# cd example/

# make

行首空白处为“tab制表符”,不能用空格;而且每次缩进都是“tab制表符”。

这个 Makefile 就解决了人们对于编译、再次编译的设想。带冒号的这里称作“条件行”,“tab键”缩进的这里称作“命令行”。当条件行里的文件发生改变的时候,就会执行相应下一行的命令行。第一次执行“make”、清除中间文件和目标文件后执行“make”命令后就会执行所有的命令行。在条件语句中,通过判断目标生成文件、条件文件的生成时间先后,决定要不要执行对应命令。

关于上面的 makefile 文件,我想大家要是一直在学习计算机(专指linux),就是不明白具体的执行内容、效果,也能看个差不多,对于这样的文档起码有个感觉,理解个大概。要是没有一点感觉的话,应该是不太适合这个事情的。对于学习这个语法仅仅是浏览一番,不必去记忆。有了感觉就自己加强一下,不强求。

在命令行和条件行会出现相同的内容(开始两行)。也就是说当工程里添加、删除某文件时,要在两行里添加相应的文件名;或者修改某个文件名称时,需要同时修改两行。这个时候人们想到了引入变量。

lastobject = 001.o 002.o 003.o 004.o 005.o 006.o 007.o 008.o 009.o 010.o

myresult:$(lastobject)

gcc -o myresult $(lastobject)

……

还可以参考:最简单的Makefile

GNU 的 make 很强大。可以自动推到文件以及文件依赖关系后面的命令。上面的 makefile 修改如下形式:

lastobject = 001.o 002.o 003.o 004.o 005.o 006.o 007.o 008.o 009.o 010.o

myresult:$(lastobject)

001.o:001.c 003.h 004.h 007.h

002.o:002.c 001.h 002.h 003.h 006.h 007.h

003.o:003.c 002.h 004.h

004.o:004.c 006.h

005.o:005.c 006.h 007.h

006.o:006.c 004.h 005.h

007.o:007.c 001.h 002.h

008.o:008.c 001.h 002.h

009.o:009.c 001.h 002.h 006.h

010.o:010.c 001.h 002.h 005.h

clean:

rm *.o

rm myresult

文件后面的“clean”是“编译程序”规则后,另外一个规则。前面的编译规则是个默认规则,因为在 “clean” 前面;那么最好不要把 “clean” 放在最前面。●在 makefile 中的 “#” 表示注视。

(到这里基本上就可以阅读文件了)

时间: 2024-10-02 02:48:28

学习理解 makefile的相关文章

【Linux学习】Makefile学习(二)

FatMouse' Trade Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 40975    Accepted Submission(s): 13563 Problem Description FatMouse prepared M pounds of cat food, ready to trade with the cats g

学习理解shell的好办法--编写自己的shell 之二

shell脚本的最简单形式就是一串命令的罗列,shell充当解释器,一条条挨个执行,直到最后一个或遇到退出命令.但这只能做很简单的事情,只是省区了每次都要敲一边命令的时间,要想完成更负责的功能,还要加上这些东西: 1.控制 前面的条件满足了,然后干什么:不满足,干什么. 2.变量 c=a+b, 用一种形式代表另一种形式,就是变量.因为形式不同了,就能用一种不变的表示另一种变化的.比如"编程语言"就可以当一个变量,可以赋值为"C语言","Perl语言&quo

Android中的context的学习理解

Android中Context的学习理解Context是一个抽象基类,通过它getResuources.getAssets and start 其他组件(Activity,Service,broadCast,getSystemService),可以这样理解:Context提供了一个运行环境for App, then app 可以访问资源,才能完成与其他组件,服务的交互,Context定义了一套基本的功能接口or一套规范 //todo

学习理解shell的好办法--编写自己的shell 之一

本文参考自<Unix/Linux编程实践教程>, 这是一本讲解unix系统编程的书,注重实践,理解难度不大,推荐大家阅读,敲完本书后,对于理解unix系统如何运作会有更深的视角,回过头再学习别的 Linux相关的东西时,感受非常不一样,这是一本可以提高"内功"的书.自己加了些很菜的解释,以便其他小白理解,大牛直接飘过吧,错误之处希望指正. shell是一个管理进程和运行程序的程序,用来人和机器交互 常用的shell如sh,bash,zsh,csh,ksh等都有三个主要功能:

深入学习理解java-ThreadLocal

导读 首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的.各个线程中访问的是不同的对象. 另外,说ThreadLocal使得各线程能够保持各自独立的一个对象,并不是通过ThreadLocal.set()来实现的,而是通过每个线程中的new 对象 的操作来创建的对象,每个线程创建一个,不是什么对象的拷贝或副本.通过ThreadLocal.set()将这个

学习写Makefile文件

Linux 环境下的程序员如果不会使用GNU make来构建和管理自己的工程,应该不能算是一个合格的专业程序员,至少不能称得上是 Unix程序员..在 Linux(unix )环境下使用GNU 的make工具能够比较容易的构建一个属于你自己的工程,整个工程的编译只需要一个命令就可以完成编译.连接以至于最后的执行.不过这需要我们投入一些时间去完成一个或者多个称之为Makefile 文件的编写. 那么问题出来了,Makefile究竟应该怎么编写? 下面看下面程序(Test.c): #include

思维探索者:理解了才是真正的学习 理解会带来巨大的好处

http://www.nowamagic.net/librarys/veda/detail/1718先说三件事情: 一个问题其实你可以一直放在脑子里面,利用暗时间对其软泡硬磨,时间足够久你总会有一点新的感悟,问题其实就像那句老话说的那样,不怕贼偷就怕贼惦记,聚精会神的思考一天,也许比不上惦记一个星期(据说数学家庞加莱就特别会惦记问题). 事实上,当你感觉懂了的时候,你至少得反问自己一句,真的懂了吗?当你确信自己真的懂了的时候,你至少得讲给别人听,别人听懂了吗?考察你自己是否真懂了的一个很好的依据

Source Xref 与 JavaDocs 学习理解

最近学习Mybatis的官方文档,看到了[项目文档]一节有很多内容没有见过,做个笔记,理解一下. 没找到java相关代码的解释,其实用下面这个php版本解释,也非常不错. What is SOURCEXref? SOURCEXref is a developer tool that’s designed to ease the process of working on large PHP projects by making it very fast and easy to browse th

30天自制OS笔记:2 汇编语言学习与Makefile入门

进一步提高代码的高级程度,在之前的代码基础上修改,所以先拷贝再重命名为helloos.nas: 感觉还是添加个git比较方便,等helloos3完成后添加个git,这样可以保留历史,而不用每次都被覆盖了. --------------------------------- 先回顾下昨天的程序结构: 只有显示部分,昨天看懂了,继续2016年9月7日18:37:10,说实话那个 因为只能提醒很麻烦,所以取消notepad++自动补全: ? ? 下面把对代码的注释添加上: 寄存器: ? ? X表示扩展