1、为什么用MakeFile?
一个多文件的工程例子:add/add_int.c add/add_float.c sub/sub_int.c sub/sub_float.c add.h sub.h main.c
add/add_int.c add/add_float.c add.h
/*add/add_float.c文件*/
#include <stdio.h> float add_float(float a,float b){ return a+b; } /*add/add_int.c文件*/ #include <stdio.h> int add_int(int a,int b){ return a+b; } /*add.h*/ #ifdef _ADD_H_ #define _ADD_H_ extern int add_int(int a,int b); extern float add_float(float a,float b); #endif
sub/sub_int.c sub/sub_float.c sub.h
/*sub/sub_int.c文件*/
#include <stdio.h> int sub_int(int a,int b){ return a-b; } /*sub/sub_float.c文件*/ #include <stdio.h> float sub_float(float a,float b){ return a-b; } /*sub.h文件*/ #ifdef _SUB_H_ #define _SUB_H_ extern int sub_int(int a,int b); extern float sub_float(float a,float b); #endif
main.c
#include <stdio.h> #include "sub.h" #include "add.h" int main(void){ int a=10,b=12; float x=1.23456,y=9.87654321; printf("int a+b is:%d\n",add_int(a,b)); printf("int a-b is:%d\n",sub_int(a,b)); printf("float x+y is:%d\n",add_float(x,y)); printf("float x+y is:%d\n",sub_float(x,y)); return 0; }
编译命令:
gcc -c add/add_int.c -o add/add_int.o gcc -c add/add_float.c -o add/add_float.o gcc -c sub/sub_int.c -o sub/sub_int.o gcc -c sub/sub_float.c -o sub/sub_float.o gcc -c main.c -o main.o #头文件必须与main.c在同一级目录下 gcc -o test add/add_int.o add/add__float.o sub/sub_int.o sub/sub_float.o main.o #链接所有目标文件生成可执行文件
或使用一条语句
gcc -o test add/add_int.c add/add_float.c sub/sub_int.c sub/sub_float.c main.c #头文件必须与main.c在同一级目录下
如果文件更多,则每次编译很麻烦,所以需要编译一个命令模版,直接运行即可
2、MakeFile文件编写
1.以上实例可使用makefile:
#文件名是makefile
#生成test,“:右边为目标,左边是所依赖项 test:add_int.o add_float.o sub_int.o sub_float.o main.o #依赖关系 依赖不满足下面的命令就不执行(#gcc之前需要用Tab,不是空格) gcc -o test add/add_int.o add/add_float.o sub/sub_int.o sub/sub_float.o main.o #生成所需的目标文件后,才会执行该语句 #生成 add_int.o的规则,将add_int.c编译成目标文件add_int.o add_int.o:add/add_int.c add/add.h gcc -c -o add/add_int.o add/add_int.c #生成add_float.o add_float.o:add/add_float.c add/add.h gcc -c -o add/add_float.o add/add_float.c #生成sub_int.o sub_int.o:sub/sub_int.c sub/sub.h gcc -c -o sub/sub_int.o sub/sub_int.c #生成sub_float.o sub_float.o:sub/sub_float.c sub/sub.h gcc -c -o sub/sub_float.o sub/sub_float.c #生成main.o main.o:main.c add/add.h sub/sub.h gcc -c -o main.o main.c -Iadd -Isub #清理命令 clean: rm -f test add/add_int.o add/add_float.o sub/sub_int.o sub/sub_float.o main.o
执行方法:
make 项目名
执行clean命令
make clean
2.使用用户自定义变量编写MakeFile
#定义变量 CC=gcc #定义gcc CFLAGS= -Isub -Iadd -O2 #加入头文件搜索路径sub和add(O2为优化) TARGET=test #最终生成可执行文件的名字 RM=rm -f #删除命令 OBJS=add/add_int.o add/add_float.o sub/sub_int.o sub/sub_float.o main.o $(TARGET):$(OBJS) ${CC} -o $(TARGET) $(OBJS) $(CFLAGS) #生成目标文件 clean: -$(RM) $(TARGET) $(OBJS) #删除所有的目标文件和可执行文件
3.使用MakeFile中的自动变量编写MakeFile--自动搜索源文件
#使用makefile中的自动变量 CC=gcc CFLAGS= -Isub -Iadd -O2 #加入头文件搜索路径sub和add(O2为优化) TARGET=test #最终生成可执行文件的名字 RM=rm -f #删除命令 OBJS=add/add_int.o add/add_float.o sub/sub_int.o sub/sub_float.o main.o $(TARGET):$(OBJS) ${CC} -o $(TARGET) $(OBJS) $(CFLAGS) $(OBJS):%.o:%.c #将OBJS中所有扩展名wei.o的文件替换成扩展名为.c的文件 $(CC) -c $(CFLAGS) $< -o $@ #编译生成目标文件 clean: -$(RM) $(TARGET) $(OBJS) #删除所有的目标文件和可执行文件
4.不指定源文件的位置并生成的目标文件存放在统一目录下编写MakeFile
#不指定源文件的具体位置 CC=gcc OBJSDIR=.objs #目标文件生成目录 VPATH=add:sub:. #加入add和sub CFLAGS= -Iadd -Isub -O2 #加入头文件搜索路径sub和add(O2为优化) TARGET=test #最终生成可执行文件的名字 RM=rm -f #删除命令 OBJS=add_int.o add_float.o sub_int.o sub_float.o main.o $(TARGET):$(OBJSDIR) $(OBJS) $(CC) -o $(TARGET) $(OBJSDIR)/*.o $(CFLAGS) #将OBJSDIR目录所有.o文件链接生成TARGET $(OBJS):%.o:%.c $(CC) -c $(CFLAGS) $< -o $(OBJSDIR)/$@ #生成目标文件,存放到OBJSDIR目录 $(OBJSDIR): mkdir -p ./$@ #建立目录,-p胡洛父目录不存在的错误 clean: -$(RM) $(TARGET) #删除可执行文件 -$(RM) $(OBJSDIR)/*.o #删除OBJSDIR下多有的.o文件
5.自推导规则
只需给出需要创建的目标文件名,make就回自动找到对应的源文件.c并使用默认命令创建目标文件
#定义变量 CC=gcc #定义gcc CFLAGS= -Isub -Iadd -O2 #加入头文件搜索路径sub和add(O2为优化)
VPATH=add:sub #存放头文件的文件名 TARGET=test #最终生成可执行文件的名字 RM=rm -f #删除命令 OBJS=add_int.o add_float.o sub_int.o sub_float.o main.o #不需要带文件路径 $(TARGET):$(OBJS) ${CC} -o $(TARGET) $(OBJS) $(CFLAGS) #生成目标文件,链接文件 clean: -$(RM) $(TARGET) $(OBJS) #删除所有的目标文件和可执行文件