嵌入式makefile实验_嵌入式基础

嵌入式makefile实验_嵌入式基础什么是通配符?学过其他编程语言的可能只要什么叫通配符,通配符是一种特殊语句,主要有星号(*)和问号(?),用来模糊搜索文件

前面我们介绍了Makefile运行规则,这一章我们介绍Makefile的语法。

1. 通配符

什么是通配符?学过其他编程语言的可能只要什么叫通配符,通配符是一种特殊语句,主要有星号(*)和问号(?),用来模糊搜索文件。当查找文件夹时,可以使用它来代替一个或多个真正字符。

1.1 Makefile常见通配符

Makefile具有较多通配符,但是常见的也就几种。如下所示:

  • %.o或%.c : 该通配符表示任意的.o文件或者.c文件
  • $@ : 表示目标
  • $< : 表示第一个依赖文件
  • $^ : 表示所有依赖文件

1.2 Makefile常见通配符实验

以下为上节课我们使用的Makefile文件

test : main.o sub.o gcc -o test main.o sub.o main.o : main.c gcc -c -o main.o main.c sub.o : sub.c gcc -c -o sub.o sub.c 

我们将使用通配符进行改进,实现我们使用%.o和%.c文件进行改进,

test : main.o sub.o gcc -o test main.o sub.o %.o : %.c gcc -c -o main.o main.c 

运行逻辑:

  • 当一开始运行程序时,没有main.o,那么会向下查找,发现通配符%.o, 那么此时将%替换为main,执行: gcc -c -o main.o main.c 命令
  • 生成main.o后,再次查找依赖sub.o, 发现没有改文件,那么需要往下查找,此时将%替换为sub, 执行gcc -c -o main.o main.c命令,不过意外的是,这里还是生成main.o, 最后还会编译不了 test, 系统报错,相应过程见下图。
    在这里插入图片描述
    需要对上述Makefile进行修改,使用
test : main.o sub.o gcc -o test main.o sub.o %.o : %.c gcc -c -o $@ $< 

$@表示目标 , $<表示第一个依赖文件, 那么当%为main时,此时 $@ 表示main.o, $<表示main.c。当%为sub时,此时 $@ 表示sub.o, $<表示sub.c。 具体运行过程见下图:

在这里插入图片描述
这样就能正常运行了, 不过是否考虑到一个问题,如果有很多OBJ文件呢? 难道我们需要一个一个加上XX.o吗,那么此时gcc -o test main.o sub.o这条语句得使劲加?显然这样是不智能的,我们可以使用$^ : 通配符,表示所有依赖文件,改进的程序如下:

test : main.o sub.o gcc -o test $^ %.o : %.c gcc -c -o $@ $< 

当运行 gcc -o test $^ 命令时,程序会将 $^ 替换为main.o sub.o, 这样的话我们有多个源文件,只需要往sub.o后添加就可以了。下图为运行过程图:
在这里插入图片描述

2. 假想目标

我们先不提什么是假想目标,我们慢慢引入。

2.1 清除中间文件

我们希望删除中间文件(.o文件)和目标文件(test), 以确保我们将编译过程产生的文件全部删除,我们可以在Makefile文件中加入 rm *.o test命令,其中 *.o表示全部的OBJ文件,test为可执行程序。那这条语句应该怎么加入到Makefile文件中呢?我们可以仿造一下,直接写clean: (不需要依赖文件)。当我们输入make时(不带任何参数),此时系统会找到文件的第一个目标文件(第一行的开头的目标:test), 默认执行make test, 此时系统运行第一行,在清楚时,输入make clean, 系统会跳转到clean处,由于不需要依赖文件,所以任何时间都会运行,此时执行rm *.o test 以下为所有代码

test : main.o sub.o gcc -o test $^ %.o : %.c gcc -c -o $@ $< clean: rm *.o test 

下图为实验过程:
在这里插入图片描述

2.2 本地存在clean文件

是否想过一个问题,如果在当前目录存在clean文件,那么当我们运行make clean时会出现什么情况?
在这里插入图片描述

如上图所示:我们使用 > clean命令创建一个空的clean文件,然后再执行make clean, 此时发现显示:make: ‘clean’ is up to date. 这个报错表示clean文件是最新的, 不需要再执行了,这样就不能执行make clean操作了,此时我们可以使用.PHONY: clean 设置clean为假想目标,详细代码如下:

test : main.o sub.o gcc -o test $^ %.o : %.c gcc -c -o $@ $< clean: rm *.o test .PHONY: clean 

下图为详细的试验过程
在这里插入图片描述

3. 变量

3.1 分类及定义

Makefile的变量分为即时变量(也称简单变量)、延时变量,即时变量是在定义时就确定值,而延时变量是在使用时才确定的值,在没使用 时一直为空,以下为使用举例:

  • A := xxx # A的值即刻确定,在定义时即确定
  • B = xxx # B的值使用到时才确定

3.2 实验

3.2.1 使用变量

Makefile中使用变量使用$(变量名称),代码中的all和之前讲的clean类似, 由于代码中只有一个目标文件all,所以在运行时输入make和make all的效果是一样的,echo是Makefile中的打印函数,测试代码如下:

A := abc B = 123 all: echo $(A) echo $(B) 

运行结果:
在这里插入图片描述
上述图中echo abc和echo 123是打印命令,如果不想打印,可以在echo前面加入@,代码如下:

A := abc B = 123 all: @echo $(A) @echo $(B) 

运行结果:
在这里插入图片描述
此时我们还是看不出即时变量和延时变量的区别,接着我们引入一个新变量C,代码如下:

A := $(C) B = $(C) C = abc all: @echo $(A) @echo $(B) 

运行结果:
在这里插入图片描述
有上图可知,A变量值为空, B变量的值为abc。
运行机制如下:运行A := $©时,由于C变量未定义,而且A为即时变量,此时A的值已经确定(为空),运行B = $©时,即使C变量未定义,但是B为延时变量,在引用时才确定值,运动C = abc,定义了延时变量C,运行@echo $(A)直接打印A的值(空),运行@echo $(B)此时先引用B,在引用时C变量已经定义,有值(abc),故此时B的值也确定了(也为abc),故打印abc。
为了更加清晰的看出变量的值,我们加上辅助信息,代码如下:

A := $(C) B = $(C) C = abc all: @echo A = $(A) @echo B = $(B) 

运行结果:
在这里插入图片描述

有人会想是否和C = abc的位置有关呢?我们修改代码如下:

A := $(C) B = $(C) # C = abc all: @echo A = $(A) @echo B = $(B) C = abc 

运行结果:
在这里插入图片描述
由运行结果可知,可位置是没关系的,是因为Makefile文件在运行前会将所有代码读入,当运行make或make all时才生产目标文件。那么我们是否会考虑代码加载的顺序?是从上到下加载吗?我们不妨做个实验:

A := $(C) B = $(C) C = abc all: @echo A = $(A) @echo B = $(B) C = 123 

观察以上代码,如果打印B=123,表示是顺序执行的,并且后面的值覆盖了前面的值
运行结果:
在这里插入图片描述
从上图结果可以看出,的确和我们的猜想是一样的。

3.3 变量运算及赋值方式

3.3.1 常见的赋值方式

  • ?= : 也是延时变量赋值的一种,区别在于如果是第一次定义才起效,如果在前面该变量已定义则忽略这句。
  • +=:附加,它是即时变量还是延时变量取决于前面的定义

3.3.2 赋值方式实验

我们做 += 的实验,运行如下代码:

A := $(C) B = $(C) C = abc all: @echo A = $(A) @echo B = $(B) C += 123 

运行结果:
在这里插入图片描述
由结果可知,C还是为即时变量,因为之前是采用 =进行定义的。

我们再做 ?= 的实验,运行如下代码:

A := $(C) B = $(C) C = abc D = LingTu D ?= LLLS all: @echo A = $(A) @echo B = $(B) @echo D = $(D) C += 123 

运行结果:
在这里插入图片描述
由上图可知,D = LingTu在D ?= LLLS之前定义了, 故D ?= LLLS定义不起效果。
我们再做一个对比,代码如下:

A := $(C) B = $(C) C = abc D ?= LLLS all: @echo A = $(A) @echo B = $(B) @echo D = $(D) C += 123 

运行结果:
在这里插入图片描述
此时D ?= LLLS为第一次定义变量,故起效果。
除了在代码中幅值外,我们也可以在输入命令时赋值,命令行的赋值先于代码中的赋值,实验如下:
在这里插入图片描述
注意命名行赋值时参数不要输入空格,命令行是默认以空格间隔参数的,第一次加入空格报错了。

今天的文章
嵌入式makefile实验_嵌入式基础分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/89698.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注