背景
在windows,linux,macOS三个平台上都写过代码,但是使用不同平台的不同IDE,当代码转移到另一个平台时,编译却很麻烦。例如我在macos上用xcode写的代码,在ubuntu上用qt打开工程后,就无法直接编译使用。因此,使用makefile这个比较通用的方式,可以很好的解决这个问题。
自己的第一个makefile文件
之前使用别人开源的代码,通常都提供了makefile活cmakelists文件,在本地最多只需做细微修改,还未对自己的代码写过makefile文件。
首先编译器会将C或C++代码编译成中间代码文件,windows上是.obj文件,unix和linux下未.o文件,即Object File,这个动作叫做编译(compile),然后再把大量的Object File合成执行文件,这个动作叫链接(link)。如果给这些中间文件打包,就成了我们所熟知的库文件(Library File),即.lib或.a文件(windows和linux)。
使用make指令时,makefile文件则负责告诉make指令如何编译和链接程序。一个工程makefile的规则是:
- 如果这个工程没被编译过,则所有的源文件都需要被编译并被链接。
- 如果这个工程的某几个源文件被修改过,则只编译被修改过的源文件,并链接目标程序。
- 如果这个工程的头文件被修改了,则需要编译引用了这几个头文件的源文件,并链接目标程序。
makefile规则
makefile主要规则如下:如果prerequisite中的文件有比target文件要新的,则执行command指令。
target ... : prerequisite ...
command
...
...
target
可以是一个object file(目标文件)或可执行文件,还可以是一个标签(label)。
prerequisite
生成target所依赖的文件或target
command
该target要执行的命令(任意的shell命令)
上图是源文件与其头文件,这里为求方便将源文件与头文件均放在了一个文件夹下。那么我们的makefile文件就可以写成如下:
objects = main.o algorithm.o AVL.o binNode.o BinTree.o BST.o graph.o\
list.o listNode.o math.o queue.o RedBlack.o stack.o tools.o vector.o
main : $(objects)
g++ -o main $(object)
AVL.o : BST.hpp
binNode.o : queue.hpp
BinTree.o : queue.hpp binNode.hpp
BST.o : BinTree.hpp
graph.o : vector.h queue.hpp stack.hpp
list.o : listNode.hpp
queue.o : list.hpp
RedBlack.o : BST.hpp
stack.o : vector.h
vector.o : math.h algorithm.hpp
.PHONY : clean
clean :
-rm main $(objects)
常见错误:
Makefile missing separator.stop:makefile中的指令是以tab开头,很多编辑器中对于tab会自动转换成四个空格,造成makefile文件报错:makefile missing separator.stop.
当遇到makefile的这个错误时,注意查看指令开头是否时tab。
make: *** No rule to make target `all'. Stop:当使用make all指令时,makefile中没有all标签。