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 |
| CC | C编译器的名称,默认值为cc |
| CPP | C预编译器的名称,默认值为$(CC) –E |
| CXX | C++编译器的名称,默认值为g++ |
| FC | FORTRAN编译器的名称,默认值为f77 |
| RM | 文件删除程序的名称,默认值为rm –f |
| ARFLAGS | 库文件维护程序的选项,无默认值 |
| ASFLAGS | 汇编程序的选项,无默认值 |
| CFLAGS | C编译器的选项,无默认值 |
| CPPFLAGS | C预编译的选项,无默认值 |
| CXXFLAGS | C++编译器的选项,无默认值 |
| FFLAGS | FORTRAN编译器的选项,无默认值 |
| $* | 不包含扩展名的目标文件名称 |
|---|---|
| $+ | 所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件 |
| $< | 获取所有第一个依赖文件的名称 |
| $? | 所有时间戳比目标文件晚的依赖文件,并以空格分开 |
| $@ | 获取目标文件名称 |
| $^ | 所有不重复的依赖文件,以空格分开 |
| $% | 如果目标是归档成员,则该变量表示目标的归档成员名称 |
| $(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
文章介绍了如何使用Makefile进行自动化编译,从简单的命令行编译到逐步引入依赖关系,优化编译过程。通过Makefile,可以更高效地管理大型项目,仅编译修改过的源文件,提高开发效率。
1758

被折叠的 条评论
为什么被折叠?



