完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
本帖最后由 城东 于 2016-12-6 22:33 编辑
~/Share/SDK/makefile的内容请看上文:https://bbs.elecfans.com/jishu_1098812_1_1.html 上面提到:make之后首先运行~/Share/SDK/et_app/makefile,而在这个makefile中包含了~/Share/SDK/makefile,所以这里就来分析这个makefile,如下: ifndef PDIR endif ifeq ($(COMPILE), xcc) AR = xt-ar CC = xt-xcc NM = xt-nm CPP = xt-xt++ OBJCOPY = xt-objcopy OBJDUMP = xt-objdump else AR = xtensa-lx106-elf-ar #创建静态库的工具 CC = xtensa-lx106-elf-gcc #C语言编译工具 NM = xtensa-lx106-elf-nm #用来列出目标文件的符号清单。Makefile中将产生的目标文件的符号清单列出工具 CPP = xtensa-lx106-elf-g++ #C++语言编译器 OBJCOPY = xtensa-lx106-elf-objcopy #格式转换工具 OBJDUMP = xtensa-lx106-elf-objdump #显示二进制文件信息,查看反汇编代码工具 endif 这里PDIR作为父目录变量没有定义,下面的工作就是定义编译器等等具体工具工具说明: ar:http://blog.chinaunix.net/uid-25909722-id-3080444.html NM:http://www.aiuxian.com/article/p-2137584.html 这些工具在下面有用到。 下来对一些主要变量进行判断处理: BOOT?=none APP?=0 SPI_SPEED?=40 SPI_MODE?=QIO SPI_SIZE_MAP?=0 其中?= 是如果没有被赋值过就赋予等号后面的值 这些变量在前面的说明中的~/Share/SDK/et_app/gen_misc.sh脚本中定义 下面的内容是根据调用make传进来的变量再次进行变量的定义: ifeq ($(BOOT), new) boot = new else ifeq ($(BOOT), old) boot = old else boot = none endif endif ifeq ($(APP), 1) app = 1 else ifeq ($(APP), 2) app = 2 else app = 0 endif endif ifeq ($(SPI_SPEED), 26.7) freqdiv = 1 else ifeq ($(SPI_SPEED), 20) freqdiv = 2 else ifeq ($(SPI_SPEED), 80) freqdiv = 15 else freqdiv = 0 endif endif endif ifeq ($(SPI_MODE), QOUT) mode = 1 else ifeq ($(SPI_MODE), DIO) mode = 2 else ifeq ($(SPI_MODE), DOUT) mode = 3 else mode = 0 endif endif endif addr = 0x01000 ifeq ($(SPI_SIZE_MAP), 1) size_map = 1 flash = 256 else ifeq ($(SPI_SIZE_MAP), 2) size_map = 2 flash = 1024 ifeq ($(app), 2) addr = 0x81000 endif else ifeq ($(SPI_SIZE_MAP), 3) size_map = 3 flash = 2048 ifeq ($(app), 2) addr = 0x81000 endif else ifeq ($(SPI_SIZE_MAP), 4) size_map = 4 flash = 4096 ifeq ($(app), 2) addr = 0x81000 endif else ifeq ($(SPI_SIZE_MAP), 5) size_map = 5 flash = 2048 ifeq ($(app), 2) addr = 0x101000 endif else ifeq ($(SPI_SIZE_MAP), 6) size_map = 6 flash = 4096 ifeq ($(app), 2) addr = 0x101000 endif else size_map = 0 flash = 512 ifeq ($(app), 2) addr = 0x41000 endif endif endif endif endif endif endif 这里我们可以总结如下: boot = new app = 1 freqdiv = 0 mode = 0 size_map = 3 flash = 2048 addr = 0x01000 这里的变量应该是十分有用的变量,值得收藏 下面的内容是: LD_FILE = $(LDDIR)/eagle.app.v6.ld ifneq ($(boot), none) ifneq ($(app),0) ifeq ($(size_map), 6) LD_FILE = $(LDDIR)/eagle.app.v6.$(boot).2048.ld else ifeq ($(size_map), 5) LD_FILE = $(LDDIR)/eagle.app.v6.$(boot).2048.ld else ifeq ($(size_map), 4) LD_FILE = $(LDDIR)/eagle.app.v6.$(boot).1024.app$(app).ld else ifeq ($(size_map), 3) LD_FILE = $(LDDIR)/eagle.app.v6.$(boot).1024.app$(app).ld else ifeq ($(size_map), 2) LD_FILE = $(LDDIR)/eagle.app.v6.$(boot).1024.app$(app).ld else ifeq ($(size_map), 0) LD_FILE = $(LDDIR)/eagle.app.v6.$(boot).512.app$(app).ld endif endif endif endif endif endif BIN_NAME = user$(app).$(flash).$(boot).$(size_map) endif else app = 0 endif 这里主要的目的就是定义BIN_NAME,从前面的定义到这里我们可以推出: LD_FILE = $(LDDIR)/eagle.app.v6.$(boot).1024.app$(app).ld也就是说 LD_FILE = ~/Share/SDK/ld/eagle.app.v6.new.1024.app1.ld BIN_NAME = user$(app).$(flash).$(boot).$(size_map)也就是说BIN_NAME = user1.2048.new.3 这也是最终生成的bin的名字 接下来的内容是: CSRCS ?= $(wildcard *.c) CPPSRCS ?= $(wildcard *.cpp) ASRCs ?= $(wildcard *.s) ASRCS ?= $(wildcard *.S) SUBDIRS ?= $(patsubst %/,%,$(dir $(wildcard */Makefile))) 其中wildcard 使变量中的通配符有效:在Makefile规则中,通配符会被自动展开。但在变量的定义和函数引用时,通配符将失效。这种情况下如果需要通配符有效,就需要使用函数“wildcard”,它的用法是:$(wildcard PATTERN...) 。(摘录于http://blog.csdn.net/liangkaiming/article/details/6267357) 这里的SUBDIRS定义比较复杂,这里首先获得所有*/Makefile结尾的所有目录,也就是获得包含Makefile文件的所有目录,也就是最后有编译工作的所有目录,然后dir函数得到拥有makefile文件的目录部分,然后用空格替换最后最后一个/,这里可以尝试分析~share/SDK/et_app/makefile最后得到~share/SDK/et_app,这里在之前的~/Share/SDK/et_app/makefile已经定义了SUBDIRS,所以并不会执行这里的$(patsubst %/,%,$(dir $(wildcard */Makefile)))函数,让我们看看之前定义的SUBDIRS,如下: SUBDIRS= user sample_lib driver 也就是最后编译的子目录就会在这三个文件里进行 接下来定义输出目录: ODIR := .output OBJODIR := $(ODIR)/$(TARGET)/$(FLAVOR)/obj 这里的:=代表是覆盖之前的值 根据前面的判断可以得出: ODIR = ~shareSDKet_app.output OBJODIR=~shareSDKet_app.outputeagledebugobj,只不过在最后生成的文件中也没有看到这个目录,说明这个只是一个临时目录 注意到了这里程序所在的目录依旧是~shareSDKet_app,只是目前执行的makefile是在~shareSDK下,所以.output依旧是~shareSDKet_app.output而不是~shareSDK.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) 这两个是和编译直接相关的变量,这里定义相互关联性 OBJS从表面上来看是让所有的“.c”,".s",".cpp",".S"文件都在OBJODIR目录下生成相应的“.o”文件,这个写法我也是第一次看到,DEPS就是让所有的“.c”,".s",".cpp",".S"文件都在OBJODIR目录下生成相应的“.d”的依赖文件。以后再慢慢分析。实在琢磨不出上面这些话,逼不得已往下走,在下面无意之中破解了这些话的意思,详情请看OIMAGES的说明。经过下面的分析我们知道:OBJS := $(CSRCS:%.c=$(OBJODIR)/%.o) 的意思是在OBJODIR目录下生成和CSRCS:%.c同名的.o文件,比如说有main.c(不管它在哪个目录)都会在OBJODIR目录下生成main.o,那这样的下来OBJS=file1.o file2.o................ ,这里的file既可以是c文件也可以是CPP文件也可以是.S文件和.s文件。DEPS也是同样的道理。 接下来的内容是: LIBODIR := $(ODIR)/$(TARGET)/$(FLAVOR)/lib OLIBS := $(GEN_LIBS:%=$(LIBODIR)/%) #目前并不知道这是什么意思 应该是GEN_LIBS=LIBODIR IMAGEODIR := $(ODIR)/$(TARGET)/$(FLAVOR)/image OIMAGES := $(GEN_IMAGES:%=$(IMAGEODIR)/%) #和OLIBS一样 BINODIR := $(ODIR)/$(TARGET)/$(FLAVOR)/bin OBINS := $(GEN_BINS:%=$(BINODIR)/%) 到这里我并不能够搜索到GEN_LIBS但是知道GEN_IMAGES= eagle.app.v6.out,GEN_BINS= eagle.app.v6.bin,但是$(GEN_LIBS:%=$(LIBODIR)/%)这句话是什么意思依旧不知道,和这里定义了几个目录,这些目录都是会在下面的编译命令中直接使用的, 在这里我们通过最后的生成目录知道生成的eagle.app.v6.out在~SDKet_app.outputeagledebugimage那这里我们就有理由推测OIMAGES=~shareSDKet_app.outputeagledebugimageeagle.app.v6.out,那么回过来我们可以知道了$(GEN_IMAGES:%=$(IMAGEODIR)/%) 的意思,这里的意思就是说用GEN_IMAGES替换$(IMAGEODIR)/%中的“%”,那么之前的意思我们就知道了,包括 $(GEN_LIBS:%=$(LIBODIR)/%) 和$(GEN_BINS:%=$(BINODIR)/%) 我们可以得到(猜测): LIBODIR=~shareSDKet_app.outputeagledebuglib OLIBS=~shareSDKet_app.outputeagledebuglib IMAGEODIR=~shareSDKet_app.outputeagledebugimage OIMAGES=~shareSDKet_app.outputeagledebugimageeagle.app.v6.out BINODIR=~shareSDKet_app.outputeagledebugbin OBINS=~shareSDKet_app.outputeagledebugeagle.app.v6.bin 接下来: CCFLAGS += -g -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -ffunction-sections -fdata-sections # -Wall 这里设置编译选项CCFLAGS,这些选项都可以在http://blog.csdn.net/earbao/article/details/53153853看到具体的意思,这里将不再分析,接下来: CFLAGS = $(CCFLAGS) $(DEFINES) $(EXTRA_CCFLAGS) $(INCLUDES) DFLAGS = $(CCFLAGS) $(DDEFINES) $(EXTRA_CCFLAGS) $(INCLUDES) 这里设置了 CFLAGS和DFLAGS这里应该是最终编译用到的文件,这些东西前面都有提到,这里不展开了。接下来: define ShortcutRule $(1): .subdirs $(2)/$(1) endef 这里ShortcutRule的作用应该是在 $(2)截取掉$(1),具体作用等用到再看。 befor 2016年12月1日 下面的内容过于复杂,再分析下去对我自己目前而言没有多大的用处,而且目前本人也有很多事要做,工作上面生活上面,所以到了这里本人将不再深究下去,不过这个makefile是一个十分经典的makefile了,有很多东西可以发掘,只不过最近太忙,所以不深究罢了。 直接看重点: all: .subdirs $(OBJS) $(OLIBS) $(OIMAGES) $(OBINS) $(SPECIAL_MKTARGETS) 这是执行make的第一个标签,也是编译的最终语句。这里直接看最后编译打印的语句: xtensa-lx106-elf-gcc -L/home/esp8266/Share/SDK//lib -Wl,--gc-sections -nostdlib -T/home/esp8266/Share/SDK//ld/eagle.app.v6.new.1024.app1.ld -Wl,--no-check-sections -u call_user_start -Wl,-static -Wl,--start-group -lminic -lgcc -lhal -lphy -lpp -ljson -lpwm -lnet80211 -lwpa -lcrypto -lmain -lfreertos -llwip -lespconn -lsmartconfig -letilink -lfac -lairkiss user/.output/eagle/debug/lib/libuser.a sample_lib/.output/eagle/debug/lib/libsample.a driver/.output/eagle/debug/lib/libdriver.a -Wl,--end-group -o .output/eagle/debug/image/eagle.app.v6.out 这里注意到十分重要的连接文件是:/home/esp8266/Share/SDK//ld/eagle.app.v6.new.1024.app1.ld,所以要知道ESP8266整体的运行顺序可以直接看eagle.app.v6.new.1024.app1.ld这个文件。 下面我们就重启一篇文章来说明eagle.app.v6.new.1024.app1.ld这个文件。 这里再次特别声明:本人的真的事情太多太杂,所以这里暂时深究这个文件,但是到了这里我觉得这个文件是一个十分经典的文件,这里我记住了,以后真的有时间有需要我会回来的。 |
|
相关推荐
1 个讨论
|
|
看来,楼主对Makefile很有好几把刷子啊
|
|
|
|
|
|
只有小组成员才能发言,加入小组>>
[小e体验板] 【小体积大智慧】关于体验板的技术问题,看这一篇就够了
2854 浏览 4 评论
【小e1开发板试用体验】分析程序架构四~/Share/SDK/makefile分析
3611 浏览 1 评论
6700 浏览 19 评论
29046 浏览 59 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-24 04:17 , Processed in 0.646551 second(s), Total 74, Slave 56 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号