zoukankan      html  css  js  c++  java
  • u-boot Makefile Source Test

    一、概述

      笔者已经写了一篇实现目标文件与源码分开的makefile测试实验,但是觉得不够完美,没有更多的体现u-boot Makefile的工作原理和特点。所以,决定重新修订,使之更加充分的接近u-boot Makfefile的原貌。

      至于,u-boot Makfefile的整体论述和特点,笔者在u-boot Makefile整体解析文中已经详细论述,不在多言。

    二、测试源码构成

      整个测试源码,由四个文件夹构成,三个是源文件夹,分别包含源程序(.c)和Makefile。顶层目录中包含config.mk和rules.mk文件。

    三、测试源码注释

     1、顶层Makfile

    ifneq ($(BUILD_DIR),)    #此变量在命令行选择定义,定义了就是目标文件和源码文件分开,否则是同一个
    saved-output := $(BUILD_DIR)
    # Attempt to create a output directory.
    $(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR})  #创建目录BUILD_DIR
    # Verify if it was successful.
    BUILD_DIR := $(shell cd $(BUILD_DIR) && /bin/pwd)
    $(if $(BUILD_DIR),,$(error output directory "$(saved-output)" does not exist))
    endif # ifneq ($(BUILD_DIR),)
    OBJTREE        := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR)) #目标文件生成的根目录,可以认为是一个常量,
                                                                    区别于obj
    SRCTREE        := $(CURDIR) #CURDIR是当前目录的路径,目录改变,它随之改变
    TOPDIR        := $(SRCTREE)
    LNDIR        := $(OBJTREE)
    export     SRCTREE OBJTREE TOPDIR 
    
    ifneq ((OBJTREE),(SRCTREE))  
    REMOTE_BUILD        := 1   
    export REMOTE_BUILD #此变量会被config.mk所调用    
    endif
    
    include $(TOPDIR)/config.mk #config.mk中定义了obj、CC等变量,下边的内容需要调用
    
    CROSS_COMPILE =  
    export    CROSS_COMPILE
    
    OBJS = add/add.o sub/sub.o test/test.o #需要生成的目标文件
    OBJS := $(addprefix $(obj),$(OBJS)) #需要生成目标文件的完整路径
    .PHONY : $(OBJS)       #确保源文件修改了,目标文件能够自动重建
    
    ALL = $(obj)program  #在program前边也加上了前缀obj 
    all:        $(ALL)
    
    $(obj)program: $(OBJS)
        $(CC) $^ -o $@
    
    $(OBJS):        
        make -C $(dir $(subst $(obj),,$@)) #依次执行各个子目录中的makefile
    
    SUBDIRS    = add/ sub/ test/
    .PHONY: clean distclean
    clean:
        for f in $(SUBDIRS); do make -C $$f clean; done //依次在各个子目录中删除
        rm -f $(ALL) 
        
    distclean:
        for f in $(SUBDIRS); do make -C $$f distclean; done
        rm -f $(ALL) 

    2、config.mk

    ifneq ($(OBJTREE),$(SRCTREE)) #判断是否选择目标文件生成目录和源码目录分开
    ifeq ($(CURDIR),$(SRCTREE)) #以下内容是目标文件生成目录和源码目录分开的情况
    dir :=
    else
    dir := $(subst $(SRCTREE)/,,$(CURDIR))
    endif
    
    obj := $(if $(dir),$(OBJTREE)/$(dir)/,$(OBJTREE)/) #确定要生成目标文件的完整路径,
                                #注意这是个变量,在不同的子目录中,执行makefile,obj的值相应的发生变化 
    src := $(if $(dir),$(SRCTREE)/$(dir)/,$(SRCTREE)/) #确定当前源文件的目录
    
    $(shell mkdir -p $(obj)) #创建目标文件的完整路径,注意gcc命令并不能自动生成缺少的路径,所以需要事先创建
    else     #以下内容是目标文件生成目录和源码目录同一的情况
    obj :=    #目标文件与源文件目录相同时,obj没有必要赋值
    src :=
    endif
    
    #以下的规则将用来编译子目录中的源文件
    # 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
    OBJCOPY = $(CROSS_COMPILE)objcopy
    OBJDUMP = $(CROSS_COMPILE)objdump
    
    #########################################################################
    
    ifndef REMOTE_BUILD
    
    %.s:    %.S
        $(CPP) $(AFLAGS) -o $@ $<
    %.o:    %.S
        $(CC) $(AFLAGS) -c -o $@ $<
    %.o:    %.c
        $(CC) $(CFLAGS) -c -o $@ $<
    
    else
    
    $(obj)%.s:    %.S
        $(CPP) $(AFLAGS) -o $@ $<
    $(obj)%.o:    %.S
        $(CC) $(AFLAGS) -c -o $@ $<
    $(obj)%.o:    %.c
        $(CC) $(CFLAGS) -c -o $@ $<
    endif
    
    #########################################################################

    3、rules.mk

    #########################################################################

    $(obj).depend: $(src)Makefile $(TOPDIR)/config.mk $(SRCS) #SRCS在子目录Makefile中定义
    @rm -f $@
    @for f in $(SRCS); do
    g=`basename $$f | sed -e 's/(.*).w/1.o/'`;
    $(CC) -M $(HOST_CFLAGS) $(CPPFLAGS) -MQ $(obj)$$g $$f >> $@ ;
    done

    #########################################################################

    4、子目录Makefile

    include $(TOPDIR)/config.mk #包含config.mk
    
    COBJS    := add.o #.c文件生成的目标文件
    SOBJS    :=       #.S文件生成的目标文件
    
    SRCS    := $(SOBJS:.o=.S) $(COBJS:.o=.c) #所有参与编译的源文件(.c、.S)
    OBJS    := $(addprefix $(obj),$(COBJS))#添加目录obj
    SOBJS    := $(addprefix $(obj),$(SOBJS))
    
    all: $(obj).depend $(OBJS) #先生成依赖文件,然后才能编译源程序
    
    clean:
        rm -f $(SOBJS) $(OBJS)
    
    distclean:    clean
        rm -f $(LIB) $(obj).depend
    
    #########################################################################
    
    # defines $(obj).depend target
    include $(SRCTREE)/rules.mk #包含rules.mk
    
    sinclude $(obj).depend #包含.depend文件
    
    #########################################################################    

     四、编译方法

    1、目标文件与源码混在一起

        直接在顶层目录中执行:#make

    2、目标文件与源码分开

    方法一:

        先声明个环境变量:#exprort BUILD_DIR=/tmp/build    //这里以/tmp/build为例

        然后在顶层目录中执行:#make

    方法二:

        直接在顶层目录中执行:#make BUILD_DIR=/tmp/build

    附:U-bootMakefileTest.zip

  • 相关阅读:
    WCF 4.0 进阶系列 – 第十四章 检测服务和路由消息(第三部分)
    WCF 4.0 进阶系列 – 第十五章 构建REST服务(第二部分)
    WCF 4.0 进阶系列 – 第十五章 构建REST服务(第一部分)
    WCF 4.0 进阶系列 – 第十六章 使用回调合约发布和订阅事件(第二部分)
    WCF 4.0 进阶系列 – 第十二章 实现单向操作和异步操作(中)
    asp调用存储过程! PENGHAO
    在b/s开发中经常用到的javaScript技术 PENGHAO
    Windows2003网络服务器安全攻略 PENGHAO
    CSDNBlog非常的不稳定!终于找到个安身之处了! PENGHAO
    ASP 函数语法速查表 PENGHAO
  • 原文地址:https://www.cnblogs.com/amanlikethis/p/3663675.html
Copyright © 2011-2022 走看看