襄阳作风建设年活动网站,单页设计是什么意思,谈谈我认为的网络营销是什么,ps网站建设教程什么是 make
make 是一个命令#xff0c;他会在源文件的当前目录下寻找 makefile 或者 Makefile 文件执行这个文件中的代码。
makefile 文件的编写
我们先来见见猪跑#xff0c;看看 make 怎么用的#xff1a; 下面是 makefile 文件的内容#xff1a; 这是 test.c 中的…什么是 make
make 是一个命令他会在源文件的当前目录下寻找 makefile 或者 Makefile 文件执行这个文件中的代码。
makefile 文件的编写
我们先来见见猪跑看看 make 怎么用的 下面是 makefile 文件的内容 这是 test.c 中的内容
#includestdio.h
int main()
{printf(hello make\n);return 0;
}之前我们想要使用 gcc 编译 test.c 生成 test 可执行文件你是不是要这样写命令
gcc -o test test.c在我们写了上面的 makefile 文件之后我们就能使用 make 命令来代替啦 我们可以看到使用 make 命令之后顺利编译出来了可执行文件并且能够顺利执行
makefile 文件的编写
我们再来看 makefile 文件中的代码 其中这个冒号前面的部分叫做依赖关系(绿色框框的那个)后面的部分叫做依赖方法(红色框框的那个)。听上去十分高大尚翻译成白话文就是依赖关系的形成需要依赖方法中的所有文件。 make 命令会自动扫描 makefile 文件查看当前目录下是否存在依赖方法中的所有文件如果已经存在那么就会执行下一行 Tab 缩进的代码(只能是 Tab 缩进)。那么如果不存在怎么办呢 我们在讲 C 语言编译链接的时候知道从 C 语言的源文件到生成功可执行文件是分成很多步骤的
gcc -E
gcc -S
gcc -C根据这个原理我们就在 makefile 文件中将那一行编译生成可执行文件的代码分成一步一步来执行。
test:test.ogcc test.o -o test
test.o:test.sgcc -c test.s -o test.o
test.s:test.igcc -S test.i -o test.s
test.i:test.cgcc -E test.c -o test.imake 命令扫描 makefile 文件时
发现依赖关系 test 的依赖文件 test.o 在源文件的当前目录不存在继续向下扫描。发现依赖关系 test.o 的依赖文件 test.s 在源文件的当前目录不存在继续向下扫描。发现依赖关系 test.s 的依赖文件 test.i 在源文件的当前目录不存在继续向下扫描。发现依赖关系 test.i 的依赖文件 test.c 在源文件的当前目录已经存在就会执行 Tab 缩进的代码gcc -E test.c -o test.i 生成 test.i。test.i 依赖文件已经存在啦就会执行gcc -S test.i -o test.s 生成 test.s 文件。test.s 依赖文件已经存在啦就会执行gcc -c test.s -o test.o 生成 test.o 文件。test.o 依赖文件已经存在啦就会执行gcc test.o -o test 生成 test 可执行文件。
在上述过程执行完成之后(使用 make 命令之后)源文件的当前目录下就会生成test.i test.s test.o test 文件。 我们可以看到显示出来命令的执行顺序与我们推导的顺序是一样的哈 综上所述扫描 makefile 文件的时候如果源文件的当前目录不存在依赖文件就会递归似的向下执行这种行为叫做 make 的自动化推导。
清理可执行文件
我们在更改了源文件的代码之后需要清除可执行文件后重新编译。那么清除可执行文件能否使用 make 命令呢那肯定是可以的撒
clean:rm -f test其中clean 是依赖关系冒号右侧为空说明表明没有依赖的文件。那么我们应该如何使用这个依赖关系呢 执行命令make clean 即可。
make clean我们看到顺利运行了呢
将 clean 放在 makefile 文件的最开头
如果我们像这样写 makefile 文件会发生什么呢
clean:rm -f test
test:test.cgcc -o test test.c可以看到我们想要编译文件就需要使用命令make test而 make 命令变成了执行rm -f test。 由此可见make 命令会从上到下扫描 makefile 文件将扫描到的第一个依赖关系作为 make 命令的默认行为。 不推荐将依赖关系 clean 放在 makefile 文件的开头。 make 命令编译多个文件
多个源文件生成一个可执行程序
我们写一个代码在 function.h 中声明一个 Add 函数在 function.c 中实现 Add 函数然后在 test.c 中调用 Add 函数。 function.h
#pragma once
int Add(int a, int b);function.c
int Add(int a, int b)
{return a b;
}test.c
#includestdio.h
#include function.h
int main()
{int a, b;scanf(%d %d, a, b);printf(a b 的结果%d\n, Add(a, b));return 0;
}我们想要编译 function.h function.c test.c 应该怎么做呢其实很简单哈
test:function.c test.cgcc -o test test.c function.c
clean:rm -f test如果是多个源文件生成一个可执行程序只需要在依赖文件中以空格隔开多个源文件即可。如果 .h 文件在源文件的当前目录依赖文件中是不需要写 .h 文件的
多个源文件生成多个可执行程序
如果在 makefile 文件的目录下有多个源文件并且想要将这些个源文件分别编译成可执行文件应该怎么做呢你可以先想一想你应该是有能力写出来的。 我们来写这样两个源文件test1.c 和 test2.c test1.c
#includestdio.hint main()
{printf(i am test1.c\n);return 0;
}test2.c
#includestdio.hint main()
{printf(i am test2.c\n);return 0;
}我们要使用 make 命令讲他们分别编译成test1 和 test2 两个可执行文件。makefile 文件可以这样写
All:test1 test2
test1:test1.cgcc -o test1 test1.c
test2:test2.cgcc -o test2 test2.c
clean:rm -f test1 test2依赖关系All 依赖于 test1 和 test2make 命令扫描 makefile 文件发现源文件当前目录不存在 test1 和 test2 那么就会继续向下扫描。当扫描到 test1 和 test2 这两个依赖关系他们的依赖文件都在源文件的当前目录。可以直接执行他们 Tab 缩进的代码生成 test1 和 test2最后完成两个源文件的编译生成两个可执行文件。
我们可以看到执行 make 命令之后也是顺利生成了 test1 和 test2 两个可执行文件了呢
make 可以重复编译吗为什么
我们还是回到最开始的那个代码 test.c
#includestdio.h
int main()
{printf(hello make!\n);return 0;
}makefile
test:test.cgcc -o test test.c
clean:rm -f test我们发现在不修改代码的情况下是不允许二次编译的 这是为什么呢 显然是因为没有这个必要哈既然你的源文件没有被修改为什么要为你重新编译呢 那这个是怎么做到的呢
一般来说我们都是先有源文件再有可执行程序。这就意味着源文件的最近修改时间比可执行程序的最近修改时间要早。因此我们只需要比较可执行程序的最近修改时间和源文件的最近修改时间就可以判断源文件是否需要重新被编译啦
思考源文件的最近修改时间会和可执行程序的最近修改时间想等吗这个一般是不会的 那么这个用来比较的时间哪里来呢 我们先来学习一个命令吧这个命令可以查看一个文件的时间状态。
stat 文件Access Modify Change 这三个时间称为文件的 ACM 时间。
Access最近访问时间几乎文件的任何操作之后这个时间都会发生改变。Modify当对文件的内容做出修改之后这个时间就会更新。Change当对文件的属性做出修改之后这个时间就会更新。
这就意味着一旦对文件的内容做出修改Access Modify Change 时间都会被更新。 因为 Access 时间要被频繁被修改在实际的实现中 Access 时间的更新是有一定的更新策略(例如当 Modiify 或者 Change 时间到达一定的次数之后再更新 Access 时间)而不是根据 Access 时间的定义那样操作一次文件都要更新这个时间。 原因文件是被存放在磁盘中的将数据刷新到磁盘的速度是比较慢的频繁地修改 Access 时间势必会影响操作系统的效率的。 在判断源文件是否需要重新编译就是根据源文件和可执行程序 Modify 时间的比较结果来判定的 如何验证呢 再来学习一个命令吧
touch 文件名这个 touch 命令除了能够创建一个普通文件还有一个功能就是当这个文件已经存在时能更新一个文件的 ACM 时间到当前的最新时间。 因此我们可以更新源文件的 ACM 时间到最新使得 make 命令可以反复编译一个相同的源文件。 我们看到第一次可以顺利编译这很正常。第二次使用 make 编译的时候就不能了我们在更新源文件的 ACM 时间之后又能使用 make 编译了由此可以验证就是通过比较源文件与可执行文件的时间来判断是否能使用 make 再次编译的
如何让一个依赖关系一直被执行
我们上面讲了通过 touch 命令可以使用 make 一直编译。但是还是不建议这么做没有修改源文件就不要重复编译这很好不是吗 但是清理可执行文件的依赖关系我们就有这个需求让他总是被执行。那么 makefile 文件应该怎么写呢
test:test.cgcc -o test test.c
.PHONY:clean
clean:rm -f testmakefile 文件中被 .PHONY 修饰的依赖关系就可以被一直执行啦 你若不信就可以给可执行文件 test 这个依赖关系加上 .PHONY 修饰看能不能 make 重复编译(不建议这么做)。
特殊符号
$表示依赖关系:依赖方法 中冒号前面的一坨^表示依赖关系:依赖方法 中冒号后面的一坨
那么我们写 makefile 文件就可以这么写啦
test:test.cgcc -o $ $^
.PHONY:clean
clean:rm -f test在这个 makefile 文件中$ 就是 test$^ 就是 test.c。
这才是我们在平时用的最多的 makefile 文件的编写方法啦
取消回显
我们在使用 make 的时候是不是能看到 make 推导出来的要执行的指令的内容像这样 如果你不想回显命令只需要在指令前面加上 符号就可以啦
test:test.cgcc -o $ $^
.PHONY:clean
clean:rm -f test