1.实验目的与要求
- 使用Makefile来管理编译源码,掌握Makefile的基本语法。
- 学习Makefile中的变量的定义和使用,以及常用的特殊变量使用。
- 学习makefile的自动推导功能。
- 学习使用makefile的伪目标。
2.实验平台
实验室安装的实验环境(Linux操作系统)和头歌(www.educoder.net)实验平台(课程实验)
3.实验内容
- Makefile的基本语法。
- Makefile中的变量的定义和使用
- makefile的自动推导功能
- makefile的伪目标
4.实验详细内容、步骤
任务描述
本关任务:使用Makefile
来管理编译源码,掌握Makefile
的基本语法。
相关知识
什么是makefile
?或许很多Winodws
的程序员都不知道这个东西,因为那些Windows
的IDE
都为你做了这个工作,但是要作一个专业的程序员,makefile
还是要懂的。makefile
其实就是描述了整个工程中所有文件的编译顺序,编译规则,并且由make
命令来读取makefile
文件,然后根据makefile
文件中定义的规则对其进行解析,完成对整个项目的编译操作。
makefile
在linux
操作系统中是比较常见的,例如,我们在使用源码安装一个软件的时候,通常只需执行make
命令即可完成对软件的编译,正是因为软件开发者已经编写了makefile
文件,所以只需执行make
命令就会完成对整个工程的自动编译。
本关将介绍makefile
的语法,使用makefile
来完成对软件的编译。
Makefile规则
makefile
文件中包含了一组用来编译应用程序的规则,一项规则可分成三个部分组成:
- 工作目标(target)
- 依赖条件(prerequisite)
- 所要执行的命令(command)
格式为:
- target : prereq1 prereq2
- commands
以上格式就是一个文件的依赖关系,也就是说,target
这个目标文件依赖于多个prerequisites
文件,其生成规则定义在commands
中。说白一点就是说,prerequisites
中如果有一个以上的文件比target
文件要新的话,commands
所定义的命令就会被执行。这就是Makefile
的规则。也就是Makefile
中最核心的内容。
注意
- commands前面使用的是TAB键,而不是空格,使用空格会出现错误;
- commands可以是任意的shell命令;
- 在执行make命令时,make会解析第一项规则;
案例演示1:
存在一个源码文件main.c
文件,编译一个makefile
规则来编译该文件,并生成一个名为HelloWorld
的可执行文件,具体操作如下:
- vim makefile
- make
- 使用
vim
编写如下代码
- #include <stdio.h>
- int main()
- {
- printf("Hello world\n");
- return 0;
- }
- 使用
vim
编写makefile
- HelloWorld : main.c
- gcc -o HelloWorld main.c
[请在右侧“命令行”里直接体验]
通过以上案例可以看到,编写好makefile
后,只需要输入make
命令即自动只需定义好的规则。
注意:gcc -o HelloWorld main.c
命令前是TAB
键而不是空格。
案例演示2:
假设一个项目中包含5
个源码文件,分别是Add.c
、Sub.c
、Mul.c
、Div.c
和main.c
和一个头文件def.h
,编译一个makefile
规则来编译该项目,并生成一个名为exe
的可执行文件,具体操作如下:
- vim makefile
- make
- vim Add.c
- #include <stdio.h>
- int Add(int a, int b)
- {
- return a + b;
- }
- vim Sub.c
- #include <stdio.h>
- int Sub(int a, int b)
- {
- return a - b;
- }
- vim Mul.c
- #include <stdio.h>
- int Mul(int a, int b)
- {
- return a * b;
- }
- vim Div.c
- #include <stdio.h>
- int Div(int a, int b)
- {
- return a / b;
- }
- vim main.c
- #include <stdio.h>
- #include "def.h"
- int main()
- {
- int add = Add(10, 5);
- int sub = Sub(10, 5);
- int mul = Mul(10, 5);
- int div = Div(10, 5);
- printf("10 + 5 = %d\n", add);
- printf("10 - 5 = %d\n", sub);
- printf("10 * 5 = %d\n", mul);
- printf("10 / 5 = %d\n", div);
- return 0;
- }
- vim def.h
- #ifndef __DEF_H__
- #define __DEF_H__
- #include <stdio.h>
- int Add(int a, int b);
- int Sub(int a, int b);
- int Mul(int a, int b);
- int Div(int a, int b);
- #endif
- vim makefile
- exe : main.o Add.o Sub.o Mul.o Div.o
- gcc -o exe main.o Add.o Sub.o Mul.o Div.o
- main.o : main.c def.h
- gcc -c main.c -o main.o
- Add.o : Add.c
- gcc -c Add.c -o Add.o
- Sub.o : Sub.c
- gcc -c Sub.c -o Sub.o
- Mul.o : Mul.c
- gcc -c Mul.c -o Mul.o
- Div.o : Div.c
- gcc -c Div.c -o Div.o
[请在右侧“命令行”里直接体验]
以上案例,当只需make
命令时,首先解析目标为exe
的规则,然后发现exe
依赖于main.o
、Add.o和Sub.o
,然后分别对main.o
、Add.o和Sub.o
规则进行解析,即分别执行目标为main.o
、Add.o和Sub.o
的命令。当main.o
、Add.o和Sub.o
生成后,最后执行exe
对应的命令。
编程要求
本关任务是学会使用makefile
来编译项目。
具体编程要求如下:
- 编写
5
个源文件Add.c、Sub.c、Mul.c、Div.c和main.c和一个头文件def.h,文件内容同案例2
; - 使用
makefile
管理以上项目,并编译生成一个名为Calc
的可执行文件; - vim Add.c
1. 1. #include <stdio.h> 2. 2. int Add(int a, int b) 3. 3. { 4. 4. return a + b; 5. 5. }
- vim Sub.c
1. 1. #include <stdio.h> 2. 2. int Sub(int a, int b) 3. 3. { 4. 4. return a - b; 5. 5. }
- vim Mul.c
1. 1. #include <stdio.h> 2. 2. int Mul(int a, int b) 3. 3. { 4. 4. return a * b; 5. 5. }
- vim Div.c
1. 1. #include <stdio.h> 2. 2. int Div(int a, int b) 3. 3. { 4. 4. return a / b; 5. 5. }
- vim main.c
1. 1. #include <stdio.h> 2. 2. #include "def.h" 3. 3. int main() 4. 4. { 5. 5. int add = Add(10, 5); 6. 6. int sub = Sub(10, 5); 7. 7. int mul = Mul(10, 5); 8. 8. int div = Div(10, 5); 9. 9. 10. 10. printf("10 + 5 = %d\n", add); 11. 11. printf("10 - 5 = %d\n", sub); 12. 12. printf("10 * 5 = %d\n", mul); 13. 13. printf("10 / 5 = %d\n", div); 14. 14. 15. 15. return 0; 16. 16. }