Makefile文件很简单

文章介绍了如何使用Makefile进行自动化编译,从简单的命令行编译到逐步引入依赖关系,优化编译过程。通过Makefile,可以更高效地管理大型项目,仅编译修改过的源文件,提高开发效率。

  makefile:管理工程文件。在一个项目里面有很多 .c, .h文件。在工作量巨大的情况下,不可能一个人工手工编译。所以通过makefile,可以实现自动化编译。直接使用make就行。废话不多说。举个栗子说明下。

makefile 1.0:

假设有一个程序。

以下是文件的内容

// 打印一个this is fun1,fun2
// fun1.c 
#include <stdio.h>
void fun1()
{
    printf("this is fun1\n");
}
// fun2.c
#include <stdio.h>
void fun2()  
{  
    printf("this is fun2\n");  
}  
​
// fun3.c 打印一个乘法口诀表
#include<stdio.h>
void fun3()  
{  
    printf("this is fun3\n"); 
    int i,j;
  //下三角
    for(i=1;i<=9;i++){
        for(j=1;j<=i;j++){
            printf("%d*%d=%d ",i,j,i*j);
        }
        printf("\n");
    } 
}  
//main.c
#include <stdio.h>
void fun1();
void fun2();
void fun3();
int main()  
{  
    printf("hello world\n");  
    fun1();  
    fun2();
    fun3();
}

这个程序执行需要fun1.c,fun2.c,fun3.c ,main.c 。执行它。毫无疑问使用

gcc -Wall fun1.c fun2.c fun3.c main.c -o app

生成可执行程序app,我们运行下app

那我们如果用makfile文件该怎么写呢?

首先我介绍下makefile文件的格式

target: dependency_files
       command

target:表示你要生成的可执行程序的名称。可以自己随便取个名字。在这里我取为app

dependency_files:创建的目标体所依赖的文件 ,在这里有fun1.c fun2.c fun3.c main.c(多个文件依赖,用空格隔开)

command:表示运行时的命令。命令为:gcc fun1.c fun2.c fun3.c main.c -o app

注意command之前一定要用tab键回车。复制的时候,一定要手动把空格删点,然后自己敲回车。不然报错

当然你首先得用 vim makefile创建一个makefile.

//makefile里面的内容
app:fun1.c fun2.c fun3.c main.c
    gcc fun1.c fun2.c fun3.c main.c -o app

运行结果:

这个时候你肯定觉得,这也没有什么。你敲了这么多的命令,不和我一样吗?确实一样,也很麻烦。不过不能一口吃个胖子。由浅入升,慢慢来。

makefile 2.0:

我们稍微将makefile文件进行一下升级。

app:fun1.o fun2.o fun3.o main.o
    gcc fun1.o fun2.o fun3.o main.o -o app
fun1.o:fun1.c
    gcc -c fun1.c -o fun1.o
fun2.o:fun2.c
    gcc -c fun2.c -o fun2.o
fun3.o:fun3.c
    gcc -c fun3.c -o fun3.o
main.o:main.c
    gcc -c main.c -o main.o

运行结果:

 我来解释下这个串代码,首先执行了gcc -c fun1.c -o fun1.o,后面依次执行,最后才执行了gcc fun1.o fun2.o fun3.o main.o -o app。

为什么会这样呢?这是因为,我开始的时候,第一行使用的是app:fun1.o fun2.o fun3.o main.o。但是文件没有fun1.o,fun2.o,fun3.o ,main.o这个依赖。后面他就继续往下执行,下面的程序,生成的.o文件。最后利用生成的.o文件当做依赖执行。

你可能觉得这样做很麻烦,还不如gcc fun1.o fun2.o fun3.o main.o -o app解决问题。敲了这么多。但是你要知道,他是用来管理一个大型的项目。如果,你修改了main.c里面的内容,你要执行程序,你是不是得把所有的程序编译一遍。这样做就很浪费时间。编译是一件很费时的事情,因为我们的程序简单,所以看不出来。如果你采用了上面的写法。编译只会修改main.c的内容。仅仅编译main.c,而不会编译其他文件。

当然这样写还不够简单不够完善。我们再次将他升级下。

makefile 3.0:

首先介绍一下基础知识。

我们观察上面的代码,发现有很多相似的地方。比如以下的代码,都很类似,我们是否可以替代呢。

答案可以,可以用通配符,这样所有以.o ,.c的代码都可以归到一起。

%.o:%.c - %: 通配符,匹配一个字符串 - 两个%匹配的是同一个字符串

以下是更多详细的介绍。

命 令 格 式含 义
AR库文件维护程序的名称,默认值为ar
AS汇编程序的名称,默认值为as
CCC编译器的名称,默认值为cc
CPPC预编译器的名称,默认值为$(CC) –E
CXXC++编译器的名称,默认值为g++
FCFORTRAN编译器的名称,默认值为f77
RM文件删除程序的名称,默认值为rm –f
ARFLAGS库文件维护程序的选项,无默认值
ASFLAGS汇编程序的选项,无默认值
CFLAGSC编译器的选项,无默认值
CPPFLAGSC预编译的选项,无默认值
CXXFLAGSC++编译器的选项,无默认值
FFLAGSFORTRAN编译器的选项,无默认值
$*不包含扩展名的目标文件名称
$+所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件
$<获取所有第一个依赖文件的名称
$?所有时间戳比目标文件晚的依赖文件,并以空格分开
$@获取目标文件名称
$^所有不重复的依赖文件,以空格分开
$%如果目标是归档成员,则该变量表示目标的归档成员名称
$(var)获取变量var的值

自定义变量

变量名=变量值 var=hello

于是,我们可以用 $(CC)来代替gcc ,自己写一个变量src表示依赖。target表示目标变量。

然后使用$(src)获取变量,即获取到了fun1.o fun2.o fun3.o main.o

使用$(target)获取变量,即获取到了app

#定义一个变量
src=fun1.o fun2.o fun3.o main.o
target=app
$(target):$(src)
    $(CC) $(src) -o $(target)
fun1.o:fun1.c
    gcc -c fun1.c -o fun1.o
fun2.o:fun2.c
    gcc -c fun2.c -o fun2.o
fun3.o:fun3.c
    gcc -c fun3.c -o fun3.o
main.o:main.c
    gcc -c main.c -o main.o

后面我们发现每次都要敲他,很麻烦,可以替换吗?

fun1.o:fun1.c gcc -c fun1.c -o fun1.o

makefile 3.0:合肥学院期末需要掌握

#定义一个变量
src=fun1.o fun2.o fun3.o main.o
target=app
$(target):$(src)
    $(CC) $(src) -o $(target)
%.o:%.c
    $(CC) -c $< -o $@

使用%.o去寻找所有的.o文件,使用了%.c通配所有.c文件。

观察代码,我们觉得src=fun1.o fun2.o fun3.o main.o我们觉得写很多.o还是麻烦怎么进一步简化呢?

makefile 4.0:合肥学院期末需要掌握

#定义一个变量
#添加所有.c文件
src=$(wildcard ./*.c)
objs=$(patsubst %.c,%.o,$(src))
target=app
$(target):$(objs)
    $(CC) $(objs) -o $(target)
%.o:%.c
    $(CC) -c $< -o $@

主要通过两个函数wildcard ./*.c。他的意思是寻找当前目录下所有的.c问下,将他的值给src

然后将他转换成.o文件。patsubst %.c,%.o,$(src)这个函数的功能是,就是如果第三个参数是和第一个参数后缀一样,我就替换为.o

下面是有关函数详细的介绍。

makefile 5.0:合肥学院期末需要掌握

#添加所有.c文件
src=$(wildcard ./*.c)
objs=$(patsubst %.c,%.o,$(src))
target=app
$(target):$(objs)
    $(CC) $(objs) -o $(target)
%.o:%.c
    $(CC) -c $< -o $@
​
.PHONY:clean
clean:
    rm $(objs) -f

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值