MakeFile的条件判断
关键字
ifeq,else,endif ,ifneq
使用
条件语句从ifeq开始,括号与关键字用空格隔开
应用场景:可以灵活的功能强大,比如一个一个软件希望编译为debug或Release模式。可以通过条件判断变量实现。
.PHONY:all
DEBUG = true
ifeq ($(DEBUG),true)
VERSION = debug
else
VERSION = release
endif
all:
@echo "build $(VERSION) mode"
注意:ifeq 后面有个空格 DEBUG 有个空格 好像有时候没有空格 make时候会报错。
我们可以去掉DEBUGE 后面的 true 再make就会输出release如下
.PHONY:all
DEBUG =
ifeq ($(DEBUG),true)
VERSION = debug
else
VERSION = release
endif
all:
@echo "build $(VERSION) mode"
make输出:build release mode
那么我们就可以再ifeq下面定义编译器了,如下:
.PHONY:all
DEBUG =
ifeq ($(DEBUG),true)
VERSION = debug
CC = gcc -g
else
VERSION = release
cc = gcc
endif
hello:hello.c
@echo "build $(VERSION) mode"
$(CC) -o $@ $^
clean:
rm hello
我们就新建一个hello.c文件
#include <stdio.h>
int main()
{
printf("hello world:\n");
return 0;
}
执行make输出:build release mode
gcc -o hello hello.c
同样我们将DEBUG改成 true
.PHONY:all
DEBUG = true
ifeq ($(DEBUG),true)
VERSION = debug
CC = gcc -g
else
VERSION = release
cc = gcc
endif
hello:hello.c
@echo "build $(VERSION) mode"
$(CC) -o $@ $^
clean:
rm hello
执行make:输出build debug mode
gcc -g -o hello hello.c
如果提示:make: 'hello' is up to date. 请先clean一下,还有需要注意的就是DEBUG 一些目标变量后面的空格键。
我刚开始好多错误,就是因为要么多一个空格要么少一个空格,特别是条件变量需要判断的变量,赋值的地方等。
还有注意:如果是arm下面CC 就需要可能等于ramcc等编译器,判断后面的空格等。
=============================================================================================
函数:函数再Makefile当中也会被大量使用,除了规则就是函数和变量被大量的使用了。而大量的变量和函数被使用的目的也是为规则服务的。为了更好的构建makefile的依赖关系。所以我们必须掌握常用的函数以及搞清楚。这样在分析复杂的makefile才能够游刃有余。
一般我们百度都能找到搜索到MakeFile的中心手册,里面列举了很多函数。
我这里总结一下函数怎么使用使用方法,另我也不推荐大家去学书“深度理解软件构造原理与最佳实战”,对软件底层构造有深度理解。虽然好但是不能但是太耗时。
我们常用的函数有:1,文本处理函数。2,文件名处理函数
看一个例子:
文本处理函数
.PHONY:all
SRCS = player.c lcd.c usb.c media.c hello.h main.txt
OBJS = $(subst .c,.o,$(strip $(SRCS)))
DEPS = $(patsubst %.c,%.d,$(SRCS))
DEPS2 = $(SRCS:.c=.d)
FIND = $(findstring usb,$(SRCS))
FILTER = $(filter %.c %.h, $(SRCS))
all:
@echo "OBJS = $(OBJS)"
@echo "DEPS = $(DEPS)"
@echo "DEPS2 = $(DEPS2)"
@echo "FIND = $(FIND)"
@echo "FILTER = $(FILTER)"
$(subst .....);//字符串替换函数后面是它的参数
$(strip(SRCS)) ;//去空格就是把SRCS的后面的字符串的.c后面的空格去掉。$
$(patsubst ....);//模式替换函数 使用的是% 功能与subst类似但是支持模糊遍历了。就是把里面的所有.c文件替换成.d文件。后面的参数就是字符串。同样后面的DEPS2 的写法是简写也可以的。
findstring 是字符串查找 从后面的参数$(SRCS)字符串查找usb这个字符串。找到就返回找不到就返回结果。如果空的话就返回空就是没有找到。
$(filter ...)//就是过滤从后面的参数$(SRCS)中的字符串中过滤.c .h文件。过滤出来返回给后面的变量。
还有其他的函数大家自己以后学习吧。
执行make输出如下:
OBJS = player.o lcd.o usb.o media.o hello.h main.txt
DEPS = player.d lcd.d usb.d media.d hello.h main.txt
DEPS2 = player.d lcd.d usb.d media.d hello.h main.txt
FIND = usb
FILTER = player.c lcd.c usb.c media.c hello.h
可以 看出OBJS 后面.c 变成了 .o
DEPS 后面变成了.d了。DEPS2 与DEPS 效果一样。为了简单可以按照下面DEPS2这样写。
filter-out与filter效果相反的,除了过滤除去还可以相反的保留下来其他过滤出去。
接下来我们再看看文件名函数,:即处理文件,文件名,文件名前缀,后缀,连接等
makefile内容如下:
.PHONY:all
LIB = /home/hello/libhello.a
LIB1 = $(dir $(LIB))
LIB2 = $(notdir $(LIB))
LIB3 = $(suffix $(LIB))
LIB4 = $(basename $(LIB))
LIB5 = $(addsuffix .c,$(LIB4))
LIB6 = $(addprefix /usr/lib/,$(LIB2))
SRCS = $(wildcard *.c)
all:
@echo "LIB1 = $(LIB1)"
@echo "LIB2 = $(LIB2)"
@echo "LIB3 = $(LIB3)"
@echo "LIB4 = $(LIB4)"
@echo "LIB5 = $(LIB5)"
@echo "LIB6 = $(LIB6)"
@echo "SRCS = $(SRCS)"
执行make输出如下:
LIB1 = /home/hello/
LIB2 = libhello.a
LIB3 = .a
LIB4 = /home/hello/libhello
LIB5 = /home/hello/libhello.c
LIB6 = /usr/lib/libhello.a
SRCS = 3.c hello.c main.c
因为我们的最后echo就输出了这么多,我们可以看出。
LIB1 取目录 LIB2去除了目录。
LIB3取后缀。LIB4取前缀
LIB5 添加一个后缀
LIB6 对LIB2添加了一个目录。
SRCS最后wildcard 函数是列举当前目录下的所有的.c文件。
除此之外还有其他常见的函数:特别重要的是foreach函数相当于C语言的for循环。
还有shell函数可以直接使用shell命令。
foreach例子如下makfile内容
1
2 A = 1 3 4 5 6 7 8 9
3 B = $(foreach i,$(A),$(addprefix 0.,$(i)))
4 C = $(foreach i,$(A),$(addsuffix .0,$(i)))
5
6
7 all:
8 @echo "A = $(A)"
9 @echo "B = $(B)"
10 @echo "C = $(C)"
注意上面的括号配对,上面的例子的第三行的foreach 就是 对字符串A 的字符依次赋值给i,那么对i进行什么操作呢?由后面的参数决定,我们上面说了addprefix 加个前缀0.
后面的第四行一样是加个后缀 .0 最后输出
我们执行make 输出如下:
A = 1 3 4 5 6 7 8 9
B = 0.1 0.3 0.4 0.5 0.6 0.7 0.8 0.9
C = 1.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0
我们接下来看看shell函数的使用:
makefile内容如下:
1 .PHONY:all clean
2 $(shell mkdir -p s1)
3 $(shell mkdir -p s2)
4 all:
5 @echo "hello world"
6 clean:
7 rm -r s1 s2
就是在makefile里面直接运行shell命令,直接加$(shell ...)就可以了。
我们执行make输出如下:hello world 再ls查看已经有了s1 s2 文件夹了。
函数这东西就是最后查手册。。makefile中文手册自己看吧。自己慢慢练习吧