Makefile学习2

简介: Makefile学习2

Makefile学习2


Makefile条件判断

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


ifeq 关键字

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

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

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

ifeq一般和变量结合使用:

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。

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中,没有定义的变量的值为空),表达式为真。

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

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

$(function arguments)
${function arguments}


注意:

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

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

SRC  = $(wildcard *.c)
HEAD = $(wildcard *.h)
all:
    @echo "SRC = $(SRC)"
    @echo "HEAD = $(HEAD)"


用户自定义函数

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

给函数传递的参数在函数中使用( 0 ) 、 (0)、(0)、(1)引用。

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

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

$(subst old,new,text)


.PHONY: all
SRC  = $(wildcard *.c)
OBJ  = $(subst .c,.o,$(SRC))
all:
    @echo "OBJ = $(OBJ)"
    @echo $(subst banana, apple, "banana is good, I like banana")
# 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如果都包含这个通配符,表示两者表示的是相同的若干个字符,并执行替换操作。

.PHONY: all
SRC  = $(wildcard *.c)
OBJ  = $(patsubst %.c, %.o, $(SRC))
all:
    @echo "OBJ = $(OBJ)"


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

.PHONY: all
STR =     hello a    b   c   
STRIP_STR = $(strip $(STR))
all:
    @echo "STR = $(STR)"
    @echo "STRIP_STR = $(STRIP_STR)"


# make
STR = hello a    b   c   
STRIP_STR = hello a b c

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

ifeq ($(strip $(foo)),)
    echo "foo is empty"
endif


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

$(findstring FIND, IN)


.PHONY: all
STR =     hello a    b   c   
FIND = $(findstring hello, $(STR))
all:
    @echo "STR = $(STR)"
    @echo "FIND = $(FIND)"

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

$(filter PATTERN…,TEXT)


.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模式的单词,保留所有不符合此模式的单词。

.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中的单词以首字母为准进行排序,并删除重复的单词。

.PHONY: all
FILE = e.c a.c b.h c.s d.cpp   
all:
  @echo "FILE = $(FILE)"
  @echo $(sort $(FILE))


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

$(word N,TEXT)


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

$(wordlist N, M, TEXT)


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

$(words TEXT)


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

$(foreach VAR,LIST,TEXT)


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


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

.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时会自动对其进行匹配处理

test: *.o
    gcc -o $@ $^
*.o: *.c
    gcc -c $^


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

clean:
    rm -f *.o


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

$(wildcard *.c)


相关文章
|
7月前
|
编译器 Shell Linux
Makefile(3)进阶
Makefile(3)进阶
55 0
|
7月前
|
Shell Linux C++
Makefile编译实战
Makefile编译实战
94 0
|
C语言
Makefile教程(Makefile的结构)
Makefile教程(Makefile的结构)
110 0
|
4月前
|
编译器 Linux C语言
Makefile实战论(一)
Makefile实战论(一)
|
7月前
Makefile(1)入门
Makefile(1)入门
53 0
|
IDE 编译器 程序员
Makefile零基础教学(一)初识makefile
Makefile零基础教学(一)初识makefile
174 1
Makefile零基础教学(一)初识makefile
|
编译器 Shell Linux
Makefile学习1
Makefile学习1
|
IDE Linux Shell
【Makefile】简单的Makefile编写
【Makefile】简单的Makefile编写
|
Java Linux 程序员
玩转Makefile | 一文入门Makefile
玩转Makefile | 一文入门Makefile
244 0
玩转Makefile | 一文入门Makefile
|
XML C++ 数据格式
Makefile的常用技术总结
一、MAKE中的自动变量:    $@: 表示target的名字    $%: 仅当目标是函数库文件中,表示规则中的目标成员名。例如,如果一个目标是"foo.a(bar.o)",那么,"$%"就是"bar.o","$@"就是 "foo.a"。    $
773 0