• makefile个人笔记


    基本形式

    target: prerequisites(also can be targets)
    	command
    
    • 1
    • 2

    target可以为文件名,也可以为一个随意的字符串,make默认执行第一个有效target
    执行逻辑:

    1. 检查前置条件,并达成所有前置条件
    2. 执行所有的command

    扩展形式(可有部份文件不触发make)

    target: prerequisites(also can be targets)|prerequisites(changes will not remake)
    	command
    
    • 1
    • 2

    匹配模式

    target:target-pattern:prereq-patterns:
    	command
    
    • 1
    • 2
    objs:=a.o b.o
    all:$(objs) #
    $(objs):%.o:%.c
    	cc -c $< -o $@
    .PHONY:clean
    clean:
    	rm *.o
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    a.o b.o:%.o:%.c #只会生成a.o
    	cc -c $< -o $@
    .PHONY:clean
    clean:
    	rm *.o
    
    • 1
    • 2
    • 3
    • 4
    • 5

    双冒号模式(可存在多个相同目标,每个目标由不同的依赖触发)

    test: a.c
    	cc -c $< -o a.o
    test: b.c
    	cc -c $< -o b.o
    
    • 1
    • 2
    • 3
    • 4

    会有警告并只执行后者

    test:: a.c
    	cc -c $< -o a.o
    test:: b.c
    	cc -c $< -o b.o
    
    • 1
    • 2
    • 3
    • 4

    打印一个 hello

    test:
    	echo hello 
    
    • 1
    • 2

    使用@可以不回显执行的命令

    test:
    	@echo hello 
    
    • 1
    • 2

    make支持的变量仅有字符串类型

    定义方式

    1. = = =,运行时展开,可使用先于声明
    2. : = := :=,编译时展开
    3. ? = ?= ?=,条件定义
    4. d e f i n e define define,多行变量

    变量定义1

    运行时展开变量,被读入的变量如果是引用其它的变量,则直到其被使用时,
    才对其进行展开,这种变量使用 = = = 号赋值。

    var1=$(val2)
    val2=$(val3)
    val3="hello "world
    test:
    	@echo $(var1)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    变量定义2

    编译时展开变量,使用符号 : = := :=
    无法使用在该变量定义的代码前无定义的变量。

    var1:=1
    var2:=$(var1)2"3"
    test:
    	@echo $(var2)
    
    • 1
    • 2
    • 3
    • 4

    变量定义3

    多行变量

    define var
    echo foo
    echo hello
    endef
    test:
    	$(var)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    类似程序中的局部变量

    var=fuck
    all:test
    	echo $(var)
    test:var=hello
    test:
    	echo ${var}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    模式匹配版本

    var=fuck
    %haha:var=hahafuck
    all:test ahaha fuckhaha
    
    test:
    	echo $(var)
    ahaha:
    	echo $(var)
    fuckhaha:
    	echo $(var)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    字符串末位替换

    写法1

    var2:=123456
    var1:=$(var2:456=abc)
    test:
    	@echo $(var1)
    
    • 1
    • 2
    • 3
    • 4

    写法2

    var2:=123456
    var1:=$(var2:%456=%abc)
    test:
    	@echo $(var1)
    
    • 1
    • 2
    • 3
    • 4

    写法3

    var2:=123456
    var1:=$(var2:%456=%abc)
    test:
    	@echo $(patsubst %456,%abc,$(var2))
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    预定义变量

    $@:
    注意,模式匹配的单个目标会展开成多个目标

    test:atest btest
    	@echo test
    %test:
    	@echo $@
    
    • 1
    • 2
    • 3
    • 4
    test fuck:
    	@echo $@
    
    • 1
    • 2

    条件判断

    1. ifdef,ifndef,ifeq,ifneq,else,endif
    var=fuck
    test:
    ifeq ($(var),fuck)
    	echo yes
    else 
    	echo no
    endif
    	echo fuck
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    注意if表示不为空取后者,没有与else endif配合

    var=cd
    test:
    	echo $(if $(var),${var},c)
    
    • 1
    • 2
    • 3

    循环

    test:
    	echo $(foreach i,a b c d, $(i)hello)
    
    • 1
    • 2

    函数

    var=$(2)$(1)
    test:
    	echo $(call var,a ,b)
    
    • 1
    • 2
    • 3
    listf = $(filter $(if $(2),$(addprefix %.,$(2)),%),\
    		  $(wildcard $(addsuffix $(SLASH)*,$(1))))
    test:
    	echo $(call listf,*.c)
    
    • 1
    • 2
    • 3
    • 4

    不展开变量的函数

    var=${hello}
    hello=fuck
    test:
    	echo $(var)
    	echo $(value var)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    eval函数

    1. 基础用法
      将变量定义的字符串转成makefile代码
    $(eval var=hello)
    all:
    	@echo $(var)
    
    • 1
    • 2
    • 3
    1. 将多行文本转化成makefile代码
    define macrotarget
    all:
    	@echo macrotarget
    endef
    $(eval $(call macrotarget))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 配合makefile变量和macro参数使用
    var=var
    define mfunc
    $(1):
    	@echo $(var)
    	@echo $(1)
    endef
    $(eval $(call mfunc,hello))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1. 二次展开
    var1=var2
    var2=var3
    define two
    $${${var1}}=test
    endef
    $(info $(call two))
    $(eval $(call two))
    all:
    	echo ${var3}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    var2=var3
    $(eval ${var2}=test)
    all:
    	echo ${var3}
    
    • 1
    • 2
    • 3
    • 4

    预定义的文本处理函数

    调用格式$ ( f u n c t i o n , p a r a m s ) (function,params) (function,params)
    局部替换函数

    全局替换

    $(subst FROM,TO,TEXT) #将text中的FROM换成TO
    
    var=fuckfuck
    test:
    	echo $(subst fuck,hello,${var})
    
    • 1
    • 2
    • 3
    • 4
    • 5

    尾部替换

    var=a.c.c #针对变量的简洁写法
    test:
    	echo $(patsubst %.c,%.o,a.c.c)
    	echo $(var:.c=.o) #针对变量的简洁写法
    
    • 1
    • 2
    • 3
    • 4

    空格去除

    var=     a  b c
    test:
    	echo $(strip $(var))
    
    • 1
    • 2
    • 3

    查找匹配字符串,成功返回该字符串,否则空串

    test:
    	echo $(findstring abc,abcd)
    	echo $(findstring abc,abdc)
    
    • 1
    • 2
    • 3

    过滤掉不符合模式的字符串

    test:
    	echo $(filter %.c,a.c b.c b.c.c a.o)
    
    • 1
    • 2

    反向过滤

    test:
    	echo $(filter-out %.c,a.c b.c b.c.c a.o)
    
    • 1
    • 2

    排序(首字母升序)

    test:
    	echo $(sort a bc cb A B C)
    
    • 1
    • 2

    取单词

    test:
    	echo $(word 1, a bc cb A B C)
    
    • 1
    • 2

    取多个单词

    test:
    	echo $(wordlist 1,3, a bc cb A B C)
    
    • 1
    • 2

    计算有多少个单词

    test:
    	echo $(words 1,3, a bc cb A B C)
    
    • 1
    • 2

    预定义文件处理函数

    取目录

    test:
    	echo $(dir /mnt/a/a.c /test/a.a)
    
    • 1
    • 2

    取文件名

    test:
    	echo $(notdir /mnt/a/a.c a.c)	
    
    • 1
    • 2

    取文件名后缀(没后缀则忽略,不产生空串)

    test:
    	echo $(suffix /mnt/a/a.c b a.c)	
    
    • 1
    • 2

    取文件名(不包括后缀)

    test:
    	echo $(basename /mnt/a/a.c b a.c)
    
    • 1
    • 2

    给文件添加后缀

    test:
    	echo $(addsuffix .haha, /mnt/a/a.c b a.c)	
    
    • 1
    • 2

    给文件添加前缀(注意文件名不要包括目录)

    test:
    	echo $(addprefix hello_, /mnt/a/a.c b a.c)
    
    • 1
    • 2

    文件名拼接

    test:
    	echo $(join a b,.a .b)
    
    • 1
    • 2

    列出当前目录下匹配成功的文件名集合

    test:
    	echo $(wildcard *.c)
    
    • 1
    • 2

    自动化变量

    空目标默认不是最新的
    $@
    显示为test

    test:
    	echo $@ 
    
    • 1
    • 2

    $%

    test(hello):
    	echo $@ $%
    
    • 1
    • 2

    $<

    test(hello):r1 r2 r3
    	echo $<
    r1 r2 r3:
    
    • 1
    • 2
    • 3

    ? 假 设 a . o 存 在 , b . o 不 存 在 , ? 假设a.o存在,b.o不存在, ?a.ob.o?=b.o

    ab.a:a.o b.o
    	echo $?
    	ar rcs ab.a a.o b.o 
    
    • 1
    • 2
    • 3

    $^ 表示所有依赖

    test:c d e f
    	echo $^
    a b c d:
    
    
    • 1
    • 2
    • 3
    • 4

    二次扩展

    .SECONDEXPANSION:
    main_OBJS := main.o try.o test.o
    lib_OBJS := lib.o api.o
    
    all: main lib
    main lib: $$($$@_OBJS)
    	echo $^
    
    main.o try.o test.o:
    
    lib.o api.o:
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
  • 相关阅读:
    【随笔】Git 高级篇 -- 分离 HEAD(十一)
    MogaFX— 阿根廷政府规制购买美元
    ElasticSearch统计总数据量
    dpdk 内存管理 原理剖析
    【04-提升模型性能:集成学习与超参数优化】
    解析人工智能管理对社会生产力的发展
    QT-信号与槽机制学习笔记
    网课答案公众号零基础怎么制作(内含详细教程)
    【字符串的copy Objective-C语言】
    婚纱租赁系统毕业设计,婚纱租赁管理系统设计与实现,论文毕设作品参考
  • 原文地址:https://blog.csdn.net/weixin_39057744/article/details/128050806