我们做一个项目会写很多文件,Windows平台上我们有IDE去执行所有操作,而在Linux平台上去做一个项目的话它的文件可能不在同一位置,此时使用gdb就不会那么方便了,所以我们需要添加一个Makefile文件来执行文件的自动编译,它的好处就是“自动化编译”,Makefile文件就是将各种命令集成到一个文件中,由它来执行文件的编译,这样操作的一个很明显的好处就是当我们某个文件更改后不用将所有文件都重新进行编译,只是针对某个文件进行操作即可。所以本篇博客简要介绍Makefile文件如何编写,并使用Makefile文件来提高软件开发效率。
一、代码文件
同样,我们先给出多个代码来作为后续试验的基础:
1.main.c
#include<stdio.h>
#include<stdlib.h>
#include"./mymath.h"
int main()
{
int a=20;
int b=3;
printf("a+b=%d\n",my_add(a,b);
printf("a-b=%d\n",my_sub(a,b);
printf("a*b=%d\n",my_mux(a,b);
printf("a/b=%f\n",my_div(a,b);
exit(0);
}
2.mymath.h
#pragma once
int my_add(int,int);
int my_sub(int,int);
int my_mux(int,int);
double my_div(int,int);
3.add.c
#include"./mymath.h"
int my_add(int a,int b)
{
return a+b;
}
4.sub.c
#include"./mymath.h"
int my_sub(int a,int b)
{
return a-b;
}
5.mux.c
#include"./mymath.h"
int my_add(int a,int b)
{
return a*b;
}
6.div.c
#include"./mymath.h"
double my_div(int a,int b)
{
if(0==b)
{
printf("error\n");
exit(0);
}
return (a*1.0)/b;
}
二、如何编写Makefile文件
首先我们编写makefile文件,它的命名一般直接使用“makefile”,适合默认情况;其文件格式如下:
target:source
(TAB)Command
例如以上的代码我们是要生成一个main可执行文件,而生成main可执行文件所依赖的文件则是各个.o文件,所以我们需要指定各个.o文件,并在后面指定.o文件的生成命令,如下:
在Makefile文件的首行我们指定了生成main文件需要的源文件为各个.o文件,再换行添加从各个.o文件生成到可执行文件的命令,注意此处一定是TAB,而不是四个空格;然后在下面再依次指定各个.o文件的生成方式,命令方式和前面是一样的;
最后的clean是一个伪目标,可以看到他后面没有添加任何文件,所以在执行操作的时候会直接执行下面的命令。
三、Makefile文件的执行过程
执行Makefile文件的命令为:make
在我们输入make命令后,make工具会从第一行开始检索各个.o文件是否存在,如果不存在,会向下搜索该文件的生成方式,注意此处的搜索顺序和main后面的.o文件顺序相同,上面的makefile文件比较简单,所以进行一级搜索之后工作就会完成,不过在大型工程中会有多级的搜索;等到全部.o文件都生成之后会执行main下面的命令来生成main可执行文件;
注意此处搜索时,如果检索到了,但其更改时间比main的生成时间晚的话,还是会生成,这就是makefile文件提高效率的方法,未更改的文件将不会参加此次编译。下面我们来执行一下:
在命令行中输入“make”
在生成之前我们先看一下文件夹下没有任何.o文件的存在;执行过程中它会执行各个命令来生成文件,可以看到它把各个命令挨个执行了,最后在各个文件都存在的情况下执行链接命令,并生成了main可执行文件,执行“./main”命令后可以看到生成结果:
然后我们尝试将add.c的内容更改为“return a”后再执行一次make:
可以看到这次make工具只重新执行了和add.c有关的命令,同样执行main后发现结果已经更改;
而对于最后的clean命令是执行清理操作的,看下面的命令就可以知道会清除哪些内容,注意执行makefile文件中的伪命令时前面需要加上“make”,测试一下:
对比会发现“make clean”命令已经清除了main和所有的.o文件
四、多文件夹下makefile的写法
1.直接指定路径:在makefile中每个所需文件的前面指定路径;
2.使用vpath:在makefile中添加VPATH变量,添加格式为:
VPATH=PATH1:PATH2
指定为当前目录:.
五、关于makefile文件的小技巧
自动推导功能
make工具包含自动推导功能,因为各个文件生成时是有文件依赖性的,比如生成add.o时依赖add.c,所以我们可以把我们的makefile文件简化成如下格式:
同样我们执行make命令:
可以看到连接执行没有任何问题,只是编译器换了(当然这不重要),如果不想使用CC可以在makefile文件头添加“CC=gcc”语句来指定为gcc编译器;
变量功能
当有些文件名被一块多次重复使用时我们可以提供一个变量来使我们的编写内容大大减少,在使用时可以直接使用这个变量名来简化,例如:
file1=main.o add.o div.o sub.o mux.o
main:$(file1)
$(file1):
此时就是使用变量名来简化操作,可以手动试一下;
换行符
当一个命令中涉及的文件很多时,可以使用“\”来换行提高文件的易读性,例如:
file1=main.o\
add.o\
div.o\
sub.o\
mux.o
此时make命令会将换行后的所有文件都认为是一起的文件;
使用all指定生成多个可执行文件
有时会需要生成多个可执行文件,而各个可执行文件所依赖的.o文件又不同,此时我们在makefile文件中加入all命令即可:
all:file1 file2
再将生成file1和file2的文件的生成方式添加在下面即可。
在此介绍了makefile的基本用法,更细致的可以搜集一些资料学习。