文章目录
前言
上一篇文章讲了Linux下的c编程,本讲重点学习make工具和Makefile,会先讲怎么引入的,不然我们只会稀里糊涂的使用,不知道为什么要这么使用,对我们的学习也是不利的。
一、make工具和Makefile文件
当一个大型项目的源码文件比较多的时候就不适合通过直接输入gcc命令来编译,这时候就需要一个自动化的编译工具。
1.make:
利用make工具可以自动完成编译工作,这些工作包括:
(1)如果修改了某几个源文件,则只重新编译这几个源文件
(2)如果某个头文件被修改了,则重新编译所有包含该头文件的源文件
利用这种自动编译可以大大简化开发工作,避免不必要的重新编译,make工具通过一个称为Makefile的文件来完成并自动维护编译工作,Makefile文件描述了整个工程的编译、连接规则。
2.Makefile: make工具所使用的文件,描述了整个工程的编译连接规则。
二、案例引入
假如我们现在有这个任务:通过键盘输入两个整形数字,然后计算他们的和并将结果显示在屏幕上,在这个工程中我们有main1.c、input.c和calcu.c这三个C文件和input.h、calcu.h这 两个头文件。其中main.c是主体,
input.c负责接收从键盘输入的数值,calcu.h进行任意两个数相加。
main1.c文件内容如下:
#include <stdio.h>
#include "input.h"
#include "calcu.h"
int main(int argc,char *argv[])
{
int a,b,num;
input_int(&a,&b);
num=calcu(a,b);
printf("%d+%d=%d\r\n",a,b,num);
return 0;
}
input.c文件内容如下:
#include <stdio.h>
#include"input.h"
void input_int(int *a,int *b)
{
printf("input tow num:");
scanf("%d %d",a,b);
printf("\r\n");
}
calc.h文件内容如下:
#include "calcu.h"
int calcu(int a,int b)
{
return (a+b);
}
input.h文件内容如下:
#ifndef _INPUT_H
#define _INPUT_H
void input_int(int *a,int *b);
#endif
calcu.h文件内容如下:
#ifndef _CALCU_H
#define _CALCU_H
int calcu(int a,int b);
#endif
以上就是我们这个小项目的所有源文件, main函数中首先通过input函数从键盘读入两个数据,然后调用calcu函数计算两数之和。
先用gcc一起编译(顺序没有要求),编译结果就是main文件,能够成功运行
通过命令 ls main -l 查看编辑的日期,然后我们重新编译一下,但是不修改文件的信息,再次查看编辑日期:
三、Makefile的引入
(1)分析
根据上述结果,可以看出代码按照我所设想的工作了,使用命令 gcc main1.c calcu.c input.c -o main 看起来比较简单,但是我们这个项目只有三个文件,如果有几千个文件,当我们修改了一个文件的内容,那么我们使用上面的命令就需要全部重新编译,就很浪费时间了。
最好的办法就是哪个文件被修改了,只编译这个被修改的文件即可,其他没有修改的文件就不需要再次重新编译了,为此改变我们的编译方法,如果第一次编译工程,我们先将工程中的文件都编译一遍,然后后面修改了哪个文件就编译哪个文件,修改的命令如下:
gcc -c mian1.c
gcc -c input.c
gcc -c calcu.c
gcc main1.o input.o calcu.o -o main
上面三行是将三个文件编译成对应的.o文件,所以使用了 -c 选项,
最后再把三个.o文件进行链接,最后一行是将编译出来的所有.o文件链接成可执行文件main。因此现在我们假如只修改了calcu.c文件,只需要将该文件重新编译即可,然后再链接,因此只需要下面两条命令即可:
gcc -c calcu.c
gcc main1.o input.o calcu.o -o main
这样做带来的问题是,当修改的文件一多,我们可能不记得了,就忘记了编译,结果。。。。。。。。
所以我们需要这样一个Makefile工具:
1.如果工程没有编译过,那么所有的.c文件都要被编译并且链接成可执行程序。
2.如果只有个别.c文件被修改了,那么只编译被修改的.c文件。
3.如果头文件被修改了,那么我们需要编译所有引用这个头文件的.c文件,并且链接成可执行文件。
(2)Makefile规则格式
Makefile由一系列的规则组成,规则格式如下:
目标 ···… : 依赖文件集合 ···
命令1
命令2
·······
比如下面这条规则:
main: main1.o input.o calcu.o
gcc -o main main1.o input.o calcu.o
这条规则的目标是main,其中main1.o,input.o和calcu.o是生成main的依赖文件,如果要更新main,就必须要先更新它的所有依赖文件,如果依赖文件中的任何一个有更新,那么目标也必须更新,也即是重新执行一遍命令。(命令列表中的每条命令必须以TAB键开始,不能使用空格!)
(2)使用Makefile
在工程目录下创建名为 Makefile 的文件,文件名一定要叫做 Makefile ,需要区分大小写,在该文件中输入如下代码(最后两行是清理工程,清除所有的.o文件和mian文件):
main:main1.o input.o calcu.o
gcc -o main main1.o input.o calcu.o
main1.o: main1.c
gcc -c main1.c
input.o:input.c
gcc -c input.c
calcu.o:calcu.c
gcc -c calcu.c
clean:
rm *.o
rm main
此时就可以使用Makefile了,直接输入 make 命令,它会在当前目录下自动找到 Makefile,然后按照规则编译,所有的.o文件也都出来了,也能够成功运行。
如果想清除编译的文件,使用命令 make clean:
如果想要编辑某一个.c文件,比如calcu.c文件中加一行空格,那么make就会检查你最后文件的修改日期,如果被改了,就会重新编译,就只会执行命令 gcc -c calcu.c,没有修改的就不会去编译。
(四)使用Makefile重新编译上篇文章的程序
经过前面的说明,我们基本懂得了其原理和应用,那么使用它重写编写上篇文章的程序也是手到擒来。
Makefile命令如下:
上篇文章编写程序不是很严谨,我们可以根据上述案例修改成一样的格式,最后也是能够成功运行。
参考视频:
https://www.bilibili.com/video/BV1vE411h7Fi?p=17&vd_source=da8896665295f05890c8318ba6ad6bb4