About GNU Make
Introduction
写自己的工程时,如果我们处在Windows环境下,VS一类的IDE会自动帮助我们解决脚本之间的依赖关系,但是如果我们处于类UNIX环境之下时,我们就需要自己手动设定文件之间的以来关系,make就是处理这类问题的一个工具。
要使用make,我们需要编写一个或者多个Makefile文件,Make file文件描述了整个工程的编译,链接等规则。为工程编写Makefile的好处就是可以使用一行命令来完成自动化编译,而不必一行一行地和编译器命令打交道。
make解释Makefile中的指令(规则)。在Makefile中可以使用系统shell所提供的任何命令来完成想要的工作,不少IDE底层采用make。
一些注意点
以后有空说不定会整理成完善的笔记
- 一个规则可以有多个命令行,每一条命令占一行,每一行命令必须以
<tab>
开始。 - Makefile中可以使用
\
来换行,但是\
之后不可以有空格。 - 当依赖关系流中任意上游文件总是要比下游文件更新时间晚的时候,make不做任何事情。
- 默认情况下,make执行的是Makefile中的第一个规则,此规则的第一个目标称为“最终目标”(即一个Makefile最终需要更新或者创建的目标)。其理论上应该是依赖关系流的最下游。除非明确指出必须执行,不然不是最终目标的Object不会被创建或者更新或者执行(例如clean)。
- 引用变量时大括号和小括号都可以,但是在规则的命令中,具体使用什么括号视平台而定
- make的隐含规则:如果生成的Object文件和源文件同名,则单独生成这一Object的规则(命令)可以省去
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
# '-rm'中的'-'意为忽视rm命令的执行错误
clean :
-rm edit $(objects)
.PHONY
目标是一个special target,只是在显式地声明target是一个伪target(phony意为虚假的)。此命令一般用于避免target名称与文件名冲突或者改善性能。例如上例中的clean
,如果项目目录中有一个叫clean
的文件,则伪targetclean
此时因为文件clean
的存在而变成了一个真的target,而这个新的target没有依赖文件,那么文件clean
永远都是最新的,并且比上游文件(没有)新,那么指令make clean
永远不会执行。已知phony目标并非是由其它文件生成的实际文件,make 会跳过隐含规则搜索。这就是声明phony 目标会改善性能的原因,即使你并不担心实际文件存在与否。- 推荐的书写规则的方式是单target,多prerequirement;另一种方式固然可以少写,但是维护起来比较麻烦。
- Makefile中第一个规则之后的所有以
<tab>
开头的行,make都会把其当作Shell命令,包括<tab>
之后是’#’的行。