学习周报2104-01-01:Makefile教程学习

本文详述了Makefile的学习要点,包括规则的结构、简单Makefile示例、处理流程、变量简化、隐式规则以及清理目录的规则。通过实例解析,展示了如何利用Makefile管理编译过程,提升开发效率。
摘要由CSDN通过智能技术生成

官方学习材料

2.1 What a Rule Looks Like

我们需要一个文件来告诉make去做什么、怎么做。一般来说,Makefile文件是要告诉make怎样编译和链接文件 。它的一般格式如下:

#Sample
target … : prerequisites …
        recipe
        …
        …
  • target:通常是可执行文件或者目标文件的文件名,或者说是要执行的操作名称,比如说‘clean’
  • prerequisite: file that is used as input to create the target,根据理解,应是可执行文件、目标文件包含或者操作需要执行的其他文件名,比如,目标文件main.o中包含了defs.h,那么defs.h就还要在这个位置出现
  • recipe:这里写的内容就是你想让make做的操作,这里可能是很长一串操作,那一一列出就好。

2.2 A Simple Makefile

这里直接粘贴复制了官方文档给出的例子,在这个例子中所有的C文件中都包含了defs.h,但是只有那些定义了编辑命令的命令才包含command.h,并且只有编辑器缓冲区的低级文件包括buffer.h文件[这段直译官方文档]。

edit : main.o kbd.o command.o display.o \
       insert.o search.o files.o utils.o
        cc -o edit main.o kbd.o command.o display.o \
                   insert.o search.o files.o utils.o

main.o : main.c defs.h
        cc -c main.c
kbd.o : kbd.c defs.h command.h
        cc -c kbd.c
command.o : command.c defs.h command.h
        cc -c command.c
display.o : display.c defs.h buffer.h
        cc -c display.c
insert.o : insert.c defs.h buffer.h
        cc -c insert.c
search.o : search.c defs.h buffer.h
        cc -c search.c
files.o : files.c defs.h buffer.h command.h
        cc -c files.c
utils.o : utils.c defs.h
        cc -c utils.c
clean :
        rm edit main.o kbd.o command.o display.o \
           insert.o search.o files.o utils.o

使用上述的makefile文件创建一个名为edit的可执行文件,只需要执行make 操作;如果要用Makefile文件从内存中删除可执行文件及目标文件,只要执行make clean即可。
在上面的样例Makefile文件中方,目标中包含了可执行文件edit,目标文件main.o,kbd.o;prerequisite是main.c、defs.h等。其实每一个.o文件都同时是目标和先决条件。recipes包括了cc -c main.ccc -c kbd.c
当目标是文件而不是操作时,如果任何prerequisite中的内容发生变化,那么都需要重新编译或者说是重新链接它。应自动更新本身自动生成的任何prerequisite。在上述例子中,target依赖于所有的8个目标文件,而目标文件main.o依赖于源文件main.c和头文件defs.h.

会在包含target、prerequisite后的每一行写上recipe,这些recipe说明,额怎样更新目标文件,注意,制表符必须出现在每一行recipe的开头。(注意make是不知道recipe到底是如何工作的,他只会根据你提供的recipe来更新目标文件);

而例子中的clean不是文件,它是一个操作.但是这个操作一般不会是其他arget的pererquiste,所以除了make特别说明,一般不使用clean`作为其先决条件。

2.3 How make Processes a Makefile

默认情况下,make从第一个target开始(而不是名字以’ . '开头的target)。这被称为默认目标。(其目的是让make不断的更新目标。
在2.2的例子中,默认目标是去更新可执行文件edit,因此,当我们执行make命令的时候,make读取当前目录中的makefile,并从处理第一条规则开始。在2.2的例子中,该规则用于重新链接edit;但是在make能够完全处理该规则之前,它必须处理编辑所依赖的文件的规则,也就是例子中的.o文件。每个文件都根据自己的规则进行处理。

例子中的makefile中的规则是要更新所有的.o文件,但是更新.o文件需要通过编译它的源文件.c/.h文件来实现。如果源文件或者被声明为prerequisite的头文件目标文件.o出现的晚或者说是目标文件不存在,那么则必须进行重新编译。

处理上述这些.o文件(也就是上文中所说的makefile文件中的规则)是因为它们target(例子中的edit)的prerequisite(例子中的一串.o文件)。如果说target(例子中的edit部分)不依赖于任何文件,也就是说prerequisites 部分为空。除非你告诉make需要做什么操作,否则make不会处理这样的规则。

在重新编译目标文件之前,make会考虑更新它的prerequisite,即源文件和头文件。这个makefile没有指定要为它们做什么(’.c’和‘.h '文件不是任何规则的target),因此make对这些文件不起作用。但是make此时会根据它们自己的规则更新自动生成的C程序,例如Bison或Yacc生成的程序.

在重新编译了它所需要的目标文件之后,make将决定是否链接到target也就是例子中的edit。如果文件edit不存在,或者任何目标文件被更新了,则make就必须要链接到edit

比如说,如果我们更改insert.c文件并执行了make命令, make将编译该文件以更新insert.o,然后链接到文件edit。如果我们更改文件command.h并运行make, make将重新编译目标文件kbd.o,command.ofile.o然后再链接到文件edit

2.4 Variables Make Makefiles Simpler

在2.2的例子中,edit的规则必须列出所有的目标文件两次。

edit : main.o kbd.o command.o display.o \ 
              insert.o search.o files.o utils.o 
        cc -o edit main.o kbd.o command.o display.o \ 
                   insert.o search.o files.o utils.o 

这样其实很容易出错。如果说一个新的目标文件被加入到系统中,那我们其实很难保证自己在每一个相应的地方都添加了该目标文件。(这其实与我们在C编程中添加常量类似,比如说我们在添加了一个在很多文件中都会用到的常量PI=3.14,那么如果我们在每一个地使用到PI的地方都定义了PI并且赋值为3.14,。一旦我们想要将PI的值该为3.14159,那单单对PI值的修改就是一个复杂的工作。那么C中是如何避免这样的麻烦的呢——宏定义)。在这里同样的,通过使用一个变量来消除上述风险并简化makefile。变量允许定义一次文本字符串,然后在多个地方替换(参见如何使用变量)。

objects = main.o kbd.o command.o display.o \ 
          insert.o search.o files.o utils.o 

通过使用变量,我们就可以使用$(objects)来替代上面一长串的文件名,简化makefile文件。

objects = main.o kbd.o command.o display.o \ 
          insert.o search.o files.o utils.o 
 
edit : $(objects) 
        cc -o edit $(objects) 
main.o : main.c defs.h 
        cc -c main.c 
kbd.o : kbd.c defs.h command.h 
        cc -c kbd.c 
command.o : command.c defs.h command.h 
        cc -c command.c 
display.o : display.c defs.h buffer.h 
        cc -c display.c 
insert.o : insert.c defs.h buffer.h 
        cc -c insert.c 
search.o : search.c defs.h buffer.h 
        cc -c search.c 
files.o : files.c defs.h buffer.h command.h 
        cc -c files.c 
utils.o : utils.c defs.h 
        cc -c utils.c 
clean : 
        rm edit $(objects)

2.5 Letting make Deduce the Recipes

没有必要在makefile中详细说明编译单个C源文件的方法,因为make可以通过其隐式规则找到它,make有一个隐式规则用于根据“.c" 文件来更新它的“.o”文件,这个隐式规则一般是使用cc -c命令。例如,它将会使用cc -c main.c -o main.o命令将main.c编译为main.o文件。
当一个“.c”文件被自动的以上述方式编译,它也将会自动的被加入到prerequisite的list中。我们可以像在recipe中省略这样的“.c”文件一样,在prerequisite中也说省略它。

objects = main.o kbd.o command.o display.o \ 
          insert.o search.o files.o utils.o 
edit : $(objects) 
        cc -o edit $(objects) 
main.o : defs.h 
kbd.o : defs.h command.h 
command.o : defs.h command.h 
display.o : defs.h buffer.h 
insert.o : defs.h buffer.h 
search.o : defs.h buffer.h 
files.o : defs.h buffer.h command.h 
utils.o : defs.h 
.PHONY : clean 
clean : 
        rm edit $(objects) 

上面的例子也是在实际中编写makefile的方式。

2.6 Another Style of Makefile

当只通过隐式规则创建makefile对象时,可以使用另一种样式的makefile。在这种风格的makefile中,可以根据条目的先决条件而不是目标对条目进行分组。

objects = main.o kbd.o command.o display.o \ 
          insert.o search.o files.o utils.o 
edit : $(objects) 
        cc -o edit $(objects) 
$(objects) : defs.h 
kbd.o command.o files.o : command.h 
display.o insert.o search.o files.o : buffer.h

在这个例子中,defs.h是所有目标文件的prerequisite;command.h和buffer.h是为它们特定目标文件的prerequisite列出的。

2.7 Rules for Cleaning the Directory

有点不太明白
下面的例子是,如何编写一个make规则来清理示例的编辑器edit

clean: 
        rm edit $(objects)

在实际情况中,我们可能希望以一种更复杂的方式编写规则,以处理未预料到的情况

.PHONY : clean 
clean : 
        -rm edit $(objects)

这可以防止make被一个叫做clean的实际文件搞混,并使它在rm出错的情况下继续运行
因为clean不是编辑的先决条件,所以如果我们给出不带参数的make命令,该规则将根本不会运行。为了让规则运行,我们必须键入make clean

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值