Makefile学习

一、变量

= := ?= +=的区别

= 最基本的赋值方式,与变量在Makefile中的位置无关,变量自动推导为为最终被指定的值

# 示例1
var=aaa.c
target:
	@echo $(var)
var=bbb.c

root@localhost:~ # make
bbb.c
root@localhost:~ #

# 示例2
var1=aaa
var2=$(var1).c
var1=bbb
target:
    @echo $(var2)

root@localhost:~ # make
bbb.c
root@localhost:~ #

:= 覆盖式赋值,只能推导前面的值

# 示例1
var=aaa.c
var:=bbb.c
target:
    @echo $(var)

root@localhost:~ # make
bbb.c
root@localhost:~ #

# 示例2
var1:=$(var2).c
var2=bbb
target:
    @echo $(var1)

root@localhost:~ # make
.c
root@localhost:~ #

 ?= 会判断该变量在前面是否已经定义过,如果没有定义过才赋值

# 示例1
var=aaa.c
var?=bbb.c
target:
    @echo $(var)

root@localhost:~ # make
aaa.c
root@localhost:~ #

# 示例2
var?=bbb.c
target:
    @echo $(var)

root@localhost:~ # make
bbb.c
root@localhost:~ #

 += 追加赋值,自动以空格分隔

var=aaa.c
var+=bbb.c
target:
    @echo $(var)

root@localhost:~ # make
aaa.c bbb.c
root@localhost:~ #

自动化变量

  1. $@:表示规则中的目标文件名。
  2. $<:表示规则中的第一个依赖文件名。
  3. $^:表示规则中的所有依赖文件列表,以空格分隔并去重。
  4. $?:表示规则中所有比目标文件更新的依赖文件列表。
  5. $*:表示不包括扩展名的目标文件名。
  6. $(@D):表示目标文件所在的目录。
  7. $(@F):表示目标文件的文件名部分。
  8. $(<D):表示第一个依赖文件所在的目录。
  9. $(<F):表示第一个依赖文件的文件名部分。

https://blog.youkuaiyun.com/sunxiaopengsun/article/details/62218843

二、选项

make -n, --just-print        只显示命令,不执行,用于调试Makefile

三、目标和伪目标

https://blog.youkuaiyun.com/oqqHuTu12345678/article/details/125641363

目标和依赖可以单独声明

命令声明在依赖之后

# 先声明目标与依赖
target: dependency1 dependency2

#命令声明在依赖之后就行,不用紧挨着,中间可以有其他代码

# 后面再写命令
target:
	command1
	command2

四、静态模式 

<targets ...>: <target-pattern>: <prereq-patterns ...>
  <commands>

比如:$(OBJ): %.o: %.c

        即OBJ都是以.o为后缀的目标,每个.o目标依赖文件名相同后缀为.c的文件

$(OBJ)可以省略,直接写%.o:%.c

五、内置函数 

$(wildcard pattern1 pattern2 ...) 展开通配符

SRC:=wildcard(*.c *.cc *.cpp *.cxx)
target:
    $(info "source file: $(SRC)")

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

OBJ:=$(patsubst %.c, %.o, $(wildcard *.c))
target:
    $(info "object file: $(OBJ)")

$(filter pattern..., text) 保留符合pattern的字符串

$(filter-out pattern..., text) 过滤掉符合pattern的字符串

SRC:=aaa.cc bbb.cc ccc.cpp ddd.cpp eee.hpp fff.cxx
target1:
    @echo $(filter %.cc, $(SRC))
target2:
    @echo $(filter-out %.hpp %.cxx, $(SRC))

root@localhost:~ # make target1
aaa.cc bbb.cc
root@localhost:~ # make target2
aaa.cc bbb.cc ccc.cpp ddd.cpp
root@localhost:~ #

$(info ...) 打印调试信息

$(warning ...) 打印警告信息

$(error ...) 打印错误信息,并终止Makefile的执行

六、自定义函数 

1.定义

define MY_MAKEFILE_FUNC
    @echo "my name is $(0)"
    @echo "my name is $(1)"
    @echo "my name is $(2)"
    # ...
endef

$(0) 表示函数名

$(1) $(2) ...表示传递给函数的参数

1.调用

$(call MY_MAKEFILE_FUNC PARAM1 PARAM2)

七、include命令

Makefile中使用include命令包含一个文件时,make首先会读取该文件。如果该文件找不到,会继续检查Makefile中是否有一个模式规则匹配该文件,如果有则这个规则会被执行。然后make会重新读取整个Makefile,包括include命令缺失的文件。

dependencies    := oam_shell_main.d

-include $(dependencies)    #如果当前目录找不到oam_shell_main.d

%.d: %.c                    # 模式%.d刚好匹配缺失的文件oam_shell_main.d,则会执行该规则下的命令(以生成oam_shell_main.d)
    $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -MM $< | \
            $(SED) 's,\($*\.o\) *:,\1 $@: ,' > $@.tmp
    $(MV) $@.tmp $@

# 重新读取整个Makefile,包括oam_shell_main.d

有了以上规则,我们在编写Makefile时可以借助其他工具(比如Yacc)自动生成源文件、头文件等

当目标依赖的文件不存在时,make会Makefile中寻找可以生成缺失文件的模式规则,然后执行该规则

# 示例1
target1: oam_xml_res.rc #如果oam_xml_res.rc不存在则执行下面的规则

%.rc: %.rc.in
    sed -i '/#include/r oam_xml_res.h' $<
    $(MV) path/$*.rc $*.rc #移动到指定目录

%.rc:
    $(SHELL) generate.sh  #执行generate.sh或generate.py生成缺失文件
#   $(PYTHON) generate.py


# 示例2
target2: y.tab.c y.tab.h #如果y.tab.c y.tab.h不存在则执行下面的规则

%.c %.h: %.y    # 缺失的.c .h文件都是由yacc工具根据同名的.y生成
    $(YACC.y) --defines $<
    $(MV) y.tab.c $*.c
    $(MV) y.tab.h $*.h
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值