前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Makefile学习2

Makefile学习2

作者头像
用户9645905
发布2023-10-17 18:02:49
2610
发布2023-10-17 18:02:49
举报
文章被收录于专栏:Linux学习~Linux学习~

Makefile学习2

Makefile条件判断

使用条件判断,可以让make在编译程序时,根据不同的情况,执行不同的分支:可以执行不同的命令,使用不同的编译参数,生成不同的目标。

ifeq 关键字

ifeq关键字用来判断两个参数是够相等,相等时条件成立为true,不相等为false。

条件判断语句由三个关键字组成:ifeq、else、endif。

ifeq后面的比较语句使用小括号抱起来,ifeq和小括号之间要用空格隔开,小括号里的两个参数用逗号隔开。当小括号里的条件满足时,make就会执行这个分支的命令,否则执行else部分。endif表示一个条件语句的结束。

ifeq一般和变量结合使用:

代码语言:javascript
复制
mode = debug
hello: hello.c
ifeq ($(mode),debug)
    @echo "debug mode" 
    gcc -g -o hello hello.c
else
    @echo "release mode"
    gcc -o hello hello.c
endif
ifneq 关键字

ifneq 关键字和ifeq关键字恰恰相反,用来判断参数是否不相等。当比较的参数不相等时,条件语句才成立,值为true,否则为false。

代码语言:javascript
复制
mode = debug
hello: hello.c
ifneq ($(mode),)
    @echo "debug mode" 
    gcc -g -o hello hello.c
else
    @echo "release mode"
    gcc -o hello hello.c
endif

在上面的语句中,我们让mode变量和一个空字符串比较,不相等,条件语句成立。

ifdef 关键字

ifdef 关键字用来判断一个变量是否已经定义。如果变量的值非空(在Makefile中,没有定义的变量的值为空),表达式为真。

代码语言:javascript
复制
mode = 
hello: hello.c
ifdef mode
    @echo "debug mode" 
    gcc -g -o hello hello.c
else
    @echo "release mode"
    gcc -o hello hello.c
endif

如果在Makefile定义一个变量没有赋值,或者没有定义变量,那么这个变量的值都为空。

ifndef 关键字

ifndef关键字和ifdef相反,如果一个变量没有定义,表达式为真。

Makefile函数

GNU make 提供了大量的函数用来处理文件名、变量、文本和命令。通过这些函数,用户可以节省很多精力,编写出更加灵活和健壮的Makefile

函数的使用和变量引用的展开方式相同:

代码语言:javascript
复制
$(function arguments)
${function arguments}

注意:

  • 函数主要分为两类:make内嵌函数和用户自定义函数。对于 GNU make内嵌的函数,直接引用就可以了;对于用户自定义的函数,要通过make的call函数来间接调用。
  • 函数和参数列表之间要用空格隔开,多个参数之间使用逗号隔开。
  • 如果在参数中引用了变量,变量的引用建议和函数引用使用统一格式:要么是一对小括号,要么是一对大括号。

wildcard函数:如果我们想要获取某个目录下所有的C文件列表,可以使用扩展通配符函数

代码语言:javascript
复制
SRC  = $(wildcard *.c)
HEAD = $(wildcard *.h)
all:
    @echo "SRC = $(SRC)"
    @echo "HEAD = $(HEAD)"
用户自定义函数

用户自定义函以define开头,endef结束。

给函数传递的参数在函数中使用

(0)、

(1)引用。

用户自定义函数使用call函数间接调用,各个参数之间使用空格隔开。

代码语言:javascript
复制
PHONY: all
define func
    @echo "pram1 = $(0)"
    @echo "pram2 = $(1)"
endef
all:
    $(call func, hello zz.cc)
文本处理函数

GNU make提供了一系列文本处理函数:subst、patsubst、strip、findstring、filter、filer-out、sort、word、wordlist、words、fistword。

subst函数:用来实现字符串的替换,将字符串text中的old替换为new

代码语言:javascript
复制
$(subst old,new,text)
代码语言:javascript
复制
.PHONY: all
SRC  = $(wildcard *.c)
OBJ  = $(subst .c,.o,$(SRC))
all:
    @echo "OBJ = $(OBJ)"
    @echo $(subst banana, apple, "banana is good, I like banana")
代码语言:javascript
复制
# ls
add.c  add.h  hello.c  main.c  makefile  sub.c  sub.h
# make
OBJ = hello.o main.o add.o sub.o
 apple is good, I like  apple

patsubst函数:主要用来模式替换,使用通配符 % 代表一个单词中的若干字符,在PATTERN和REPLACEMENT如果都包含这个通配符,表示两者表示的是相同的若干个字符,并执行替换操作。

代码语言:javascript
复制
.PHONY: all
SRC  = $(wildcard *.c)
OBJ  = $(patsubst %.c, %.o, $(SRC))
all:
    @echo "OBJ = $(OBJ)"

strip函数:去空格函数,一个字符串通常有多个单词,单词之间使用一个或多个空格进行分割,strip函数用来将多个连续的空字符合并成一个,并去掉字符串开头、末尾的空字符。空字符包括:空格、多个空格、tab等不可显示的字符。

代码语言:javascript
复制
.PHONY: all
STR =     hello a    b   c   
STRIP_STR = $(strip $(STR))
all:
    @echo "STR = $(STR)"
    @echo "STRIP_STR = $(STRIP_STR)"
代码语言:javascript
复制
# make
STR = hello a    b   c   
STRIP_STR = hello a b c

strip函数经常用在条件判断语句的表达式中,去掉多余的空格等因素,确保表达式比较的可靠和健壮。

代码语言:javascript
复制
ifeq ($(strip $(foo)),)
    echo "foo is empty"
endif

findstring函数:用来查找一个字符串,在字符串IN中查找“FIND”字符串,如果找到,则返回字符串FIND,否则,返回空。

代码语言:javascript
复制
$(findstring FIND, IN)
代码语言:javascript
复制
.PHONY: all
STR =     hello a    b   c   
FIND = $(findstring hello, $(STR))
all:
    @echo "STR = $(STR)"
    @echo "FIND = $(FIND)"

filter函数:用来过滤掉一个指定的字符串,用来过滤掉字符串TEXT中所有不符合PATTERN模式的单词,只留下符合PATTERN格式的单词。

代码语言:javascript
复制
$(filter PATTERN…,TEXT)
代码语言:javascript
复制
.PHONY: all
FILE = a.c b.h c.s d.cpp   
SRC = $(filter %.c, $(FILE))
all:
    @echo "FILE = $(FILE)"
    @echo "SRC = $(SRC)"

filer-out函数:是一个反过滤函数,功能和filter函数恰恰相反:该函数会过滤掉所有符合PATTERN模式的单词,保留所有不符合此模式的单词。

代码语言:javascript
复制
.PHONY: all
FILE = a.c b.h c.s d.cpp   
SRC = $(filter-out %.c, $(FILE))
all:
    @echo "FILE = $(FILE)"
    @echo "SRC = $(SRC)"

sort函数:对字符串LIST中的单词以首字母为准进行排序,并删除重复的单词。

代码语言:javascript
复制
.PHONY: all
FILE = e.c a.c b.h c.s d.cpp   
all:
	@echo "FILE = $(FILE)"
	@echo $(sort $(FILE))

word函数:从一个字符串TEXT中,按照指定的数目N取单词

代码语言:javascript
复制
 $(word N,TEXT)

wordlist函数:用来从一个字符串TEXT中取出从N到M之间的一个单词串

代码语言:javascript
复制
$(wordlist N, M, TEXT)

words函数:用来统计一个字符串TEXT中单词的个数

代码语言:javascript
复制
$(words TEXT)

foreach函数:做一些循环或遍历操作

代码语言:javascript
复制
$(foreach VAR,LIST,TEXT)

把LIST中使用空格分割的单词依次取出并赋值给变量VAR,然后执行TEXT表达式。重复这个过程,直到遍历完LIST中的最后一个单词。函数的返回值是TEXT多次计算的结果。

自动搜索各个目录下的C源文件:

代码语言:javascript
复制
.PHONY: all
dirs = lcd usb media keyboard
srcs = $(foreach dir, $(dirs), $(wildcard $(dir)/*))
all:
    @echo "srcs = $(srcs)"

Makefile 通配符

Makefile中表示一个文件名时,可以使用通配符。

Makefile中可以使用的通配符有:* 、? 、 […]。通配符的使用方法和含义和在shell中一样。

通配符

使用说明

*

匹配0个或者是任意个字符

匹配任意一个字符

[]

我们可以指定匹配的字符放在 “[]” 中

除此之外,Makefile还有经常使用的几个自动变量也可以看做特殊通配符:

  • $@:所有目标文件
  • $^:目标依赖的所有文件
  • $<:第一个依赖文件
  • $?:所有更新过的依赖文件

Makefile中,通配符主要用在两个场合:

用在规则的目标和依赖中:make在读取Makefile时会自动对其进行匹配处理

代码语言:javascript
复制
test: *.o
    gcc -o $@ $^
*.o: *.c
    gcc -c $^

用在规则的命令中:通配符的通配处理在shell执行命令时完成

代码语言:javascript
复制
clean:
    rm -f *.o

除了以上两种情况,在其他地方都不能直接使用通配符。需要一些函数(如wildcard)来实现。如果想列举当前目录下的所有C文件,可以直接使用wildcard函数:

代码语言:javascript
复制
$(wildcard *.c)
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-10-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Makefile学习2
    • Makefile条件判断
      • ifeq 关键字
      • ifneq 关键字
      • ifdef 关键字
      • ifndef 关键字
    • Makefile函数
      • 用户自定义函数
      • 文本处理函数
    • Makefile 通配符
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档