首页 > 代码库 > 学习写Makefile文件
学习写Makefile文件
Linux 环境下的程序员如果不会使用GNU make来构建和管理自己的工程,应该不能算是一个合格的专业程序员,至少不能称得上是 Unix程序员。。在 Linux(unix )环境下使用GNU 的make工具能够比较容易的构建一个属于你自己的工程,整个工程的编译只需要一个命令就可以完成编译、连接以至于最后的执行。不过这需要我们投入一些时间去完成一个或者多个称之为Makefile 文件的编写。
那么问题出来了,Makefile究竟应该怎么编写?
下面看下面程序(Test.c):
#include <stdio.h> int main(int argc,char *argv[]) { printf("hello world\n"); return 0; }初学者很多都直接在命令行编译链接:gcc–o Test Test.c
因此他们觉得用不用Makefile无所谓。其实不然,我们看下面程序:
程序有三个文件:Test.c、add.h 、add.c
Test.c 文件
#include <stdio.h> #include"add.h" int main(int argc,char *argv[]) { printf("%d \n",add(1,2)); return 0; }
add.h 文件
#ifndef ADD_H_ #define ADD_H_ int add(int a,int b); #endif /* ADD_H_ */
add.c 文件
int add(inta,intb) { return a+b; }
此时,如果你再用命令去编译链接时候就显得比较麻烦了,如果代码文件更多呢?那就不可想象了,因此我们要学会写Makefile文件。
Makefile是一个文件文件形式的脚本文件,其中包含一些规则告诉make编译哪些文件怎么编译以及在什么条件下编译。
让我们先来粗略地看一看Makefile的规则。[
target:dependency
command
...
目标:依赖
执行指令 ...
注意每个command 第一个字符必须是tab键,而不是4个空格。不然的话make会报错停止。执行的时候make空格后接目标,当然也可以不输入目标。这时make就会默认只执行第一个目标。
下面就由简单到复杂编写Makefile文件:
1.写一个最简单的Makefile
start: gcc –o test Test.c
在命令输入make回车即可完成编译和链接。
2..将编译和链接分开
start:Test.o gcc -o Test Test.o Test.o:Test.c gcc -o Test.o -c Test.c
这里出现两个目标(target)start,和Test.o如果在make时候没有加上目标的话,其只会执行第一个目标,除非有依赖才执行下面的(如2)。这里当你在命令行中输入make后面没有更任何参数时候其会从start开始执行,发现其依赖Test.o文件,其就往下找,就会执行Test.o这个目标。
当然这里可以make Test.o ,就不会执行第一个目标了。
3.引入变量
CC = gcc SRCS = Test.c OBJS = Test.o EXEC = Test start:$(OBJS) $(CC) -o $(EXEC) $(OBJS) $(OBJS):$(SRCS) $(CC) -o $(OBJS) -c$(SRCS)
为什么要引入变量CC,SRCS等(变量习惯使用大写),后面在使用变量的时候要这样写:$(变量名)。引入变量的原因,主要是方便修改,比如要换编译器,要换文件等比较方便。
4.进一步完善
CC = gcc SRCS = Test.c OBJS = $(SRCS:.c=.o) EXEC = Test start:$(OBJS) $(CC) -o $(EXEC) $(OBJS) $(OBJS): $(CC) -o $(OBJS) -c$(SRCS) clean: rm -f $(OBJS)
OBJS = $(SRCS:.c=.o) 这句话意思是把SRSC字符中.c替换成.o
5.再完善
.SUFFIXES:.c .o CC = gcc SRCS = Test.c OBJS = $(SRCS:.c=.o) EXEC = Test start:$(OBJS) $(CC) -o $(EXEC) $(OBJS) .c.o: $(CC) -o $@ -c $< clean: rm -f $(OBJS)
.SUFFIXES:.c .o 表示任何x.c 和x.o相关联如果这里使用是cpp文件则改为:.SUFFIXES:.cpp .o (注意cpp和.o之间有个空格)
OBJS = $(SRCS:.cpp=.o)
$@和$<是make预定义的变量。$@为规则目标所对应的文件名,$<规则中第一个相关的文件名(这里可以理解为.c文件)。
6.如果有多个.c或者.cpp文件怎么办?Test..c 和add.c 文件存在。
.SUFFIXES:.c .o CC = gcc SRCS = Test.c add.c OBJS = $(SRCS:.c=.o) EXEC = Test start:$(OBJS) $(CC) -o $(EXEC) $(OBJS) .c.o: $(CC) -o $@ -c $< clean: rm -f $(OBJS)
这里\ 相当于换行链接。三个可以写成这样
如果文件非常多也可以这样写,
.SUFFIXES:.c .o CC = gcc SRCS = $(shell ls *.c) OBJS = $(SRCS:.c=.o) EXEC = Test start:$(OBJS) $(CC) -o $(EXEC) $(OBJS) .c.o: $(CC) -o $@ -c $< clean: rm -f $(OBJS)
$(shell ls *.c) 表示使用shell 查找符合条件文件
执行结果:
学习写Makefile文件