makefile4vivi-top makefile

    技术2025-08-15  3

    个人在看VIVI的makefile时的一些认识(部分内容已经被我修改,初步的草稿,还将继续修正):

     

     

    总MAKEFILE最终目的就是要生成VIVI,所以从生成VIVI的规则开始分析。前面的部分都是在后面规则里面需要用到的定义。

    #版本信息和体系结构

    VERSION = 0 PATCHLEVEL = 1 SUBLEVEL = 4 VIVIRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)

     

    ARCH := arm

     

    #选择相应的SHELL

    CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; /     else if [ -x /bin/bash ]; then echo /bin/bash; /     else echo sh; fi ; fi) TOPDIR    := $(shell /bin/pwd) # # change this to point to the Linux include directory # LINUX_INCLUDE_DIR    = /usr/local/arm/2.95.3/include #VIVI的头文件路径 VIVIPATH           = $(TOPDIR)/include

     

     

     

    #一系列的工具和编译选项

    HOSTCC          = gcc HOSTCFLAGS      = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer CROSS_COMPILE   = /usr/local/arm/2.95.3/bin/arm-linux- # # Include the make variables (CC, etc...) # AS              = $(CROSS_COMPILE)as LD              = $(CROSS_COMPILE)ld CC              = $(CROSS_COMPILE)gcc CPP             = $(CC) -E AR              = $(CROSS_COMPILE)ar NM              = $(CROSS_COMPILE)nm STRIP           = $(CROSS_COMPILE)strip OBJCOPY         = $(CROSS_COMPILE)objcopy OBJDUMP         = $(CROSS_COMPILE)objdump MAKEFILES       = $(TOPDIR)/.config MD5SUM        = md5sum PERL            = perl AWK        = awk export  VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE /         CONFIG_SHELL TOPDIR VIVIPATH HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC /     CPP AR NM STRIP OBJCOPY OBJDUMP MAKE MAKEFILES MD5SUM PERL AWK

     

     

     

    #总的依赖为vivi,version,.config,如果.config存在那么将其包含,利用其中的配置信息,如果不存在那么需要通过依赖建立这个文件,

    #所以在不存在时定义CONFIGURATION = config,并使CONFIGURATION成为依赖。

    ifeq (.config,$(wildcard .config)) include .config else CONFIGURATION = config #do-it-all:    $CONFIGURATION

    #从下面分析来看这一句并不是必须的,在下面的vivi的生成规则中已经包含了对$CONFIGURATION的依赖,可以执行config操作。 endif

     

     

    #MAKE入口点

    all:     do-it-all

     

    do-it-all:    Version vivi

    #接下来就是要看这两个文件怎么生成 # # standard CFLAGS # CPPFLAGS := -I$(VIVIPATH) -I$(LINUX_INCLUDE_DIR) #CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 / #          -fomit-frame-pointer -fno-strict-aliasing -fno-common #normal flags CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -O2 -fPIC -fomit-frame-pointer #symbol table make up #CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -O2 -fPIC -fomit-frame-pointer -ggdb AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS)

    # # Location of the gcc arm libs. #

    ARM_GCC_LIBS    = /usr/local/arm/2.95.3/lib/gcc-lib/arm-linux/2.95.3 OBJCOPYFLAGS = -R .comment -R .stab -R .stabstr CLIBS = -L$(ARM_GCC_LIBS) -lgcc -lc #laputa symbolic  这里的.lds文件需要编写 LINKFLAGS = -Tarch/vivi.lds -Bstatic

    CORE_FILES    = init/main.o init/version.o lib/lib.o LIBS            := lib/priv_data/priv_data.o SUBDIRS         = drivers lib

    #下面这个写法我觉得很好,如果配置文件中有相应的配置,那么该配置就是y,对应的驱动被追加,将最后的追加结果给驱动。

    DRIVERS-y := DRIVERS-$(CONFIG_SERIAL) += drivers/serial/serial.o DRIVERS-$(CONFIG_MTD) += drivers/mtd/mtd.o DRIVERS := $(DRIVERS-y)

     

    #清除操作对应的文件

    #最终生成的一些文件

    CLEAN_FILES = /     vivi-elf /     vivi /     vivi.nm /     vivi.map

    #配置过程生成的一些文件 DISTCLEAN_FILES = /     include/autoconf.h include/version.h /     scripts/lxdialog/*.o scripts/lxdialog/lxdialog /     .menuconfig.log /     .config .config.old

     

    #由于在生成最终文件的时候要用到arch文件夹中的目标文件,调用其makefile进行生成

    include arch/Makefile export  CPPFLAGS CFLAGS AFLAGS export  DRIVERS LDFLAGS

    #因为compile.h 中保存的是最后一次编译过程中生成的时间,工具等信息,它被include/version.h调用,需要更新,所以将其删除

    Version: dummy     @rm -f include/compile.h

     

    #生成最终vivi文件的规则,可以看一下需要的依赖有没有全部有相应生成的地方

    vivi: include/version.h $(CONFIGURATION) init/main.o init/version.o linuxsubdirs     $(LD) -v $(LINKFLAGS) /         $(HEAD) /         $(CORE_FILES) /         $(DRIVERS) /         $(LIBS) /         -o vivi-elf $(CLIBS)     $(NM) -v -l vivi-elf > vivi.map     $(OBJCOPY) -O binary -S vivi-elf vivi $(OBJCOPYFLAGS)

     

    #这里对以上用到各文件进行一个分析:HEAD在arch目录下定义,上面已经include了相应的makefile进行规则定义,打开看一下可知主

    #要是根据配置文件(主Makefile包含了.config,这样看来先make config一下比较稳妥)追加了一些与体系结构等有关的编译规则、定义了MACHINE PROCESSOR TEXTADDR,修改了SUBDIRS #CORE_FILE CLEAN_FILES 使其包含了这个目录下相关的文件而

    #head.o的生成则是由主Makefile中include Rules.make来完成。

    #其中vivi:$(HEAD)  arch/vivi.lds  arch/vivi.lds: $(LDSCRIPT) dummy  @sed s/TEXTADDR/$(TEXTADDR)/ $(LDSCRIPT) >$@

    #使得vivi包含了对$(HEAD)的依赖,由于其中的连接方式等可能与总的vivi那边不大一样,所以写在了子Makefile中。

    #总的来看该子makefile主要的任务是根据CPU的相关信息来调整总操作和选项。

     

     

    #几种config操作:通过相应的脚本和config.in文件中的选择与用户交互完成.config文件生成。以config操作为例,其中

    #scripts/Configure脚本是模仿LINUX的,打开看一下可知config.in需要根据自己的需要进行修改,主要功能是提醒用户可以选择的配置

    #以及完成相应配置的保存。主要有如:comment、bool、hex等这些语句来提示和保存信息。最后有source lib/priv_data/Config.in #source drivers/serial/Config.in source drivers/mtd/Config.in source lib/Config_cmd.in几个配置选择文件的调入。打开看下这些子config.in可知,它们又调入了更下一层的config.in文件,这样要提示用户一个新的可配置的模块时,只需要写好该模块自己的config.in提示文件,并在它所属的上一层config.in中用source调用即可。

    oldconfig:     $(CONFIG_SHELL) scripts/Configure -d arch/config.in config:     $(CONFIG_SHELL) scripts/Configure arch/config.in menuconfig: include/version.h     $(MAKE) -C scripts/lxdialog all     $(CONFIG_SHELL) scripts/Menuconfig arch/config.in clean:     find . /( -name '*.o' -o -name core -o -name ".*.flags" /) -type f -print /     | grep -v lxdialog/ | xargs rm -f     rm -f $(CLEAN_FILES) distclean: clean     rm -f $(DISTCLEAN_FILES)

     

    #执行其他子目录下的makefile

    linuxsubdirs: $(patsubst %, _dir_%, $(SUBDIRS))

    #使用patsubst避免目标和操作的文件重名

    $(patsubst %, _dir_%, $(SUBDIRS)) : include/version.h     $(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" -C $(patsubst _dir_%, %, $@)

     

    #还没有看明白以下两句有何精髓...可能是在别的makefile中有用到下面两个目标 $(TOPDIR)/include/version.h: include/version.h $(TOPDIR)/include/compile.h: include/compile.h

    #在前面为了产生新的version.h,前面已经通过make Version或者通过make入口后删除了compile.h文件,在成为依赖时重新生成

    include/compile.h: $(CONFIGURATION) include/version.h     @echo -n /#define UTS_VERSION /"/#$(VIVIRELEASE) > .ver     @if [ -f .name ]; then  echo -n /-`cat .name` >> .ver; fi     @echo ' '`date`'"' >> .ver     @echo /#define VIVI_COMPILE_TIME /"`date +%T`/" >> .ver     @echo /#define VIVI_COMPILE_BY /"`whoami`/" >> .ver     @echo /#define VIVI_COMPILE_HOST /"`hostname`/" >> .ver     @if [ -x /bin/dnsdomainname ]; then /        echo /#define VIVI_COMPILE_DOMAIN /"`dnsdomainname`/"; /      elif [ -x /bin/domainname ]; then /        echo /#define VIVI_COMPILE_DOMAIN /"`domainname`/"; /      else /        echo /#define VIVI_COMPILE_DOMAIN ; /      fi >> .ver     @echo /#define VIVI_COMPILER /"`$(CC) $(CFLAGS) -v 2>&1 | tail -1`/" >> .ver     @mv -f .ver $@ include/version.h:     @echo /#define VIVI_RELEASE /"$(VIVIRELEASE)/" > .ver     @echo /#define VIVI_VERSION_CODE `expr $(VERSION) //* 65536 + $(PATCHLEVEL) //* 256 + $(SUBLEVEL)` >> .ver     @echo '#define VIVI_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))' >>.ver     @mv -f .ver $@ init/version.o: init/version.c include/compile.h     $(CC) $(CFLAGS) -DUTS_MACHINE='"$(ARCH)"' -c -o init/version.o init/version.c init/main.o: init/main.c     $(CC) $(CFLAGS) $(CFLAGS_KERNEL) $(PROFILING) -c -o $*.o $<

     

    #如果需要选择默认的配置文件来复制生成.config并且自动执行后面操作生成vivi,默认配置文件里面定义了一种配置模式,可以打开看一下

    #是否能满足需要

    %: ./arch/def-configs/%     $(MAKE) distclean     cp arch/def-configs/$* ./.config -f     $(MAKE) oldconfig     $(MAKE)     #通过make ..config 可以查看是否存在.config文件,如果不存在将会给出相关提示。 ifdef CONFIGURATION ..$(CONFIGURATION):     @echo     @echo "You have a bad or nonexistent" .$(CONFIGURATION) ": running 'make" $(CONFIGURATION)"'"     @echo     $(MAKE) $(CONFIGURATION)     @echo     @echo "Successful. Try re-making (ignore the error that follows)"     @echo     exit 1 dummy: else dummy: endif

     

    #这一句很重要,很多的通过规则都放在其中,使得很多makefile中只需要给出依赖关系即可

    include Rules.make

    最新回复(0)