Makefile Tutorial

Makefile Tutorial

Intro

Makefile是一种复杂的shell脚本,能够将重复性的、对相互关联的源文件进行编译的工作,进行自动化。

该教程将会帮助你学习makefile。

教程目标

  • 解释什么是Makefile
  • 解释一个Makefile如何被建立

什么是Makefile

Make是一种Unix工具,用于执行一个Makefile. Makefile包含shell命令,我们可以自由创建Makefile。在某个目录中含有Makefile时,我们就可以使用make命令执行它。如果某目录中有多个Makefile,在执行make命令之前必须确保我们处于正确的目录下。

make会追踪目标文件的最新更新时间,在目标文件依赖的源文件更新时,就需要重新生成目标文件。如果某个项目有许多源文件和头文件,对其中某个文件进行修改,同时其它文件对该文件有依赖,如果不使用makefile,你需要手动对所有文件进行重新编译,这是一个非常巨大的工程量。

Makefile也和具体的shell对应,可能在一种shell工具中有效的makefile在另一种shell工具的作用下就会失效。

Makefile包含一系列的rules(规则),这些规则告诉系统你到底想执行什么命令。大多数情况下,这些规则是编译一系列文件的命令。规则必须从第一列开始编写,分为2部分,第一行是dependency line(依赖行),第二行(s)是actions or commands(动作或命令),动作行(s)要有一个tab的缩进。

\[RULE: Dependency \space line \\ [tab] Action \space lines \]

依赖行由2部分组成,第一部分(冒号之前)是target files(目标文件),第二部分是source files(源文件)。之所以被称为一个依赖行,是因为第一部分的目标文件依赖第二部分的源文件,多个目标文件或多个源文件由空格分开。

\[Dependency \ line: Target files : Source files \]

在Makefile创建之后,可以使用make对一个项目进行编译或重新编译。make工具会读取Makefile的内容并创建一个依赖树,并采取一些必要的步骤。并不是makefile中所有的规则都要被执行,因为大多数重新编译时,不需要更新所有的依赖。如果在扫描依赖树时发现目标文件比源文件的更新时间旧,就会重新生成目标文件。

在上述的任何一个过程中发生错误,make都会停下来。

建立 Makefile

Makefile本质上就是一个文本文件,最终会被系统shell执行。

如果要向Makefile中添加注释,那么就以#开头。对Makefile的依赖树进行描述,添加创建者、更新时间,在规则复杂时,添加注释都是非常好的Makefile编写习惯。

首先在Makefile中创建一个规则,以依赖行开始,依赖行中的目标文件之间需要用空格分开,源文件也是一样。之后是一个冒号,冒号后面可以是源文件,源文件的顺序不重要。如果未定义任何源文件,则系统假定它将依赖于编译器或汇编程序源代码文件来构成目标文件(这被称为隐含依赖性)。

规则行Example:

# 最终生成的可执行文件total,是由main.o和total.o制作而成的
# 这就是一个规则行
total:main.o total.o

接下来就是命令行,命令行需要比规则行缩进一个tab,命令行(s)以命令自身执行的顺序列在规则行之下。

命令行Example:

# cc是编译器,-o用于创建可执行文件,total是最终可执行文件的名字,total由后面的两个.o文件制作而成。
# 这行的作用其实和我们在terminal中执行时没什么区别
[tab]cc -o total main.o total.o

当然命令行可以不止一行,因此可以用相同的方式在该行后面继续跟上命令行,这些命令行都属于同一个依赖行。

如果make在规则行之后遇到了第一个没有tab缩进的语句或一个#sign,则认为这条规则已经结束。

可以使用\来使过长的命令行换行。

@常常出现在命令行的开始,这表示当该行执行时,不会在屏幕上回显该行的内容。

Makefile中常常使用宏来减少文字量,提高可读性。宏需要大写,然后跟个等号,之后是宏本身的内容,如:

DESTDIR=/home/ewan/software/src/xxx.c

如果需要使用宏,只需要$(宏名)${宏名}

宏也可以嵌套:

DESTDIR=/home/ewan/software/src/xxx.c
LIBDIRS=-L$(DESTDIR)/lib
# 上一句等同于下面的语句:
LIBDIRS=-L/home/ewan/software/src/xxx.c

我们也可以创建用于在编译和测试完成项目之后进行清除工作的规则

在下面的例子中,如果我们在terminal中运行了make clean,那么所有.o文件都会从当前目录删除掉。

clean:
	rm *.o

有了这些基础知识,再遇到Makefile就可以看懂了。需要注意的是,在真正的makefile中,除了这些基本概念,还有大量的bash/sh语法。

参考文献:
http://www.sis.pitt.edu/mbsclass/tutorial/advanced/makefile/

posted @ 2021-04-09 18:14  EwanHai  阅读(228)  评论(0编辑  收藏  举报