contiki2.6之Makefile详细解读四

来源:互联网 发布:linux如何安装显卡驱动 编辑:程序博客网 时间:2024/06/05 21:31

     上次分析到了这里:

CONTIKI_TARGET_DIRS_CONCAT = ${addprefix ${dir $(target_makefile)}, $(CONTIKI_TARGET_DIRS)}

CONTIKI_CPU_DIRS_CONCAT    = ${addprefix $(CONTIKI_CPU)/, $(CONTIKI_CPU_DIRS)}

经分析CONTIKI_TARGET_DIRS_CONCAT的值为$(CONTIKI)/platform/cc2530dk/.dev

CONTIKI_CPU_DIRS_CONCAT的值为$(CONTIKI)/cpu/cc253x/. dev

 

SOURCEDIRS = . $(PROJECTDIRS) $(CONTIKI_TARGET_DIRS_CONCAT) \
             $(CONTIKI_CPU_DIRS_CONCAT) $(CONTIKIDIRS) $(APPDIRS) ${dir $(target_makefile)}

定义SOURCEFIRS值为. 表示当前目录,$(PROJECTDIRS),没找到这个变量的值,然后是$(CONTIKI)/platform/cc2530dk/.dev$(CONTIKI)/cpu/cc253x/.  dev$(CONTIKI)/core/dev $(CONTIKI)/core/lib $(CONTIKI)/core/net .......

对于cc2530我们没有定义APPS 所以这里$(APPDIRS)为空   以及

$(CONTIKI)/platform/cc2530dk/

这个SOURCEFRS指定了需要被编译的所有源文件的目录

 

vpath %.c $(SOURCEDIRS)
vpath %.S $(SOURCEDIRS)

vpath关键字指定了makefile中出现某文件的搜索路径。在这里它指定了所有在Makefile文件中出现的以.c和.S为后缀的源文件的搜索路径为$(SOURCEDIRS) 。 这一步为我们后面的编译过程所用的模式规则做好准备。

 

CFLAGS += ${addprefix -I,$(SOURCEDIRS)}

指定了头文件的搜索路径,因为在很多源文件目录中有相应的头文件

 

RELSTR=${shell git describe --tags 2>/dev/null}
ifneq ($(RELSTR),)
CFLAGS += -DCONTIKI_VERSION_STRING=\"Contiki-$(RELSTR)\"
endif

这几行貌似有点多余 ,因为在contiki-version.h文件中已经指定了CONTIKI_VERSION_STRING为"Contiki 2.6"

 

ifneq ($(MAKECMDGOALS),clean)
-include ${addprefix $(OBJECTDIR)/,$(CONTIKI_SOURCEFILES:.c=.d) \
       $(PROJECT_SOURCEFILES:.c=.d)}
endif

MAKECMDGOALS为make的环境变量,它会存放你所指定的终极目标的列表。那么上面几句表示如果执行的命令不是make clean 则包含include指定的makefile文件,这些文件是什么呢?obj_cc2530dk/....中以.d为后缀的文件

 

define FINALIZE_DEPENDENCY
cp $(@:.o=.d) $(@:.o=.$$$$); \
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
    -e '/^$$/ d' -e 's/$$/ :/' < $(@:.o=.$$$$) >> $(@:.o=.d); \
rm -f $(@:.o=.$$$$)
endef

多行定义变量FINALIZE_DEPENDENCY,其值为下面三个命令。这三个命令具体是干啥的,下面用到的时候再说!

 

clean:
 rm -f *~ *core core *.srec \
 *.lst *.map \
        *.cprg *.bin *.data contiki*.a *.firmware core-labels.S *.ihex *.ini \
        *.ce *.co $(CLEAN)
 -rm -rf $(OBJECTDIR)

clean伪目标用于删除所有编译链接产生的文件

 

下面都是一些编译源代码的一些规则。那么我们就从整个make执行的流程来看一下这个contiki系统是如何被编译,包括工程文件。

 

首先在工程目录中的makefile文件中找到终极目标为all,它依赖于 hello-world blink-hello timer-test sensors-demo

这四个文件,那么make就会去寻找第一个依赖文件的重建规则,hello-world,好像我们找了半天都没找到与它先关的规则,呵呵!那是因为在contiki系统中,所有重建过程都是用的模式规则,当然就看到以hello-world为目标的规则了!

    我们按照make读取makefile文件的过程来分析,首先读取makefile.include,途中读取了makefile.cc2530dk,在此文件中也没发现与hello-world相关的规则,在makefile.cc2530dk文件中又引入了makefile.cc253x文件,在此文件中也没找到,那么make就回到makefile.include文件中继续寻找。返现在makefile.include文件的末尾有这两句:

%: %.c

 注意这里的空行

%: %.$(TARGET)
@

单独一个%表示可以匹配任意字符,那么我们的目标hello-world当然可以匹配它了,所以就执行上面第一句。它的依赖文件为相应的hello-world.c文件,发现在工程目录中确实有这个文件,显然它比目标更新,所以执行下面语句!但是,居然为空命令,所以这一句相当于什么也不执行,但是make不服气啊?因为目标还没生成怎么就返回呢?所以继续找,那就是下面一个规则,它的依赖为hello-world.cc2530dk,那么这个文件显然在我们的目录中是没有的,所以make就去寻找建立它的规则。其实这里是多规则目标,一个hello-world对应两个规则,但是只能有一个规则有命令,其他的规则没有命令行,当要重建这个目标时,make会把它的依赖文件合并成一个依赖文件列表,然后执行那个有命令的规则!

hello-world.cc2530dk找规则......

一个是在makefile.include中

ifndef CUSTOM_RULE_LINK
%.$(TARGET): %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a
 $(LD) $(LDFLAGS) $(TARGET_STARTFILES) ${filter-out %.a,$^} ${filter %.a,$^} $(TARGET_LIBFILES) -o $@
endif

一个是在makefile.cc2530dk中

%.$(TARGET): %.hex FORCE
 cp $< $(<:.hex=.$(TARGET))
 @echo "\nReport"
 @echo "==============="
 @echo 'Code footprint:'
 @echo    'Area                                Addr        Size' \
          '         Decimal'
 @echo    '----------------------------------  --------    --------' \
          '     --------'
 @echo -n 'HOME,CSEG,CONST,XINIT,GS*           $(HOME_START)    '
 @egrep ',CODE\)' $(<:.hex=.map) | egrep -v '(^BANK[1-9][^=])' | uniq | \
 awk '{ SUM += $$5 } END { printf "%08X =    %8d", SUM, SUM }'
 @echo '. bytes (REL,CON,CODE)'
 @egrep '(^BANK[1-9][^=])' $(<:.hex=.map) | uniq | sort
 @egrep -A 5 'Other memory' $(<:.hex=.mem)

那么我们执行哪个呢?显然make搜索是从头开始,那么按照makefile的读取顺序,当然是下面那个规则先执行,况且上面那个规则中还判断CUSTOM_RULE_LINK是否定义了,经查证,它定义了,那么上面那个规则对于cc2530dk来说永远不会执行!所以看下面那个规则。

 

它依赖于helloworld.hex文件,这个文件在目录中显示是不存在的,那么make就继续寻找建立它的规则。

在makefile.cc253x中又找到了两个,但是实际上有一个规则使用了条件判断的。(没有定义UIP_CONF_IPV6,且

HAVE_BANKING=0)  所以:

%.hex: %.ihx
     $(PACKIHX) $< > $@

根据上面说的make工作原理,这样一直找下去,直到找到能生成目标的规则!!!这应该给大家提供了一种read makefile的思路吧!

 先休整一下,得去看看sdcc的东西,因为接下来大多都是sdcc编译器编译链接的事了!且听下回分解!

 

 

 

 

 


 

 


 

 

原创粉丝点击