入门Makefile
一:概述
Makefile是一个命令工具,是一个解释 makefile 中指令的命令
工具,一般来说,大多数的 IDE 都有这个命令,比如:Delphi 的 make,Visual C++的 nmake,
Linux 下 GNU 的 make。可见,makefile 都成为了一种在工程方面的编译方法。
是否具备Makefile编程也从侧面说明了一个人是否具备做项目的基本能力。
二:关于程序的编译和链接
在程序编译中,无论是在C或者C++,首先要把源文件编译成一个中间代码文件,在windows下也就是.obj文件。
UNIX下也是.o文件,即Object File,这个动作叫做编译,然后再把大量的Object File 合成执行文件。
这个动作叫做链接。编译时候,编译器需要的是语法的正确,函数与变量的声明正确,对于后者,通常是
你需要告诉编译器头文件的所在位置,(头文件中应该是声明,定义放在C/C++文件中)只要所有的语法正确,
编译器就可以编译出中间目标文件,一般来说,每个源文件都应该对应一个中间目标文件(.o或者OBJ文件)
链接的时候,主要链接函数和全局变量,所以我们要使用这些中间目标文件来连接我们的应用程序,链接器
不管函数所在的源文件,只管函数的中间目标文件(Object file)在大多数时候,由于源文件太多,编译生成
的中间目标文件太多,而在链接时需要明显地指出中间目标文件名,这对于编译很不方便,所以,我们要给中间目标文件
打个包,在 Windows 下这种包叫“库文件”(Library File),也就是 .lib 文件,在 UNIX
下,是 Archive File,也就是 .a 文件。
总结一下,源文件首先会生成中间目标文件,再由中间目标文件生成执行文件。在编译
时,编译器只检测程序语法,和函数、变量是否被声明。如果函数未被声明,编译器会给出
一个警告,但可以生成 Object File。而在链接程序时,链接器会在所有的 Object File 中
找寻函数的实现,如果找不到,那到就会报链接错误码(Linker Error),在 VC 下,这种错
误一般是:Link 2001 错误,意思说是说,链接器未能找到函数的实现。你需要指定函数的
Object File.
三:简单的Makefile
简单的Makefile语法格式:
方式1:
标签1:
指令1
标签2:
指令2
例:
all:
gcc main.c -o app
clean:
rm app
执行Makefile :
在工程目录下直接执行make 就会在当前路径下找对应的Makefile文件执行
如果当前路径有多个Makefile文件时,Make —f makefile文件名,来执行
对应的makefile文件。
例2:
目标 依赖
| |
app:main.o
gcc main.o -o app
main.o:main.s //这种写法的main.o叫目标 是要生成对应的main.o文件的
gcc -c main.s -o main.o
main.s:main.i
gcc -S main.i -o main.s
main.i:main.c
gcc -E main.c -o main.i
clean: //这种写法的clean 叫做伪目标,是不生成对应文件的
rm app main.o main.i main.s
在执行make的时候,makefile会自动推导依赖关系。
app->main.o->main.s->main.i->main.c
所以最终的顺序是:
gcc -E main.c -o main.i
gcc -S main.i -o main.s
gcc -c main.s -o main.o
gcc main.o -o app
这是最简单的makefile格式,已经实现了自动编译的流程,但是看起来可能很low,
所以我们可以用一些makefile中的变量去替换一下,让他们变得更加简洁。
四:Makefile中的变量
Makefile可以使用变量,让它变得更加精简。
使用的变量和方式基本和shell脚本一样。
如:
$() 引用变量。
Makefile中变量赋值的问题:
= :会将变量在Makefile中所有的赋值都找到
:将最后一次赋值的结果赋值给新的变量
.eg:
var=abc
var1=$(var)
var=def
#@表示取消命令执行的回显
all:
@echo $(var) #def
@echo $(var1) #def
:= :立即赋值
.eg:
var2:=abc
var3:=$(var2)
var2:=def
#@表示取消命令执行的回显
all:
@echo $(var2) #def
@echo $(var3) #abc
+= 附加赋值
var4=abc
var4+=def
all:
@echo $(var4) #abc def
?= 询问?前的变量之前是否被赋值过,如果被赋值过
本次赋值不成立,否者本次赋值成立
var5=www.hqyj.com
var5 ?=www.farsight.com
all:
@echo $(var5) #www.csdn.com
Makefile中的特殊变量:
$@ :目标文件
$^ :所有的依赖文件
$< :第一个依赖文件
Makefile中的通配符:
% :在makefile中代表任意长度的的字符。
* :在引用shell命令的时候代表shell中的通配符。
Makefile引用文件:
-include 路径/文件名
所以我们的Makefile根据特殊变量的优化版本就是:
OBJ=main.o func1.o func2.o func3.o
INCLUDE= -I ../include
CC=gcc
FLAG= -c -o
app:$(OBJ)
$(CC) $(OBJ) $(INCLUDE) -o $@
%.o%.cabs
$(CC)$^ $(INCLUDE) $(FLAG) =$@
clean:
rm $(OBJ)
rm $(OBJ)