1148_Makefile学习_Makefile中的目标、变量以及通配符初步

本文详细讲解了Makefile中的目标设定、多个目标的all规则,变量的赋值与引用,以及自动变量的使用,包括通配符在查找文件和处理规则中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    全部学习汇总: https://github.com/GreyZhang/g_makefile

    前面已经简单梳理了关于Makefile中目标的基础信息,接下来增补并且测试几个关于目标的小知识点。顺便,增加部分其他的基础信息。

    如果目标文件有多个,可以设置一个all目标作为多个目标的目标。

all: one two three

one:

    touch one

two:

    touch two

three:

    touch three

clean:

    rm -f one two three

    测试效果如下:

    这是一个比较常规的习惯性写法,可以在很多工程中看到。但是all也并不意味着是Makefile的一个默认target,这个通过简单的修改测试就能够看出来。做部分修改如下:

one:

    touch one

two:

    touch two

three:

    touch three

clean:

    rm -f one two three

all: one two three

    测试效果:

    可以看得出来,如果把all转移到后面,Makefile默认寻找的还是第一个target。

    接下来看一个Makefile中变量的基本使用例子:

files := file1 file2

some_file: $(files)

    echo "Look at this variable: " $(files)

    touch some_file

file1:

    touch file1

file2:

    touch file2

clean:

    rm -f file1 file2 some_file

    测试效果:

    首先说明一下变量的赋值,可以使用 := 来进行赋值,不过=也可以用。再就是变量本身的引用,通过${}或者$()来引用。其次,看看执行的效果可以看得出来,变量的求解其实在命令回显的时候就已经完成了。

files := file1 file2 file3

some_file: $(files)

    echo "Look at this variable: " $(files)

    touch some_file

files := file1 file2 file3

file3:

    echo "Look at this variable: " $(files)

file1:

    touch file1

file2:

    touch file2

clean:

    rm -f file1 file2 some_file

    做一下修改,看一下变量的重复赋值。运行效果如下:

    其实,这个是我第二次尝试成功二次赋值的一个结果。在此之前,我尝试了在一个target的处理规则之中进行赋值失败了。相应的Makefile代码以及出现的提示如下:

files := file1 file2 file3

some_file: $(files)

    echo "Look at this variable: " $(files)

    touch some_file

file3:

    files := file1 file2 file3

    echo "Look at this variable: " $(files)

file1:

    touch file1

file2:

    touch file2

clean:

    rm -f file1 file2 some_file

    从这个效果来看,似乎target并不像一个C语言的函数,而这个处理块中只能够引用而不能够修改变量的值。那么,如同第一种修改方式,在实际的使用中是不是会欠缺一点灵活度呢?

x := dude

all:

    echo $(x)

    echo ${x}

    # Bad practice, but works

    echo $x

    这里看另一个例子,通过这个例子看一下变量的引用。Makefile中的变量引用可以采用${}或者$()的形式。但是省略两种括号也是可以的,但是这并不是一个很好的实践方式。从掌握一门技术的便捷度考虑,其实只要几种方式没有功能上的区分,选择大家用的最多的一种方式就是很好的突破手段。上面的Makefile在执行make时候的输出结果:

    注释的这一行居然被直接回显出来了,这个的确是我意料之外的一个行为。看起来,惊喜满满啊!

all: f1.o f2.o

f1.o f2.o:

    echo $@

# Equivalent to:

# f1.o

#    echo $@

# f2.o

#    echo $@

    运行的效果:

    这里主要是看一下Makefile自动变量$@的效果,它能够包含所有的target名字并提供了类似遍历处理的效果。

# Print out file information about every .c file

print: $(wildcard *.c)

    ls -la  $?

    上面的例子中使用了函数wildcard以及通配符*,用来获取当前目录所有的.c文件。

    运行效果:

    关于wildcard的函数究竟有什么作用还是需要进一步研究,但是做了一个简单的测试如下:

    我在目录中增加了几个包含.c字段的文件只是不是扩展名,上面的函数是捕获不到具体的文件的。也就是说,配合通配符wildcard函数其实是获取指定后缀名的文件名。同样的文件,进一步修改Makefile测试:

# Print out file information about every .c file

print: $(wildcard *.c*)

    ls -la  $?

    运行效果:

    这一次成功捕获到了所有的含有相应字段的文件的文件名。从这两个测试的效果对比来看,其实这个用法进行的是整个字符串完整的匹配而不是部分子串的匹配。我又做了新的测试,用%取代了*,这次的代码不再贴了。但是这次倒是发现了%与*的不同。%也是一个通配符,但是可以匹配子串。也就是说,%.c配合wildcard其实是可以匹配所有的文件名包含.c字段的文件的文件名的。

    这里,截取了别人总结出来的一段说明。前面两行其实是变量的定义,因此第一个会是一个直接的字符串而第二个则是一条命令。由此,one其实是一个字符串;two是简单的通配符的表达,但是这个有一个比较特殊的地方在于如果比配不成功那么可能会导致解析失败(我实际的测试中会提示*.o不存在,也就是说Makefile会直接寻找这样的一个文件名);three以及four其实是等同的,从编写的角度来考虑或许我倾向于用第四种。

    三个常用的自动变量做一个简单的说明,前面其实已经看到了2个。第一个是$@,这个是用来指代所有的target;第二个是$?,用来指代所有的可能更新的依赖文件;第三个是$^,用来指代所有的依赖文件。

    这样关于Makefile中的目标的归总、变量以及自动变量的简单使用以及通配符的基础信息基本就做了一个初步梳理了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值