hello,各位小伙伴,本篇文章跟大家一起学习《Linux:make,Makefile》,感谢大家对我上一篇的支持,如有什么问题,还请多多指教 !
如果本篇文章对你有帮助,还请各位点点赞!!!
话不多说,开始正题:
文章目录
🍁
- 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
- 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
- makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
- make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
- make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。
🍁总的说(理解)
就是依赖例子
🍁例子
先简单写一个c代码:
#include<stdio.h>
int main()
{
printf("hello\n");
return 0;
}
再vim一个Makefile:
delete:del.c
gcc -o delete del.c
.PHONY:clean
clean:
rm -f delete
也可以这么写:
$@ : 表示目标文件
$^ : 表示所有依赖文件
依赖关系
delete
依赖del.c
依赖方法
gcc -o delete del.c
,就是对应的依赖方法gcc -o $@ $^
,也可以是这样
Makefile本质就是依赖关系和依赖方法的集合
原理
- make在默认方式下,也就是只输入make命令,那:
-
make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
-
如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“delete”这个文件,并把这个文件作为最终的目标文件。
-
如果delete文件不存在,或是
del.c
所依赖的后面的文件的文件修改时间要比delete
这个文件新(可以用 touch 测试),那么,他就会执行后面所定义的命令来生成del.c
这个文件。 -
如果
del.c
所依赖的delete文件不存在,那么make会在当前文件中找目标为del.c
文件的依赖性,如果找到则再根据那一个规则生成del.c文件。(这有点像一个堆栈的过程)
-
当然,你的C文件和H文件是存在的啦,于是make会生成
del.c
文件,然后再用del.c
文件声明make的终极任务,也就是执行文件delete
了。 -
这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
-
在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。
-
make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。
-
只输入
make
会默认实行Makefile
里第一句命令
项目清理
- 工程是需要被清理的
- 像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要make执行。即命令——“make clean”,以此来清除所有的目标文件,以便重编译。
- 但是一般我们这种clean的目标文件,我们将它设置为伪目标,用
.PHONY
(PHONY
是假的意思)修饰,伪目标的特性是,总是被执行的。 - 可以将我们的
delete
目标文件声明成伪目标,测试一下。
简单来说就是:我需要clean
这个文件,但是没有,所以make
会搜寻目标文件为make
的文件,也就是:
clean:
rm -f delete
如果要形成clean
目标文件,其对应的方法总是被执行的
stat
stat delete
🍁多个文件
bin = delete
src = del.c
$(bin):$(src)
gcc -o $@ $^
bin(可以自己命名,定义了目标文件) = 可以跟多个文件
src(可以自己命名,定义了源文件) = 可以跟多个文件
🍃Makefile中的通配符%
例子:
%.c
:所有的.c
文件
%.o
:所有的.o
文件
tar = program
src = $(wildcard *.c)
obj = $(src:.c=.o)
%.o:%.c
gcc -c $< -o $@
$(tar):$(obj)
gcc -o $(tar) $(obj)
.PHONY:clean
clean:
rm -f $(obj) $(tar)
下面是一个简单的实例操作步骤:
1.创建文件:
在一个新的目录中,创建以下文件:
main.c:
#include <stdio.h>
void hello() {
printf("Hello, World!\n");
}
int main() {
hello();
return 0;
}
hello.c:
#include <stdio.h>
void hello();
4.创建 Makefile:
在同一目录中创建一个名为 Makefile 的文件,内容如下:
TARGET = program
SOURCES = $(wildcard *.c)
OBJECTS = $(SOURCES:.c=.o)
%.o: %.c
gcc -c $< -o $@
$(TARGET): $(OBJECTS)
gcc -o $(TARGET) $(OBJECTS)
.PHONY:clean
clean:
rm -f $(OBJECTS) $(TARGET)
src = $(wildcard *.c)
obj = $(src:.c=.o)
这两行用于自动生成源文件和目标文件列表。
-
src = $(wildcard *.c):
-
wildcard 函数用于查找当前目录下所有 .c 文件,并将它们的列表赋值给 src 变量。
-
obj = $(src:.c=.o):
-
这行使用了模式替换,将
src
中的每个.c
文件名替换为相应的.o
文件名,生成的列表赋值给obj
变量。
这样,就可以在编译时自动处理所有源文件,而不必手动列出每个文件。
%.o:%.c
gcc -c $< -o $@
这行规则来自动编译 .c
文件为 .o
文件:
命令行操作:
在命令行中输入make
编译完成后,运行生成的可执行文件:./program
如果需要清理生成的文件,可以运行:make clean
🍃$
符
在 Makefile 中,$ 是一个特殊符号,用于引用变量和自动变量。以下是一些常用的用法:
1.引用变量:
- $(VAR_NAME):用于引用名为 VAR_NAME 的变量。例如,如果你定义了 SOURCES,可以使用 $(SOURCES) 来访问其值。
2.自动变量:
- $<:表示规则中的第一个依赖文件(通常是源文件)。
- $@:表示当前规则的目标文件(通常是生成的对象文件)。
- $^:表示所有依赖文件的列表,去重。
示例:
%.o: %.c
gcc -c $< -o $@
在这里,$<
会被替换为 .c
文件的名称,而 $@
会被替换为相应的 .o
文件的名称。
🍃make
Makefile 的行为:
- 默认目标:make 从上到下扫描 Makefile,默认生成第一个目标。如果想执行其他目标,可以使用 make <target>。
- 语法错误处理:如果在执行命令时发生语法错误,make 会停止处理,避免生成不完整或错误的文件。
- 自动推导:make 会根据文件的依赖关系自动推导目标。如果依赖文件不存在,make 不会立即执行相关命令,而是会继续推导直到找到需要的依赖文件。
- 逆向执行:一旦找到所有依赖文件,make 会逆向执行所有相关的命令,以生成最终目标。
- 默认生成:make 默认生成一个可执行文件,但可以根据需要定义多个目标。
你学会了吗?
好啦,本章对于《Linux:make,Makefile》的学习就先到这里,如果有什么问题,还请指教指教,希望本篇文章能够对你有所帮助,我们下一篇见!!!
如你喜欢,点点赞就是对我的支持,感谢感谢!!!