Makefile学习之ESP8266官方工程的Makefile

关于如何学习Makefile
成熟工程的Makefile编写会比较复杂,看相关的介绍总会觉得不理解,不清晰
可以尝试自己编写一个简单的Makefile去验证
比如我在一个文件夹下创建a.c 文件,并在同目录下编写一个Makefile,即可测试Makefile的相关语法

#a.c
int main(){
    return 0;
}
#Makefile
LIBODIR := /home
GEN_LIBS :=libfreertos.a libmy.a
OLIBS := $(GEN_LIBS:%= $(LIBODIR)/%)
a:a.c
    @echo $(GEN_LIBS)
    @echo $(LIBODIR)
    @echo $(OLIBS)
    gcc $^ -o $@

此Makefile可用于验证A := $(B:%=$(C)/%)的作用,终端cd到该目录,并输入make,将可得到

 libfreertos.a libmy.a
/home
/home/libfreertos.a /home/libmy.a
gcc a.c -o a

即此语句的作用为:寻找$(GEN_LIBS)中的每一项,并在其前分别加上$(LIBODIR)/,最后给$(OLIBS)赋值,而$(GEN_LIBS) $(LIBODIR)的值均不变


接下来,开始分析ESP8266的Makefile

如代码段3.2和代码段2.1所示,从子目录 ESP8266_RTOS_SDK-master/third_party/freertos/ 中执行Makefile,将会包含上级目录ESP8266_RTOS_SDK-master/third_party/的Makefile,而该Makefile又包含根目录的Makefile。


$LIBODIR

由此可见,代码段1.1中的$LIBODIR实际上等于.ouput/eagle/debug/lib
此时的工作目录在ESP8266_RTOS_SDK-master/third_party/freertos/ 中,
即为ESP8266_RTOS_SDK-master/third_party/freertos/.ouput/eagle/debug/lib
这是LIB文件生成的目录。


$OLIBS

由代码段3.1可知 $GEN_LIBSlibfreertos.a
OLIBS := $(GEN_LIBS:%=$(LIBODIR)/%) 中的%libfreertos
$OLIBS$LIBODIO/libfreertos.a,为目标库文件的完整文件名(即带路径的文件名)


$ (foreach …,…,…) | $(eval ..)

$(A ...)的意思是执行函数A
此处是执行foreach和eval函数
foreach用于遍历循环,而eval用于把内容转化成Makefile语句,即让Make执行eval里面的内容
代码段1.4中的语句的意思是取出$(GEN_LIBS)中的所有元素,对每个元素进行同样的操作,操作内容是让Makefile执行 自定义的命令包
此处命令包的名字叫ShortcutRule,在代码段1.2中有其定义,
同时把$(lib) $(LIBODIR)当作参数传入该命令包
$(lib)是在foreach函数中,从$(GEN_LIBS)得到的每个元素
此处,$(GEN_LIBS)只有一个元素:libfreertos.a
所以该命令包只执行一次


ShortcutRule

由代码段1.2可得,ShortcutRule的内容为
$(1): .subdirs $(2)/$(1)
即把$(1)作为目标文件,把.subdirs$(2)/$(1)作为其依赖文件
$(1)、$(2)分别为第一参数和第二参数
此处$(1)、$(2)分别为$(lib) $(LIBODIR)
则此处的代码展开为
libfreertos.a: .subdirs ESP8266_RTOS_SDK-master/third_party/freertos/.ouput/eagle/debug/lib/libfreertos.a

MakeLibrary

由代码段1.4可得,在确定了目标库文件及其依赖文件后,紧接着对MakeLibrary命令块进行了调用,以生成库文件
传入参数为libfreertoslibfreertos.a
$$(COMPONENTS_$(1))没有定义
$$(DEPENDS_$(1))没有定义
则由代码段1.3可得,
DEP_LIBS_$(1)NULL
DEP_OBJS_$(1)NULL

$$(LIBODIR)/$(1).a: $$(OBJS) $$(DEP_OBJS_$(1)) $$(DEP_LIBS_$(1)) $$(DEPENDS_$(1))
此处的
$$(LIBODIR)/$(1).a实际上就是ShortcutRule中的第二个依赖文件,此处为目标文件
该目标文件依赖$$(OBJS)
由代码段1.1中有$$(OBJS)的赋值,其中$(CSRCS)、$(CPPSRCS)、$(ASRCs)、$(ASRCS)、分别为执行Make的文件夹,也就是ESP8266_RTOS_SDK-master/third_party/freertos/里面的所有.c、.cpp、.s、.S文件
$OBJ则代表所有在上述文件夹里有的源文件所需产生的编译文件.o的完整文件名


相关代码,代码段顺序与文件中顺序一致
以下代码位于 ESP8266_RTOS_SDK-master/ :

#ESP8266_RTOS_SDK-master/Makefile
#代码段1.1
ODIR := .output
#...
OBJS := $(CSRCS:%.c=$(OBJODIR)/%.o) \
        $(CPPSRCS:%.cpp=$(OBJODIR)/%.o) \
        $(ASRCs:%.s=$(OBJODIR)/%.o) \
        $(ASRCS:%.S=$(OBJODIR)/%.o)

DEPS := $(CSRCS:%.c=$(OBJODIR)/%.d) \
        $(CPPSRCS:%.cpp=$(OBJODIR)/%.d) \
        $(ASRCs:%.s=$(OBJODIR)/%.d) \
        $(ASRCS:%.S=$(OBJODIR)/%.d)

LIBODIR := $(ODIR)/$(TARGET)/$(FLAVOR)/lib
OLIBS := $(GEN_LIBS:%=$(LIBODIR)/%)
#ESP8266_RTOS_SDK-master/Makefile
#代码段1.2
define ShortcutRule
$(1): .subdirs $(2)/$(1)
endef
#ESP8266_RTOS_SDK-master/Makefile
#代码段1.3
define MakeLibrary
DEP_LIBS_$(1) = $$(foreach lib,$$(filter %.a,$$(COMPONENTS_$(1))),$$(dir $$(lib))$$(LIBODIR)/$$(notdir $$(lib)))
DEP_OBJS_$(1) = $$(foreach obj,$$(filter %.o,$$(COMPONENTS_$(1))),$$(dir $$(obj))$$(OBJODIR)/$$(notdir $$(obj)))
$$(LIBODIR)/$(1).a: $$(OBJS) $$(DEP_OBJS_$(1)) $$(DEP_LIBS_$(1)) $$(DEPENDS_$(1))
    @mkdir -p $$(LIBODIR)
	$$(if $$(filter %.a,$$?),mkdir -p $$(EXTRACT_DIR)_$(1))
	$$(if $$(filter %.a,$$?),cd $$(EXTRACT_DIR)_$(1); $$(foreach lib,$$(filter %.a,$$?),$$(AR) xo $$(UP_EXTRACT_DIR)/$$(lib);))
	$$(AR) ru $$@ $$(filter %.o,$$?) $$(if $$(filter %.a,$$?),$$(EXTRACT_DIR)_$(1)/*.o)
	$$(if $$(filter %.a,$$?),$$(RM) -r $$(EXTRACT_DIR)_$(1))
endef
#ESP8266_RTOS_SDK-master/Makefile
#代码段1.4
$(foreach lib,$(GEN_LIBS),$(eval $(call ShortcutRule,$(lib),$(LIBODIR))))
...
$(foreach lib,$(GEN_LIBS),$(eval $(call MakeLibrary,$(basename $(lib)))))

以下代码位于 ESP8266_RTOS_SDK-master/third_party/:

##ESP8266_RTOS_SDK-master/third_party/Makefile
#代码段2.1

TARGET = eagle
#FLAVOR = release
FLAVOR = debug

#EXTRA_CCFLAGS += -u

ifndef PDIR # {
GEN_IMAGES= eagle.app.v6.out
GEN_BINS= eagle.app.v6.bin
SPECIAL_MKTARGETS=$(APP_MKTARGETS)
SUBDIRS=    \
    user

endif # } PDIR
#...
INCLUDES := $(INCLUDES) -I $(PDIR)include
sinclude $(SDK_PATH)/Makefile

以下代码位于 ESP8266_RTOS_SDK-master/third_party/freertos/:

#ESP8266_RTOS_SDK-master/third_party/freertos/Makefile
#代码段3.1
ifndef PDIR

GEN_LIBS = libfreertos.a

endif
#ESP8266_RTOS_SDK-master/third_party/freertos/Makefile
#代码段3.2
PDIR := ../$(PDIR)
sinclude $(PDIR)Makefile
#本文件结束
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值