Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Makefile的通配符与变量的使用 #61

Open
ZhangZhiyuan-2021 opened this issue Jun 16, 2022 · 1 comment
Open

Makefile的通配符与变量的使用 #61

ZhangZhiyuan-2021 opened this issue Jun 16, 2022 · 1 comment

Comments

@ZhangZhiyuan-2021
Copy link

Makefile通配符与变量的使用

Makefile在我们上课时详细介绍,他为我们提供了“自动编译”的功能,只需要简短的命令,就能将整个工程文件重新编译,极大的降低了工程修改的成本,并提高了软件开发的效率。这里我们介绍一些Makefile的较高级用法。


Makefile的通配符

Makefile支持使用shell命令,因此在Makefile中可以直接使用shell所支持的一些通配符,如*%?[……]等。

与正则表达式极其类似,其中,*%表达匹配任意个字符,?表示匹配任意一个字符,[……]表示将指定需要匹配的内容放入[]中。

例如:

test:*.cpp
	g++ -o $@ $^
clean:
	rm -rf *.o test

在以上代码中,我们看到,*既可以用在规则中,也可以用在规则的命令中,此处即表示任意的以.cpp或.o结尾的文件。


需要特别指出的是,%*作用极其类似,但%将我们需要的所有文件组合成为一个列表,从列表中依次取出的每一个文件,%即为取出文件的文件名。

例如:

test:*.o
	g++ -o $@ $^
%.o:%.cpp
	g++ -c $< -o $@

这段代码即表示依次取出%.cpp文件。执行命令直至列表中文件为空。

这就是Makefile中的静态模规则:规则存在多个目标,并且不同的目标可以根据目标文件的名字来自动构造出依赖文件。


Makefile的变量

Makefile中定义变量的语法为:变量名称=值列表,等号左右对于空白符无要求,值列表可以是任意项,并且不需要使用数据类型。

在调用变量的时候可以使用$(VALUE_LIST){VALUE_LIST}

而使用变量的优点在于,当我们需要添加或者是删除某个依赖文件的时候,我们只需要改变变量的值即可。

例如:

TEST = main.o test1.o test2.o test3.o
test:$(TEST)
	g++ -o test $(TEST)

而变量赋值的基本方法有四种,分别是:

  • 简单赋值 ( := ) :类比为c++中的普通赋值,只改变该变量。
  • 递归赋值 ( = ) :类比为c++中的引用,赋值语句可能改变多个变量。
  • 条件赋值 ( ?= ) 如果变量未定义,则使用符号中的值定义变量。如果该变量已经赋值,则该赋值语句无效。
  • 追加赋值 ( += ) 将原变量用空格隔开的方式追加一个新值。

例如:

#简单赋值
a:=friend
b:=$(b)s
a:=guy
#递归赋值
c=friend
d=$(d)s
c=guy
#条件赋值
e:=friend
f:=$(e)s
e?=guy
#追加赋值
g:=friend
h:=$(g)s
g+=$(h)
#输出检验结果
test:
      @echo "a=>$(a)"
      @echo "b=>$(b)"
      @echo "c=>$(c)"
      @echo "d=>$(d)"
      @echo "e=>$(e)"
      @echo "f=>$(f)"
      @echo "g=>$(g)"
      @echo "h=>$(h)"

在命令行执行make test,则有:

a=>friend
b=>friends
#在给b赋值的引用了变量a:$(a)
c=>guy
d=>guys
#随着c变化,采取递归赋值的d跟随变化
e=>friend
f=>friends
#e已经有值,因此条件赋值未生效
g=>friend
h=>friend friends
#在h=friend后追加空格以及变量g=friends

自动变量

在我们介绍通配符的时候,使用了符号$@$^等,这些符号即为自动变量,它们具有很好的便捷性,如果能良好的使用,会极大地缩减我们的代码量。其中:

  • $@表示目标文件的名称;
  • $^表示的是所有依赖文件的列表,使用空格进行分隔;
  • $<表示第一个依赖的文件名称;
  • $?表示所有比目标文件更新的依赖文件的列表,使用空格进行分隔;
  • $%表示静态库的一个成员名;
  • $+$^类似,但$^只记录依赖文件第一次引用的情况,会去掉重复的依赖文件,而$+会保留所有依赖文件中重复出现的文件,可以用于库的引用出现交叉时的情况。

让我们回到刚才的例子:

test:*.cpp
	g++ -o $@ $^
clean:
	rm -rf *.o test

其中$@表示目标文件的名称,在此处被用作命名值,而$^表示所有依赖文件,代表将所有文件统一链接。

test:*.o
	g++ -o $@ $^
%.o:%.cpp
	g++ -c $< -o $@

这段代码的test指令与刚才相同,而第二个指令中,$^表示依赖文件中的第一个,$@代表目标文件,这个指令就是将所有的%.cpp文件编译成为%.o文件。

@Yu-Shi
Copy link
Member

Yu-Shi commented Jul 4, 2022

OK

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants