Makefile文件其实就是管理编译的工具。使用makefile文件,去寻找相关的*.c 、.h或者.a、*.so的静态库动态库文件等。makefile文件就是告诉编译链工具去相关的路径上寻找,寻找相关的依赖文件。平常若是简单的一两个文件下,可以使用编译器进行gcc编译文件,但是一旦文件多了,需要手动的每一条命令进行执行就会有极大的麻烦,同时也不好管理。
以下就使用相关简单的例子去一步步深入makefile,了解make文件是如何进行文件管理,从而使编译器进行文件编译的。
1、相对于统一目录下的单文件
创建文件:
# touch main.c tool1.c tool1.h tool2.c tool2.h
# ls
main.c tool1.c tool1.h tool2.c tool2.h
tool1.h文件如下:
#ifndef TOOL1_H_
#define TOOL1_H_
void mytool1(void);
#endif
tool1.c文件如下:
#include <stdio.h>
#include "tool1.h"
void mytool1()
{ printf("tool1 printf\n");}
Tool2.h文件如下:
#ifndef TOOL2_H_
#define TOOL2_H_
void mytool2(void);
#endif
Tool2.c文件如下:
#include <stdio.h>
#include "tool2.h"
void mytool2()
{ printf("tool2 printf\n");}
Main.c文件如下:
#include <stdio.h>
#include "tool1.h"
#include "tool2.h"
int main ()
{ mytool1();mytool2(); return 0;}
测试一:
创建好文件后,进行gcc编译,生成a.out。运行a.out显示打印结果
在上述简单的gcc *.c的过程中,其实有如下的依赖过程:
a.out -> main.o tooll.o tool2.o //a.out的生成其实依赖于main.o tooll.o tool2.o
main.o -> main.c
tooll.o -> tooll.c
tool2.o -> tool2.c
测试二:
将以上的所有内容复制到一个新的文件夹,再创建一个makefile文件。如下图创建文件如下:
Makefile文件内容如下:
mytool:main.o tool1.o tool2.o
gcc main.o tool1.o tool2.o -o mytool
main.o:main.c
gcc main.c -c -Wall -g -o main.o
tool1.o :tool1.c
gcc tool1.c -c -Wall -g -o tool1.o
tool2.o :tool2.c
gcc tool2.c -c -Wall -g -o tool2.o
执行make后,打印出两个文件的内容。从makefile可知,.h文件从不参与文件编译,都是从.c的头文件include进行包含进去的。
(注意:若想包含头文件,有三个方法。方法一:使用include进行头文件包含,在头文件线上.h的相关路径;方法二:使用 -I<文件路径> 在makefile文件中,编译的时候进行添加。方法三:使用隐式函数,例如:LDFLAGS 这个为链接选项,如 -L ; LDLIBS 这个为链接需要的库,如-Ikernel32 -Iuser32。这是用隐式函数时,makefile就会去相对的路径寻找相关的文件。)
相关makefile代码例如:
OBJS=main.o tool1.o tool2.o
CC=gcc
CFLAGS+=-c -Wall -g
#VPATH = src:include
mytool:$(OBJS)
$(CC) $^ -o $@ -Iinclude
%.o:%.c
$(CC) $^ $(CFLAGS) -o $@ -Iinclude
clean:
rm *.o mytoo*
测试三:替换
将makefile使用先关的简式的形式替换,使用OBJS替换相关的*.o等目标文件。使用CC代替相关的编译工具链,使用CFLAGS控制调试信息。将相关的文件进行简化。
(注:相关的#后续的内容为注释内容,用户可以一步一步删除#,使得后续的命令生效。对比前后文的差异)
将相关的make进行执行,可得出相同的结果。
测试四:简化
下图为makefile代码
将相关的make进行执行,可得出相同的结果。
测试五:最简化
使用通配符 %.o:%.c 使用通配符将所有的.O .C文件全部替换,让编译文件尽量简洁。
在原有makefile文件中进行最简化修改,在makefile.baceup文件中就是修改成的最简化的形式。如下图所示。所有的.O .C文件全部被替换。
将相关的make进行执行,相关结果如下。到达此步,已将可以写成一个最简版的makefile文件了。已经初步具备编写makefile文件的程度
测试六:多文件夹
在实际开发过程中,以上的前五个测试都是简单的几个文件放在同一个文件夹中。但是在实际开发大型项目时,为了比较好的管理文件,通常都会创建好几个文件夹。每个文件夹都会存放相同类型的文件以便管理。
以下创建两个文件夹,include文件夹存放.h相关的所有文件 src文件夹存放.c的所有文件。
还有main.c和makefile文件位置不变。
其中makefile文件修改如下:
OBJS:为目标文件通配符
CC:为编译工具链
CFLAGS+=-c -Wall -g :为编译信息的配置
VPATH = src:include :为makefile文件编译时寻找的路径
mytool:$(OBJS)
$(CC) $^ -o $@ -Iinclude
$(CC)为编译工具,可以自行修改 $^表示所有的依赖 $@表示目标 -Iinclude 表示链接include文件夹里面的.h文件。由于使用VPATH命令指定搜索路径,所以makefile可以选找到inclued中的.h文件
%.o:%.c
$(CC) $^ $(CFLAGS) -o $@ -Iinclude
%.o:%.c 表示所有目标文件:所有依赖文件 $(CFLAGS)表示编译配置信息
clean:
rm *.o mytoo*
clean 表示清除所有编译的内容
执行结果如下:makefile成功执行