Linux操作系统实验十二 Linux编程技术应用

1.实验目的与要求

  1. 使用Makefile来管理编译源码,掌握Makefile的基本语法。
  2. 学习Makefile中的变量的定义和使用,以及常用的特殊变量使用。
  3. 学习makefile的自动推导功能。
  4. 学习使用makefile的伪目标。

2.实验平台

实验室安装的实验环境(Linux操作系统)和头歌(www.educoder.net)实验平台(课程实验)

3.实验内容

  1. Makefile的基本语法。
  2. Makefile中的变量的定义和使用
  3. makefile的自动推导功能
  4. makefile的伪目标

4.实验详细内容、步骤

任务描述

本关任务:使用Makefile来管理编译源码,掌握Makefile的基本语法。

相关知识

什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些WindowsIDE都为你做了这个工作,但是要作一个专业的程序员,makefile还是要懂的。makefile其实就是描述了整个工程中所有文件的编译顺序,编译规则,并且由make命令来读取makefile文件,然后根据makefile文件中定义的规则对其进行解析,完成对整个项目的编译操作。

makefilelinux操作系统中是比较常见的,例如,我们在使用源码安装一个软件的时候,通常只需执行make命令即可完成对软件的编译,正是因为软件开发者已经编写了makefile文件,所以只需执行make命令就会完成对整个工程的自动编译。

本关将介绍makefile的语法,使用makefile来完成对软件的编译。

Makefile规则

makefile文件中包含了一组用来编译应用程序的规则,一项规则可分成三个部分组成:

  1. 工作目标(target)
  2. 依赖条件(prerequisite)
  3. 所要执行的命令(command)

格式为:

  1. target : prereq1 prereq2
  2.     commands

以上格式就是一个文件的依赖关系,也就是说,target这个目标文件依赖于多个prerequisites文件,其生成规则定义在commands中。说白一点就是说,prerequisites中如果有一个以上的文件比target文件要新的话,commands所定义的命令就会被执行。这就是Makefile的规则。也就是Makefile中最核心的内容。

注意

  1. commands前面使用的是TAB键,而不是空格,使用空格会出现错误;
  2. commands可以是任意的shell命令;
  3. 在执行make命令时,make会解析第一项规则;

案例演示1:

存在一个源码文件main.c文件,编译一个makefile规则来编译该文件,并生成一个名为HelloWorld的可执行文件,具体操作如下:

  1. vim makefile
  2. make
  • 使用vim编写如下代码
  1. #include <stdio.h>
  2. int main()
  3. {
  4.     printf("Hello world\n");
  5.     return 0;
  6. }
  • 使用vim编写makefile
  1. HelloWorld : main.c
  2.     gcc -o HelloWorld main.c

[请在右侧“命令行”里直接体验]

通过以上案例可以看到,编写好makefile后,只需要输入make命令即自动只需定义好的规则。

注意:gcc -o HelloWorld main.c命令前是TAB键而不是空格。

案例演示2:

假设一个项目中包含5个源码文件,分别是Add.cSub.cMul.cDiv.cmain.c和一个头文件def.h,编译一个makefile规则来编译该项目,并生成一个名为exe的可执行文件,具体操作如下:

  1. vim makefile
  2. make
  • vim Add.c
  1. #include <stdio.h>
  2. int Add(int a, int b)
  3. {
  4.     return a + b;
  5. }
  • vim Sub.c
  1. #include <stdio.h>
  2. int Sub(int a, int b)
  3. {
  4.     return a - b;
  5. }
  • vim Mul.c
  1. #include <stdio.h>
  2. int Mul(int a, int b)
  3. {
  4.     return a * b;
  5. }
  • vim Div.c
  1. #include <stdio.h>
  2. int Div(int a, int b)
  3. {
  4.     return a /  b;
  5. }
  • vim main.c
  1. #include <stdio.h>
  2. #include "def.h"
  3. int main()
  4. {
  5.     int add = Add(10, 5);
  6.     int sub = Sub(10, 5);
  7.     int mul = Mul(10, 5);
  8.     int div = Div(10, 5);
  9.     
  10.     printf("10 + 5 = %d\n", add);
  11.     printf("10 - 5 = %d\n", sub);
  12.     printf("10 * 5 = %d\n", mul);
  13.     printf("10 / 5 = %d\n", div);
  14.     
  15.     return 0;
  16. }
  • vim def.h
  1. #ifndef __DEF_H__
  2. #define __DEF_H__
  3. #include <stdio.h>
  4. int Add(int a, int b);
  5. int Sub(int a, int b);
  6. int Mul(int a, int b);
  7. int Div(int a, int b);
  8. #endif
  • vim makefile
  1. exe : main.o Add.o Sub.o Mul.o Div.o
  2.     gcc -o exe main.o Add.o Sub.o Mul.o Div.o
  3. main.o : main.c def.h
  4.     gcc -c main.c -o main.o
  5. Add.o : Add.c
  6.     gcc -c Add.c -o Add.o
  7. Sub.o : Sub.c
  8.     gcc -c Sub.c -o Sub.o
  9. Mul.o : Mul.c
  10.     gcc -c Mul.c -o Mul.o
  11. Div.o : Div.c
  12.     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.	#include <stdio.h>
2.	int Add(int a, int b)
3.	{
4.	    return a + b;
5.	}
  • vim Sub.c
1.	#include <stdio.h>
2.	int Sub(int a, int b)
3.	{
4.	    return a - b;
5.	}
  • vim Mul.c
1.	#include <stdio.h>
2.	int Mul(int a, int b)
3.	{
4.	    return a * b;
5.	}
  • vim Div.c
1.	#include <stdio.h>
2.	int Div(int a, int b)
3.	{
4.	    return a /  b;
5.	}
  • vim main.c
1.	#include <stdio.h>
2.	#include "def.h"
3.	int main()
4.	{
5.	    int add = Add(10, 5);
6.	    int sub = Sub(10, 5);
7.	    int mul = Mul(10, 5);
8.	    int div = Div(10, 5);
9.	
10.	    printf("10 + 5 = %d\n", add);
11.	    printf("10 - 5 = %d\n", sub);
12.	    printf("10 * 5 = %d\n", mul);
13.	    printf("10 / 5 = %d\n", div);
14.	
15.	    return 0;
16.	}
  • vim def.h
1.	#ifndef __DEF_H__
2.	#define __DEF_H__
3.	
4.	#include <stdio.h>
5.	
6.	int Add(int a, int b);
7.	int Sub(int a, int b);
8.	int Mul(int a, int b);
9.	int Div(int a, int b);
10.	#endif
  • vim makefile
1.	Calc : main.o Add.o Sub.o Mul.o Div.o
2.	    gcc -o Calc main.o Add.o Sub.o Mul.o Div.o
3.	
4.	main.o : main.c def.h
5.	    gcc -c main.c -o main.o
6.	
7.	Add.o : Add.c
8.	    gcc -c Add.c -o Add.o
9.	
10.	Sub.o : Sub.c
11.	    gcc -c Sub.c -o Sub.o
12.	
13.	Mul.o : Mul.c
14.	    gcc -c Mul.c -o Mul.o
15.	
16.	Div.o : Div.c
17.	    gcc -c Div.c -o Div.o

任务描述

本关任务:学习Makefile中的变量的定义和使用,以及常用的特殊变量使用。

相关知识

变量的使用可以方便我们编写makefile文件,我们可以使用一个简短的变量来替换一个比较长的字符串,这样我们在使用这个字符串的时候就可以方便的使用变量来替换。除此之外,当我们修改某一个字符串时,如果我们没有使用变量,则我们需要修改使用该字符串的每个地方,如果使用了变量,我们只需要修改变量定义处即可。

makefile 变量的命令可以包含字符、数字、下划线(可以是数字开头),并且大小写敏感。

makefile变量在声明时需要对其进行赋值,而在使用该变量时需要在变量名前加上**$符号 例如$(VARNAME),如果用户需要在makefile文件中使用真实的$字符,则使用$$**表示。

makefile中对变量的赋值方式有三种,分别是:

  1. 递归赋值(=):递归赋值,即赋值后并不马上生效,等到使用时才真正的赋值,此时通递归找出当前的值;
  2. 直接赋值(:=):是将":="右边中包含的变量直接展开给左边的变量赋值;
  3. 条件赋值(?=):只有此变量在之前没有赋值的情况下才会对这个变量进行赋值,所有一般用在第一次赋值;

makefile除了可以自定义变量外,还存在一些系统默认的特殊变量,这些特殊变量可以方便帮助我们快速的编写makefile文件,例如:$@、$<和$^等等。

本关将介绍makefile的变量的定义和使用方法,以及使用特殊变量来编写makefile文件。

Makefile 自定义变量

自定义变量格式:

  • 递归赋值 变量名 = 变量内容
  • 直接赋值 变量名 := 变量内容
  • 条件赋值 变量名 ?= 变量内容

变量的使用格式为: $变量名或者${ 变量名}或者$(变量名)

案例演示1:

在上一关中案例2中的项包含了5个源码文件和一个头文件,如果使用变量来编写makefile则会显示出比较简洁的格式,具体操作如下:

  1. vim makefile
  2. make
  • vim makefile
  1. object=main.o Add.o Sub.o Mul.o Div.o
  2. exe : $(object)
  3.     gcc -o exe $(object)
  4. main.o : main.c def.h
  5.     gcc -c main.c -o main.o
  6. Add.o : Add.c
  7.     gcc -c Add.c -o Add.o
  8. Sub.o : Sub.c
  9.     gcc -c Sub.c -o Sub.o
  10. Mul.o : Mul.c
  11.     gcc -c Mul.c -o Mul.o
  12. Div.o : Div.c
  13.     gcc -c Div.c -o Div.o

[makefile内容]

[请在右侧“命令行”里直接体验]

可以看到,我们使用object来表示main.o Add.o Sub.o Mul.o Div.o,这样我们就可以使用$(object)来表示以上目标文件,而不是每次输入这5个目标文件。

Makefile 特殊变量

makefile常用的特殊变量有:

  1. $@:表示所有目标;
  2. $^:表示所有依赖目标的集合,以空格分隔;
  3. $<:表示依赖目标中第一个目标的名子;

案例演示1:

接着上一个案例中的项目,如果使用特殊变量来编写makefile则会显示出更加简洁的格式,具体操作如下:

  1. vim makefile
  2. make
  • vim makefile
  1. object=main.o Add.o Sub.o Mul.o Div.o
  2. exe : $(object)
  3.     gcc -o $@ $(object)
  4. main.o : main.c def.h
  5.     gcc -c $< -o $@
  6. Add.o : Add.c
  7.     gcc -c $< -o $@
  8. Sub.o : Sub.c
  9.     gcc -c $< -o $@
  10. Mul.o : Mul.c
  11.     gcc -c $< -o $@
  12. Div.o : Div.c
  13.     gcc -c $< -o $@

[请在右侧“命令行”里直接体验]

编程要求

本关任务是学会使用makefile来编译项目。

具体编程要求如下:

  • 编写5个源文件Add.c、Sub.c、Mul.c、Div.c和main.c和一个头文件def.h,文件内容同第一关案例2
  • 使用makefile的变量来编译生成一个名为VarCalc的可执行文件;

•    vim makefile

1.	object=main.o Add.o Sub.o Mul.o Div.o
2.	VarCalc : $(object)
3.	    gcc -o VarCalc $(object)
4.	
5.	main.o : main.c def.h
6.	    gcc -c $< -o $@
7.	
8.	Add.o : Add.c
9.	    gcc -c $< -o $@
10.	
11.	Sub.o : Sub.c
12.	    gcc -c $< -o $@
13.	
14.	Mul.o : Mul.c
15.	    gcc -c $< -o $@
16.	
17.	Div.o : Div.c
18.	    gcc -c $< -o $@

任务描述

本关任务:学习makefile的自动推导功能。

相关知识

make很强大,它可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必要去在每一个.o文件后都写上类似的命令。因为,我们的make会自动识别,并自己推导命令。

只要make看到一个.o文件,它就会自动的把.c文件加在依赖关系中,如果make找到一个main.o,那么main.c就会是main.o的依赖文件。并且 gcc -c main.c 也会被推导出来,于是,我们的makefile再也不用写得这么复杂。

本关将介绍makefile的自动推导功能。

Makefile 自动推导

自动推导格式: 目标 : 其它依赖

案例演示1:

如果使用自动推导模式来编写上一关卡案例中的makefile,则会有更简洁的格式,具体操作如下:

  1. vim makefile
  2. make
  • vim makefile
  1. object=main.o Add.o Sub.o Mul.o Div.o
  2. exe : $(object)
  3.     gcc -o $@ $(object)
  4. main.o : def.h

[请在右侧“命令行”里直接体验]

可以看到,我们只需要为main.o创建一个编译规则,其4个目标文件则不需要为其创建编译规则,因为make会自动的为其构造出编译规则。

编程要求

本关任务是学会makefile中的自动推导。 具体编程要求如下:

  • 修改上一关的makefile,使用自动推导来编译项目,并生成一个名为AutoCalc的可执行文件;

•    vim makefile 

1.	object=main.o Add.o Sub.o Mul.o Div.o
2.	AutoCalc : $(object)
3.	    gcc -o AutoCalc $(object)
4.	
5.	main.o : def.h

任务描述

本关任务:学习使用makefile的伪目标。

相关知识

每个Makefile中都应该写一个清空目标文件(.o和执行文件)的规则,这不仅便于重编译,也很利于保持文件的清洁。

通常,我们在使用源码安装软件的时候,都会在编译完软件后,执行make install这个命令来安装软件,或者执行make clean这个命令清空临时生成的目标文件。以上操作就是利用了makefile的伪目标。

本关将介绍makefile的伪目标。

Makefile 伪目标

makefile使用.PHONY关键字来定义一个伪目标,具体格式为: .PHONY : 伪目标名称

案例演示1:

为上一关卡案例中的makefile添加清空临时目标文件标签clean,具体操作如下:

  1. vim makefile
  2. make
  • vim makefile
  1. object=main.o Add.o Sub.o Mul.o Div.o
  2. exe : $(object)
  3.     gcc -o $@ $(object)
  4. main.o : def.h
  5. .PHONY : clean
  6. clean :
  7.     rm $(object)

[请在右侧“命令行”里直接体验]

可以看到,当我们执行完make命令后会生成多个临时文件,然后我们执行make clean命令后,则会将生成的临时文件删除掉,其实执行make clean命令就是在执行rm main.o Add.o Sub.o Mul.o Div.o

案例演示2:

使用另一个格式来清除临时产生的目录文件和不显示删除命令,具体操作如下:

  1. vim makefile
  2. make
  • vim makefile
  1. object=main.o Add.o Sub.o Mul.o Div.o
  2. exe : $(object)
  3.     gcc -o $@ $(object)
  4. main.o : def.h
  5. clean :
  6.     @echo "clean object files"
  7.     @rm $(object)

[请在右侧“命令行”里直接体验]

可以看到,当我们执行make clean命令后,将不会在终端中显示rm main.o Add.o Sub.o Mul.o Div.o命令。

注意:在命令前加了**@**符号,则不会把命令原样输出在终端。

编程要求

本关任务是学会makefile中的伪目标。 具体编程要求如下:

  • 为上一关的makefile添加自动清理临时文件的伪目标clean,并生成一个名为AutoCleanCalc的可执行文件;

•    vim makefile 

1.	object=main.o Add.o Sub.o Mul.o Div.o
2.	AutoCleanCalc : $(object)
3.	    gcc -o AutoCleanCalc $(object)
4.	
5.	main.o : def.h
6.	
7.	.PHONY : clean
8.	
9.	clean :
10.	    rm $(object)

猜你喜欢

转载自blog.csdn.net/qq_64314976/article/details/131432211