Makefile

缩进必须使用tab

build:
<tab>gcc main.c -o main

include

包含其他makefile文件,原样放在当前位置,一般搜索路径为当前目录,-I指定的目录,/usr/include 等

伪目标

真正的目标最终都会生成一个文件,而伪目标的意思是只执行里面的规则,而不管实际文件存不存在,比如

clean:
    rm *.o

如果当前有clean文件,那么这个命令就不会被执行,应该手动定义为伪目标

.PHONY: clean
clean:
    rm *.o

通配符

~    代表当前用户根目录

*    通配符,比如 *.c

文件搜寻

VPATH变量用来定义Makefile的搜索路径,多个可以使用冒号隔开

VPATH = src:../headers

也可以使用vpath关键字定义

#为符合模式<pattern>的文件指定搜索目录<directories>
vpath <pattern> <directories>

#清除符合模式<pattern>的文件的搜索目录
vpath <pattern>

#清除所有已被设置好了的文件搜索目录
vpath

vapth使用方法中的<pattern>需要包含 % 字符,% 的意思是匹配零或若干字符

比如

vpath %.h ../headers

隐藏执行命令

@符号可以不显示被执行的命令

@echo '----------------'

多条命令相互依赖执行

需要写在一行上,并且使用分号隔开

exec:
    cd /root;pwd

嵌套执行子Makefile

sub:
    cd xxx && $(MAKE)

#同

sub:
    $(MAKE) -C xxx

如果想传递变量到子Makefile,可以使用export

export va = value

define定义命令包

$@即为foo.c,$^即为foo.h

define cmds
echo $@
echo $^
echo this is test
endef

foo.c: foo.h
    $(cmds)

foo.h:
    echo 11

变量相关

变量使用时使用$开头,如果需要使用$本身,那么需要2个比如$$

如果使用=好赋值,那么是没有顺序关系的,只有在需要用到时才会展开,比如

x = $(y)
y = 111

all:
    echo x

但是很容易造成递归调用,比如

CFLAGS = $(CFLAGS) -O0 -g3

最好使用 := ,这样定义是有顺序要求的

定义一个空格技术

nullstring :=
space := $(nullstring) #end of the line

$(nullstring)代表标明变量的值开始了,#代表行的结束,这样中间的空格就被当成space的值

其他高级用法

将变量的.o结尾替换为.c结尾

foo := a.o b.o c.o
bar := $(foo:.o=.c)

把变量的值当成变量名

x = y
y = z
a := $($(x))

first_second = Hello
a = first
b = second
all = $($a_$b)

追加变量值

objects = main.o foo.o bar.o utils.o
objects += another.o

objects = main.o foo.o bar.o utils.o
objects := $(objects) another.o

override覆盖命令行指定的变量定义

默认情况下,命令行定义的变量优先,除非我们加上override

override name := dl

没定义才赋值,如果定义了则什么也不做

foo ?= aaa

条件判断语法

ifeq(arg1, arg2)
xxx
endif

ifeq(arg1, arg2)
xxx
else
zzz
endif

除了ifeq还有ifneq、ifdef等,这里的arg可以加上make的相关函数

函数调用语法

$(<function> <arguments>)
${<function> <arguments>}

函数名和参数之间使用空格隔开,参数之间使用逗号隔开

comma:= ,
empty:=
space:= $(empty) $(empty)
foo:= a b c
bar:= $(subst $(space),$(comma),$(foo))

字符串处理函数

#替换
$(subst <from>,<to>,<text>)

#模式替换
$(patsubst <pattern>,<replacement>,<text>)

#去除开头和结尾空格
$(strip <string>)

#字符串查找,找到返回,找不到返回空
$(findstring <find>,<in>)

#过滤
$(filter <pattern...>,<text>)

#反过滤
$(filter-out <pattern...>,<text>)

#升序排序
$(sort <list>)

#取第n个单词
$(word <n>,<text>)

#取范围单词
$(wordlist <s>,<e>,<text>)

#单词个数统计
$(words <text>)

#取第一个单词
$(firstword <text>)

文件名操作函数

#取目录函数
$(dir <names...>)

#取文件名函数
$(notdir <names...>)

#取后缀函数
$(suffix <names...>)

#去前缀函数
$(basename <names...>)

#加后缀函数
$(addsuffix <suffix>,<names...>)

#连接函数,把list2中的单词对应加到list1后面
$(join <list1>,<list2>)

foreach函数

$(foreach <var>,<list>,<text>)

if函数

$(if <condition>,<then-part>)
$(if <condition>,<then-part>,<else-part>)

call函数

当 make执行这个函数时,<expression>参数中的变量,如$(1),$(2),$(3)等,会被参数<parm1>,<parm2>,<parm3>依次取代。而<expression>的返回值就是 call函数的返回值

$(call <expression>,<parm1>,<parm2>,<parm3>...)
reverse = $(1) $(2)
foo = $(call reverse,a,b)

origin函数

告诉你你的这个变量是哪里来的

#undefined default environment file command line override 
$(origin <variable>)

shell函数

执行操作系统命令,输出作为返回值

contents := $(shell cat foo)

控制make函数

#产生致命错误
$(error <text ...>)

#警告信息
$(warning <text ...>)


make命令

-v    #打印版本号

-C    #先切换目录,再读取makefile
-f    #手动指定makefile文件,默认为Makefile
-I    #指定搜索路径
-w    #打印具体进入目录,离开目录,对嵌套makefile调试非常有帮助

-j    #指定任务数,一般指定为cpu的核数

-i    #忽略所有错误并重新编译
-k    #尽最大可能忽略错误并前进

-n    #只打印,不执行
-s    #不打印执行命令

-r    #不使用隐式规则
-R    #不定义内置变量


上一篇: linux shell 学习记录
下一篇: 无
作者邮箱: 203328517@qq.com