转载

Makefile文件编写

源代码文件

main3.c

 1 #include <stdio.h>  2 #include "static_lib.h"  3 #include "fun.h"  4   5 int main(void){  6     int a=2,b=3;  7     printf("add:%d sub:%d mul:%d div:%d/n",add(a,b),sub(a,b),mul(a,b),div(a,b));  8     fun1();  9     return 0; 10 }

static_lib.h和

1 extern int add(int a,int b); 2 extern int sub(int a,int b); 3 extern int mul(int a,int b); 4 extern int div(int a,int b);

static_lib.c

 1 int add(int a,int b){  2     return a + b;  3 }  4   5 int sub(int a,int b){  6     return a - b;  7 }  8   9 int mul(int a,int b){ 10     return a * b; 11 } 12  13 int div(int a,int b){ 14     return a / b; 15 }

fun.h和

1 extern void fun1();

fun.c

1 #include <stdio.h> 2 void fun1(){ 3     printf("fun1 ..."); 4 }

其中stati_lib.c中的文件编译成静态库

正常编译

按照正常的编译方法,这个程序可以按如下顺序编译

Makefile文件编写

但是每次改了源代码之后都这样子编译显然是不明智的,所以需要编写一个Makefile规则文件

Makefile Base

Makefile的规则为

Makefile文件编写

其中target是目标文件或者动作

prerequisites是生成目标依赖的文件

command是规则执行的命令,如果命令与依赖规则在一行,则以';'分割,如果在另一行,则以tab开头

编写一个最简单的Makefile编译这些源码

 1 app3  : static_lib.a fun.o  2     gcc main3.c static_lib.a fun.o -o app3  3   4 fun.o :  5     gcc -c fun.c  6 static_lib.o :   7     gcc -c static_lib.c  8   9 static_lib.a : static_lib.o 10     ar rcs static_lib.a static_lib.o 11  12 clean : 13     rm static_lib.a static_lib.o fun.o app3

执行make clean可以将原来的清理掉

执行make会重新编译源码

Makefile文件编写

这样当我们修改源代码之后就可以简单的编译源码了

Makefile hidden

但上面的Makefile显然不够简洁,我们可以利用一些make的隐式规则,简写makefile,这些隐含规则可以通过 make -p 指令查看。

1 app3  : static_lib.a fun.o main3.o 2     gcc main3.o fun.o static_lib.a -o app3 3  4 static_lib.a : static_lib.o # 隐含会寻找*.c文件编译成*.o文件 5     ar rcs static_lib.a static_lib.o 6  7 clean : 8     rm *.a *.o app3

执行make可以看到依然能够编译成功

Makefile文件编写

其中cc是一个符号链接

Makefile文件编写

Makefile Var

还可以进一步使用一些变量,进一步提高Makefile的可维护性

 1 CC       = gcc  2 OBJS     = main3.o static_lib.a fun.o  3 GEN_OPTS = -o   4 app3  : $(OBJS)  5     $(CC) $(OBJS) $(GEN_OPTS) app3  6   7 static_lib.a : static_lib.o # 隐含会寻找*.c文件编译成*.o文件  8     ar rcs static_lib.a static_lib.o  9  10 clean : 11     rm *.a *.o app3

执行make

Makefile文件编写

而且可以看到 1,2,4行的gcc存在缩进,说明隐含规则也使用指明的CC变量编译。

Makefile autoVar

进一步的,我们可以使用一些自动化的变量。

 1 CC       = gcc  2 OBJS     = main3.o static_lib.a fun.o  3 GEN_OPTS = -o   4 app3  : $(OBJS)  5     $(CC) $(OBJS) $(GEN_OPTS) app3  6   7 static_lib.a : static_lib.o # 隐含会寻找*.c文件编译成*.o文件  8     ar rcs $@ $^  9  10 clean : 11     rm *.a *.o app3

其中自动化变量 $@表示规则中的目标文件集,$^表示依赖集,这个Makefile执行之后也能得到想要的结果

Makefile Fun

最后结合前面的变量,再结合函数,等写一个更完善的makefile,可以做到增加了新的c文件或h文件不需要修改Makefile文件,再次之前,首先将static_lib.* 移动到lib目录下,将其余源码文件移动到src目录。

Makefile文件编写

并修改main3.c的include为 ../lib/static_lib.h,修改Makefile文件如下

 1 CC       = gcc  2 SRC      = ./src  3 LIB      = ./lib  4 OBJS     = $(patsubst %.c, %.o, $(wildcard $(SRC)/*.c))  5 LIBS     = $(patsubst %.c, %.a, $(wildcard $(LIB)/*.c))  6 GEN_OPTS = -o   7 app3  : $(OBJS) $(LIBS)  8     $(CC) $(OBJS) $(LIBS) $(GEN_OPTS) app3  9     @echo "gen done" 10 # 将lib目录下的c文件编译成a库文件 11 $(LIBS) : $(patsubst %.c, %.o, $(wildcard $(LIB)/*.c)) 12     ar rcs $@ $^ 13  14 clean : 15     -rm $(SRC)/*.o $(LIB)/*.a app3 16     @echo clean done.

其中patsubst是一个函数,替换通配符,wildcard函数扩展通配符,展开目录下的所有匹配文件。

命令前面加'-'的话表示即便出错也继续执行。

Makefile文件编写

正文到此结束
Loading...