About GNU Make

Author Avatar
Tianqi Zhang 8月 04, 2018

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的文件,则伪target clean此时因为文件clean的存在而变成了一个真的target,而这个新的target没有依赖文件,那么文件clean永远都是最新的,并且比上游文件(没有)新,那么指令make clean永远不会执行。已知phony目标并非是由其它文件生成的实际文件,make 会跳过隐含规则搜索。这就是声明phony 目标会改善性能的原因,即使你并不担心实际文件存在与否。
  • 推荐的书写规则的方式是单target,多prerequirement;另一种方式固然可以少写,但是维护起来比较麻烦。
  • Makefile中第一个规则之后的所有以<tab>开头的行,make都会把其当作Shell命令,包括<tab>之后是’#’的行。

Reference

GNU make

GNU make 中文教程