前言
虽然现代的IDE已经提供了较为完善的c编译手段,使得程序员只需注意程序的设计,而不必考虑编译路径。然而学习make还是有其特有的作用的,特别是当你使用学校的电脑写c时😢。
什么是make?
在介绍mke之前,我们先来看看我们要如何使用gcc(GNU C Compiler)编译C语言:
gcc -o hello hello.c意思是使用gcc编译器,编译hello.c,并将编译后生成的可执行程序命名为hello。
假如说要使用的程序有100个.c文件,难道每次编译都要写100次gcc命令吗,能不能只写一次编译命令到一个文件里,然后每次需要编译时执行那个文件就行?于是make便诞生了。
让我们使用make的方法编译上面的程序,首先编写Makefile文件:
//Makefile文件
hello:hello.c
gcc -o hello hello.c这相当于告诉make:hey,make,检查hello文件,如果需要编译,你需要依赖hello.c文件,在依赖完成后,执行
gcc -o hello hello.c这个指令。归纳一下,makefile可以表达为
target: dependencies //target任务文件的依赖
command 1
command 2
...
command n //target任务所执行的命令 需要注意的时make时增量编译的,所以尽量将target任务文件命名为command生成的文件,关于这部分内容的详细解释,见文档。
重定向
虽然管道键 | 可以连接命令与命令:
ls / | grep "os" //ls / :列出根目录下的所有文件和文件夹。
//| (管道符)把 ls / 的输出结果传递给grep命令搜索“os”字符但是却不能连接命令与文件(文件和文件是什么呢?cp,cat…),而重定向解决了这个问题,将input.txt作为输入,交给calc可执行文件处理:
./calc < input.txt //启动./calc程序,将标准输入从键盘切换为input.txt (输入重定向)如果想要把 ./calc 程序的结果输出到outcome.txt:
./calc > outcome.txt //启动./calc程序,将标准输出从屏幕切换为input.txt (输入重定向)综合一下,启动./calc程序,用input.txt作为输入,outcome.txt作为输出:
./calc < input.txt > output.txt
//cat input.txt | ./calc > output.txt √
//cat input.txt | ./calc | output.txt ❌ 管道符 | 的右边必须是一个命令总结一下:
| 符号 | 作用 | 记忆点 |
> | 覆盖输出 | 漏斗指向文件,旧的冲走 |
>> | 追加输出 | 漏斗指向文件,叠在一起 |
2> | 重定向错误 | 专门管报错 |
< | 输入重定向 | 文件流向命令 |
练习题
接下来让我们看回OSpre的题目:

我们需要做:
1.调用casegen生成测试样例,重定向到特定文件中。
2.合并文件
3.调用calc计算合并的文件
4.清除
1.生成测试样例,重定向到特定文件中
case_add:casegen
./casegen add 100 > case_add //以生成case_add为例,其依赖于casegen程序,
casegen:casegen.c
gcc -o casegen casegen.c //编译casegen.c,生成可执行程序2.合并文件
case_all:case_add case_sub case_mul case_div
cat case_add case_sub case_mul case_div > case_all //合并所有程序,依赖于case_xxx文件
//命令:将case_xxx文件合并3.调用calc计算合并的文件为out
out: calc case_all
./calc < case_all > out //依赖和命令分别是什么?
calc:calc.c
gcc -o calc calc.c4.清除
这里的.PHONY是为了让make每次都执行clean。
最终代码:
.PHONY: clean
out: calc case_all
./calc < case_all > out
casegen:casegen.c
gcc -o casegen casegen.c
calc:calc.c
gcc -o calc calc.c
case_add:casegen
./casegen add 100 > case_add
case_sub:casegen
./casegen sub 100 > case_sub
case_mul:casegen
./casegen mul 100 > case_mul
case_div:casegen
./casegen div 100 > case_div
case_all:case_add case_sub case_mul case_div
cat case_add case_sub case_mul case_div > case_all
clean:
rm -f out calc casegen case_* *.o
以下是make的依赖树:
