Nuttx编译系统

作者: Loyen | 来源:发表于2018-11-11 17:05 被阅读2次

    Nuttx相关的历史文章:

    配置

    Nuttx在编译之前需要先进行配置,而Nuttx是一个高度可配置的RTOS,Nuttx的配置文件使用kconfig-frontends工具来维护,配置工具将使用Kconfig文件,而Kconfig文件在Nuttx的代码文件夹中随处可见。每一个Kconfig文件包含了配置变量的声明,而每一个配置变量又给Nuttx提供了一种配置选择,Nuttx的最终配置都由这些Kconfig文件决定。
    一般进行Nuttx配置的时候,都可以在Nuttx根目录中通过make menuconfig命令来操作,前提是在根目录中需要有.config文件存在,而.config文件是从某个特定的开发板中的某个路径下拷贝过来的。

    要获取.config文件,又有两种途径:一种是通过手动将.configMake.defs文件从特定开发板中的某个路径中拷贝至Nuttx的顶层路径;一种是通过tools目录下的configure.sh脚本完成拷贝工作。最终在进行编译的时候,需要依赖这两个文件。

    1. 手动配置
    • Copy configs/<board-name>/[<config-dir>/]Make.defs to ${TOPDIR}/Make.defs
    • Copy configs/<board-name>/[<config-dir>/]defconfig to ${TOPDIR}/.config
    1. 自动配置
    • tools/confiure.sh [OPTIONS] <board-name>[/<config-dir>]

    每个特定的开发板文件夹中都有两个文件Make.defsdefconfig文件来描述该开发板的配置。

    Make.defs

    1. Make.defs提供架构和特定工具的构建选项,在编译时它将被其他所有的Makefile包含,它将定义如下内容:
    • Tools: CC, LD, AR, NM, OBJCOPY, OBJDUMP
    • Tools options: CFLAGS, LDFLAGS
    1. Make.defs运行时,TOPDIR会传递给它,在Make.defs中将包含以下两个文件:
    • $(TOPDIR)/.config: Nuttx的配置
    • $(TOPDIR)/tools/Config.mk:一些通用的定义。tools/Config.mk文件中包含了一些额外的宏定义,这些宏定义的值在需要的时候可能会在特定架构中的Make.defs中被覆盖,比如:COMPILE, ASSEMBLE, ARCHIVE, CLEAN, MKDEP等。

    defconfig
    defconfig文件中包含一些如CONFIG_VARIABLE=value形式的定义,它拷贝至$(TOPDIR)路径下后,在编译时会被其他Makefile所包含,并且会用它来生成include/nuttx/config.h文件,这个文件在很多C文件中会用到。

    编译

    大概的目录组织如下:

    build
    |-nuttx
    |  |
    |  - Makefile
    |-apps
    |  |
    |  - Makefile
    

    先罗列一下编译时所需要的文件,其中$(TOPDIR)nuttx目录,编译时是在nuttx目录中进行。

    • Makefile文件,包括各个目录及子目录下的Makefile文件
    • Make.defs文件,从特定开发板目录中拷贝过来的,见上文中的配置部分
    • .config文件,从特定开发板目录中拷贝过来的,见上文中的配置部分
    • tools/Config.mk文件,定义了某些通用的宏定义
    • tools/目录,该目录下提供了各类工具(脚本/执行文件),具体的功能也可以查看README.txt
    • FlatLibs.mk/KernelLibs.mk/ProtectedLibs.mk文件,这三个文件分别对应到内存配置中的Flat模式Kernel模式(需要MMU支持)保护模式(需要MPU支持),我使用的是Flat模式,所以在实际编译时只需要FlatLibs.mk文件即可。
    • Directories.mk文件,描述一些add-on目录

    完成配置后,编译的过程很简单:

    • cd $(TOPDIR)
    • make
      上文中也提到过,$(TOPDIR)中的.config文件主要描述当前的配置,Make.defs文件描述特定的开发板配置。

    系统第一次build的时候,会有一些额外的配置动作,包括:

    • 自动使用$(TOPDIR)/.config来生成include/nuttx/config.h文件
    • 如果$(TOPDIR)/.version文件不存在的话,自动使用version 0.0来生成
    • 自动使用$(TOPDIR)/.version来生成include/nuttx/version.h文件
    • 创建链接,将$(TOPDIR)/include/arch链接到$(TOPDIR)/arch/<arch-name>/include目录
    • 创建链接,将$(TOPDIR)/include/arch/board链接到$(TOPDIR)/configs/<board-name>/include目录
    • 创建链接,将$(TOPDIR)/arch/<arch-name>/src/board链接到$(TOPDIR)/configs/<board-name>/src目录
    • 创建链接, 将$(TOPDIR)/include/apps链接到$(APPDIR)/include目录
    • 创建make dependencies,描述Makefile中的自动依赖关系,文件为Make.dep

    讲这么多,还是直接从Makefile开始入手跟踪吧。在$(TOPDIR)目录中,Makefile内容如下:

    ...
    -include .config    #将.config文件包含进来,其中`-`表示如果.config文件不存在,Makefile也不会报错,并继续运行
    ifeq ($(CONFIG_WINDOWS_NATIVE),y)
    include Makefile.win
    else
    include Makefile.unix    #根据编译环境,选择对应的Makefile,真正的入口
    endif
    

    下面将分别介绍上面讲到的文件,核心是围绕Makefile.unix文件。

    .config

    整个.config文件内容格式如下所示,用来定义配置选项,在编译时需要用到。

    ...
    # Build Setup
    #
    # CONFIG_EXPERIMENTAL is not set
    # CONFIG_DEFAULT_SMALL is not set
    CONFIG_HOST_LINUX=y
    # CONFIG_HOST_OSX is not set
    # CONFIG_HOST_WINDOWS is not set
    # CONFIG_HOST_OTHER is not set
    
    #
    # Build Configuration
    #
    CONFIG_APPS_DIR="../apps"
    CONFIG_BUILD_FLAT=y
    # CONFIG_BUILD_2PASS is not set
    ...
    

    tools/Config.mk

    Config.mk文件中,定义了如PREPROCESS, COMPILE, COMPILEXX, ASSEMBLE, ARCHIVE, DELFILE等通用宏,在其他文件中将使用$(call XXX, in-file, out-file)形式来使用,其中XXX表示定义的这些宏。

    # These are configuration variables that are quoted by configuration tool
    # but which must be unquoated when used in the build system.
    
    # 调整架构相关宏的值,其中patsubst为Makefile匹配与替换函数,strip为去空格函数
    CONFIG_ARCH       := $(patsubst "%",%,$(strip $(CONFIG_ARCH)))
    CONFIG_ARCH_CHIP  := $(patsubst "%",%,$(strip $(CONFIG_ARCH_CHIP)))
    CONFIG_ARCH_BOARD := $(patsubst "%",%,$(strip $(CONFIG_ARCH_BOARD)))
    
    # Some defaults just to prohibit some bad behavior if for some reason they
    # are not defined
    
    OBJEXT ?= .o
    LIBEXT ?= .a
    
    # DELIM - Path segment delimiter character
    #
    # Depends on this settings defined in board-specific defconfig file installed
    # at $(TOPDIR)/.config:
    #
    #   CONFIG_WINDOWS_NATIVE - Defined for a Windows native build
    # 定义DELIM分隔符
    ifeq ($(CONFIG_WINDOWS_NATIVE),y)
      DELIM = $(strip \)
    else
      DELIM = $(strip /)
    endif
    
    # INCDIR - Convert a list of directory paths to a list of compiler include
    #   directirves
    # Example: CFFLAGS += ${shell $(INCDIR) [options] "compiler" "dir1" "dir2" "dir2" ...}
    #
    # Note that the compiler string and each directory path string must quoted if
    # they contain spaces or any other characters that might get mangled by the
    # shell
    #
    # Depends on this setting passed as a make commaond line definition from the
    # toplevel Makefile:
    #
    #   TOPDIR - The path to the top level NuttX directory in the form
    #     appropriate for the current build environment
    #
    # Depends on this settings defined in board-specific defconfig file installed
    # at $(TOPDIR)/.config:
    #
    #   CONFIG_WINDOWS_NATIVE - Defined for a Windows native build
    
    ifeq ($(CONFIG_WINDOWS_NATIVE),y)
      INCDIR = "$(TOPDIR)\tools\incdir.bat"
    else
      INCDIR = "$(TOPDIR)/tools/incdir.sh"
    endif
    
    # PREPROCESS - Default macro to run the C pre-processor
    # Example: $(call PREPROCESS, in-file, out-file)
    #
    # Depends on these settings defined in board-specific Make.defs file
    # installed at $(TOPDIR)/Make.defs:
    #
    #   CPP - The command to invoke the C pre-processor
    #   CPPFLAGS - Options to pass to the C pre-processor
    # 预处理宏
    define PREPROCESS
        @echo "CPP: $1->$2"
        $(Q) $(CPP) $(CPPFLAGS) $1 -o $2
    endef
    
    # COMPILE - Default macro to compile one C file
    # Example: $(call COMPILE, in-file, out-file)
    #
    # Depends on these settings defined in board-specific Make.defs file
    # installed at $(TOPDIR)/Make.defs:
    #
    #   CC - The command to invoke the C compiler
    #   CFLAGS - Options to pass to the C compiler
    
    define COMPILE
        @echo "CC: $1"
        $(Q) $(CC) -c $(CFLAGS) $1 -o $2
    endef
    
    # COMPILEXX - Default macro to compile one C++ file
    # Example: $(call COMPILEXX, in-file, out-file)
    #
    # Depends on these settings defined in board-specific Make.defs file
    # installed at $(TOPDIR)/Make.defs:
    #
    #   CXX - The command to invoke the C++ compiler
    #   CXXFLAGS - Options to pass to the C++ compiler
    
    define COMPILEXX
        @echo "CXX: $1"
        $(Q) $(CXX) -c $(CXXFLAGS) $1 -o $2
    endef
    
    # ASSEMBLE - Default macro to assemble one assembly language file
    # Example: $(call ASSEMBLE, in-file, out-file)
    #
    # NOTE that the most common toolchain, GCC, uses the compiler to assemble
    # files because this has the advantage of running the C Pre-Processor against
    # the assembly language files.  This is not possible with other toolchains;
    # platforms using those other tools should define AS and over-ride this
    # definition in order to use the assembler directly.
    #
    # Depends on these settings defined in board-specific Make.defs file
    # installed at $(TOPDIR)/Make.defs:
    #
    #   CC - By default, the C compiler is used to compile assembly language
    #        files
    #   AFLAGS - Options to pass to the C+compiler
    
    define ASSEMBLE
        @echo "AS: $1"
        $(Q) $(CC) -c $(AFLAGS) $1 -o $2
    endef
    
    # MOVEOBJ - Default macro to move an object file to the correct location
    # Example: $(call MOVEOBJ, prefix, directory)
    #
    # This is only used in directories that keep object files in sub-directories.
    # Certain compilers (ZDS-II) always place the resulting files in the the
    # directory where the compiler was invoked with not option to generate objects
    # in a different location.
    
    define MOVEOBJ
    endef
    
    # ARCHIVE - Add a list of files to an archive
    # Example: $(call ARCHIVE, archive-file, "file1 file2 file3 ...")
    #
    # Note: The fileN strings may not contain spaces or  characters that may be
    # interpreted strangely by the shell
    #
    # Depends on these settings defined in board-specific Make.defs file
    # installed at $(TOPDIR)/Make.defs:
    #
    #   AR - The command to invoke the archiver (includes any options)
    #
    # Depends on this settings defined in board-specific defconfig file installed
    # at $(TOPDIR)/.config:
    #
    #   CONFIG_WINDOWS_NATIVE - Defined for a Windows native build
    
    ifeq ($(CONFIG_WINDOWS_NATIVE),y)
    define ARCHIVE
        @echo AR: $2
        $(Q) $(AR) $1 $(2)
    endef
    else
    define ARCHIVE
        @echo "AR: $2"
        $(Q) $(AR) $1 $(2) || { echo "$(AR) $1 FAILED!" ; exit 1 ; }
    endef
    endif
    
    # PRELINK - Prelink a list of files
    # This is useful when files were compiled with fvisibility=hidden.
    # Any symbol which was not explicitly made global is invisible outside the
    # prelinked file.
    #
    # Example: $(call PRELINK, prelink-file, "file1 file2 file3 ...")
    #
    # Note: The fileN strings may not contain spaces or  characters that may be
    # interpreted strangely by the shell
    #
    # Depends on these settings defined in board-specific Make.defs file
    # installed at $(TOPDIR)/Make.defs:
    #
    #   LD - The command to invoke the linker (includes any options)
    #    OBJCOPY - The command to invoke the object cop (includes any options)
    #
    # Depends on this settings defined in board-specific defconfig file installed
    # at $(TOPDIR)/.config:
    #
    #   CONFIG_WINDOWS_NATIVE - Defined for a Windows native build
    
    ifeq ($(CONFIG_WINDOWS_NATIVE),y)
    define PRELINK
        @echo PRELINK: $1
        $(Q) $(LD) -Ur -o $1 $2 && $(OBJCOPY) --localize-hidden $1
    endef
    else
    define PRELINK
        @echo "PRELINK: $1"
        $(Q) $(LD) -Ur -o $1 $2 && $(OBJCOPY) --localize-hidden $1
    endef
    endif
    
    # DELFILE - Delete one file
    
    ifeq ($(CONFIG_WINDOWS_NATIVE),y)
    define DELFILE
        $(Q) if exist $1 (del /f /q $1)
    endef
    else
    define DELFILE
        $(Q) rm -f $1
    endef
    endif
    
    # DELDIR - Delete one directory
    
    ifeq ($(CONFIG_WINDOWS_NATIVE),y)
    define DELDIR
        $(Q) if exist $1 (rmdir /q /s $1)
    endef
    else
    define DELDIR
        $(Q) rm -rf $1
    endef
    endif
    
    # MOVEFILE - Move one file
    
    ifeq ($(CONFIG_WINDOWS_NATIVE),y)
    define MOVEFILE
        $(Q) if exist $1 (move /Y $1 $2)
    endef
    else
    define MOVEFILE
        $(Q) mv -f $1 $2
    endef
    endif
    
    # CLEAN - Default clean target
    
    ifeq ($(CONFIG_WINDOWS_NATIVE),y)
    define CLEAN
        $(Q) if exist *$(OBJEXT) (del /f /q *$(OBJEXT))
        $(Q) if exist *$(LIBEXT) (del /f /q *$(LIBEXT))
        $(Q) if exist *~ (del /f /q *~)
        $(Q) if exist (del /f /q  .*.swp)
    endef
    else
    define CLEAN
        $(Q) rm -f *$(OBJEXT) *$(LIBEXT) *~ .*.swp
    endef
    endif
    
    

    Make.defs

    Make.defs中定义了一些板级相关的宏定义。

    # 包含需要依赖的文件
    include ${TOPDIR}/.config 
    include ${TOPDIR}/tools/Config.mk 
    include ${TOPDIR}/arch/arm/src/arm/Toolchain.defs
    
    ifeq ($(WINTOOL),y)
      # Windows-native toolchains
      DIRLINK = $(TOPDIR)/tools/copydir.sh
      DIRUNLINK = $(TOPDIR)/tools/unlink.sh
      MKDEP = $(TOPDIR)/tools/mkwindeps.sh
      ARCHINCLUDES = -I. -isystem "${shell cygpath -w $(TOPDIR)/include}"
      ARCHXXINCLUDES = -I. -isystem "${shell cygpath -w $(TOPDIR)/include}" -isystem "${shell cygpath -w $(TOPDIR)/include/cxx}"
      ARCHSCRIPT = -T "${shell cygpath -w $(TOPDIR)/configs/$(CONFIG_ARCH_BOARD)/scripts/ld.script}"
    else
      # Linux/Cygwin-native toolchain        在Linux环境下使用的工具链
      MKDEP = $(TOPDIR)/tools/mkdeps$(HOSTEXEEXT)
      ARCHINCLUDES = -I. -isystem $(TOPDIR)/include
      ARCHXXINCLUDES = -I. -isystem $(TOPDIR)/include -isystem $(TOPDIR)/include/cxx -isystem $(TOPDIR)/include/uClibc++
      ARCHSCRIPT = -T$(TOPDIR)/configs/<board-name>/$(CONFIG_ARCH_BOARD)/scripts/ld.script
    endif
    
    # 定义工具,其中$(CROSSDEV)在$(TOPDIR)/arch/arm/src/arm/Toolchain.defs文件中定义
    CC = $(CROSSDEV)gcc
    CXX = $(CROSSDEV)g++
    CPP = $(CROSSDEV)gcc -E
    LD = $(CROSSDEV)ld
    AR = $(CROSSDEV)ar rcs
    NM = $(CROSSDEV)nm
    OBJCOPY = $(CROSSDEV)objcopy
    OBJDUMP = $(CROSSDEV)objdump
    
    # 编译器版本
    ARCHCCVERSION = ${shell $(CC) -v 2>&1 | sed -n '/^gcc version/p' | sed -e 's/^gcc version \([0-9\.]\)/\1/g' -e 's/[-\ ].*//g' -e '1q'}
    ARCHCCMAJOR = ${shell echo $(ARCHCCVERSION) | cut -d'.' -f1}
    
    ifeq ($(CONFIG_DEBUG_SYMBOLS),y)
      ARCHOPTIMIZATION = -g
      ARCHOPTIMIZATION += -fno-omit-frame-pointer -mapcs -mno-sched-prolog
    endif
    
    ifneq ($(CONFIG_DEBUG_NOOPT),y)
      ARCHOPTIMIZATION += $(MAXOPTIMIZATION) -fno-strict-aliasing -fno-strength-reduce -fomit-frame-pointer
    endif
    
    ifeq ($(ARCHCCMAJOR),4)
      ARCHCPUFLAGS = -mtune=arm9tdmi -march=armv5te -mfloat-abi=soft -fno-builtin
    else
      ARCHCPUFLAGS = -mapcs-32 -mtune=arm9tdmi -march=armv5te -msoft-float -fno-builtin
    endif
    
    ARCHCFLAGS = -fno-builtin
    ARCHCXXFLAGS = -fno-builtin -fno-exceptions -fcheck-new  -fpermissive -fno-rtti
    ARCHWARNINGS = -Wall -Wstrict-prototypes -Wshadow -Wundef
    ARCHWARNINGSXX = -Wall -Wshadow -Wundef
    ARCHDEFINES =
    ARCHPICFLAGS = -fpic -msingle-pic-base -mpic-register=r10
    
    # 定义所有编译时的FLAG选项
    CFLAGS = $(ARCHCFLAGS) $(ARCHWARNINGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe
    CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS)
    CXXFLAGS = $(ARCHCXXFLAGS) $(ARCHWARNINGSXX) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -std=c++11 -pipe
    CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS)
    CPPFLAGS = $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES)
    AFLAGS = $(CFLAGS) -D__ASSEMBLY__
    
    NXFLATLDFLAGS1 = -r -d -warn-common
    NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)/binfmt/libnxflat/gnu-nxflat-gotoff.ld -no-check-sections
    LDNXFLATFLAGS = -e main -s 2048
    
    # 定义文件后缀
    ASMEXT = .S
    OBJEXT = .o
    LIBEXT = .a
    EXEEXT =
    
    ifneq ($(CONFIG_ARM_TOOLCHAIN),BUILDROOT)
      LDFLAGS += -nostartfiles -nodefaultlibs
    endif
    ifeq ($(CONFIG_DEBUG_SYMBOLS),y)
      LDFLAGS += -g
    endif
    
    # 定义Host的编译器
    HOSTCC = gcc
    HOSTINCLUDES = -I.
    HOSTCFLAGS = -Wall -Wstrict-prototypes -Wshadow -Wundef -g -pipe
    HOSTLDFLAGS =
    
    

    Directories.mk

    Directories.mk主要定义了NUTTX_ADDONSUSER_ADDONS,其中NUTTX_ADDONS包含了一系列文件夹,最终将编译进Nuttx内核中,而USER_ADDONS包含了一系列文件夹,最终会编译进Apps中。Directories.mk将Nuttx内核中的文件夹都包含了进来。

    # All add-on directories.
    #
    # NUTTX_ADDONS is the list of directories built into the NuttX kernel.
    # USER_ADDONS is the list of directories that will be built into the user
    #   application
    
    NUTTX_ADDONS :=
    USER_ADDONS :=
    
    # In the protected build, the applications in the apps/ directory will be
    # into the userspace; in the flat build, the applications will b built into
    # the kernel space.  But in the kernel build, the applications will not be
    # built at all by this Makefile.
    
    ifeq ($(CONFIG_BUILD_PROTECTED),y)
    USER_ADDONS += $(APPDIR)
    else
    ifneq ($(CONFIG_BUILD_KERNEL),y)
    NUTTX_ADDONS += $(APPDIR)
    endif
    endif
    
    # Lists of build directories.
    #
    # FSDIRS depend on file descriptor support; NONFSDIRS do not (except for parts
    #   of FSDIRS).  We will exclude FSDIRS from the build if file descriptor
    #   support is disabled.  NOTE that drivers, in general, depends on file
    #   descriptor support but is always built because there are other components
    #   in the drivers directory that are needed even if file descriptors are not
    #   supported.
    # CONTEXTDIRS include directories that have special, one-time pre-build
    #   requirements.  Normally this includes things like auto-generation of
    #   configuration specific files or creation of configurable symbolic links
    # USERDIRS - When NuttX is build is a monolithic kernel, this provides the
    #   list of directories that must be built
    # OTHERDIRS - These are directories that are not built but probably should
    #   be cleaned to prevent garbage from collecting in them when changing
    #   configurations.
    
    NONFSDIRS = sched drivers configs $(ARCH_SRC) $(NUTTX_ADDONS)
    FSDIRS = fs binfmt
    CONTEXTDIRS = configs $(APPDIR)
    USERDIRS =
    OTHERDIRS = lib
    
    ifeq ($(CONFIG_BUILD_PROTECTED),y)
    
    USERDIRS += libc mm $(USER_ADDONS)
    ifeq ($(CONFIG_HAVE_CXX),y)
    USERDIRS += libxx
    endif
    
    else
    ifeq ($(CONFIG_BUILD_KERNEL),y)
    
    USERDIRS += libc mm
    ifeq ($(CONFIG_HAVE_CXX),y)
    USERDIRS += libxx
    endif
    
    else
    
    NONFSDIRS += libc mm
    OTHERDIRS += $(USER_ADDONS)
    ifeq ($(CONFIG_HAVE_CXX),y)
    NONFSDIRS += libxx
    else
    OTHERDIRS += libxx
    endif
    
    endif
    endif
    
    ifeq ($(CONFIG_LIB_SYSCALL),y)
    NONFSDIRS += syscall
    CONTEXTDIRS += syscall
    USERDIRS += syscall
    else
    OTHERDIRS += syscall
    endif
    
    ifeq ($(CONFIG_LIB_ZONEINFO_ROMFS),y)
    CONTEXTDIRS += libc
    endif
    
    ifeq ($(CONFIG_NX),y)
    NONFSDIRS += graphics libnx
    CONTEXTDIRS += graphics libnx
    else
    OTHERDIRS += graphics libnx
    endif
    
    ifeq ($(CONFIG_AUDIO),y)
    NONFSDIRS += audio
    else
    OTHERDIRS += audio
    endif
    
    ifeq ($(CONFIG_DRIVERS_WIRELESS),y)
    NONFSDIRS += wireless
    else
    OTHERDIRS += wireless
    endif
    
    # CLEANDIRS are the directories that will clean in.  These are
    #   all directories that we know about.
    # KERNDEPDIRS are the directories in which we will build target dependencies.
    #   If NuttX and applications are built separately (CONFIG_BUILD_PROTECTED or
    #   CONFIG_BUILD_KERNEL), then this holds only the directories containing
    #   kernel files.
    # USERDEPDIRS. If NuttX and applications are built separately (CONFIG_BUILD_PROTECTED),
    #   then this holds only the directories containing user files. If
    #   CONFIG_BUILD_KERNEL is selected, then applications are not build at all.
    
    CLEANDIRS   = $(NONFSDIRS) $(FSDIRS) $(USERDIRS) $(OTHERDIRS)
    KERNDEPDIRS = $(NONFSDIRS)
    USERDEPDIRS = $(USERDIRS)
    
    # Add file system directories to KERNDEPDIRS (they are already in CLEANDIRS)
    
    ifeq ($(CONFIG_NFILE_DESCRIPTORS),0)
    ifeq ($(CONFIG_NET),y)
    ifneq ($(CONFIG_NSOCKET_DESCRIPTORS),0)
    KERNDEPDIRS += fs
    endif
    KERNDEPDIRS += drivers
    endif
    else
    KERNDEPDIRS += $(FSDIRS)
    endif
    
    # Add networking directories to KERNDEPDIRS and CLEANDIRS
    
    ifeq ($(CONFIG_NET),y)
    KERNDEPDIRS += net
    endif
    CLEANDIRS += net
    
    ifeq ($(CONFIG_CRYPTO),y)
    KERNDEPDIRS += crypto
    endif
    CLEANDIRS += crypto
    
    

    FlatLibs.mk

    内存配置在Flat模式情况下,会使用FlatLibs.mk文件,该文件主要定义NUTTXLIBSUSERLIBS,其中NUTTXLIBS包含了一系列的库文件,最终用于特定处理器来编译Nuttx ImageUSERLIBS包含一系列库文件用于用户层的Apps。此外,还定义了EXPORTLIBS,用于在make export时,生成库文件。

    # NUTTXLIBS is the list of NuttX libraries that is passed to the
    #   processor-specific Makefile to build the final NuttX target.
    #   Libraries in FSDIRS are excluded if file descriptor support
    #   is disabled.
    # USERLIBS is the list of libraries used to build the final user-space
    #   application
    # EXPORTLIBS is the list of libraries that should be exported by
    #   'make export' is
    
    NUTTXLIBS = lib$(DELIM)libsched$(LIBEXT)
    USERLIBS =
    
    # Driver support.  Generally depends on file descriptor support but there
    # are some components in the drivers directory that are needed even if file
    # descriptors are not supported.
    
    NUTTXLIBS += lib$(DELIM)libdrivers$(LIBEXT)
    
    # Add libraries for board support
    
    NUTTXLIBS += lib$(DELIM)libconfigs$(LIBEXT)
    
    # Add libraries for syscall support.
    
    NUTTXLIBS += lib$(DELIM)libc$(LIBEXT) lib$(DELIM)libmm$(LIBEXT)
    NUTTXLIBS += lib$(DELIM)libarch$(LIBEXT)
    ifeq ($(CONFIG_LIB_SYSCALL),y)
    NUTTXLIBS += lib$(DELIM)libstubs$(LIBEXT)
    USERLIBS  += lib$(DELIM)libproxies$(LIBEXT)
    endif
    
    # Add libraries for C++ support.  CXX, CXXFLAGS, and COMPILEXX must
    # be defined in Make.defs for this to work!
    
    ifeq ($(CONFIG_HAVE_CXX),y)
    NUTTXLIBS += lib$(DELIM)libcxx$(LIBEXT)
    endif
    
    # Add library for application support.
    
    ifneq ($(APPDIR),)
    NUTTXLIBS += lib$(DELIM)libapps$(LIBEXT)
    endif
    
    # Add libraries for network support
    
    ifeq ($(CONFIG_NET),y)
    NUTTXLIBS += lib$(DELIM)libnet$(LIBEXT)
    endif
    
    # Add libraries for Crypto API support
    
    ifeq ($(CONFIG_CRYPTO),y)
    NUTTXLIBS += lib$(DELIM)libcrypto$(LIBEXT)
    endif
    
    # Add libraries for file system support
    
    ifeq ($(CONFIG_NFILE_DESCRIPTORS),0)
    ifneq ($(CONFIG_NSOCKET_DESCRIPTORS),0)
    NUTTXLIBS += lib$(DELIM)libfs$(LIBEXT)
    endif
    else
    NUTTXLIBS += lib$(DELIM)libfs$(LIBEXT) lib$(DELIM)libbinfmt$(LIBEXT)
    endif
    
    # Add libraries for the NX graphics sub-system
    
    ifeq ($(CONFIG_NX),y)
    NUTTXLIBS += lib$(DELIM)libgraphics$(LIBEXT)
    NUTTXLIBS += lib$(DELIM)libnx$(LIBEXT)
    endif
    
    # Add libraries for the Audio sub-system
    
    ifeq ($(CONFIG_AUDIO),y)
    NUTTXLIBS += lib$(DELIM)libaudio$(LIBEXT)
    endif
    
    # Add libraries for the Wireless sub-system
    
    ifeq ($(CONFIG_WIRELESS),y)
    NUTTXLIBS += lib$(DELIM)libwireless$(LIBEXT)
    endif
    
    # Add C++ library
    
    ifeq ($(CONFIG_HAVE_CXX),y)
    NUTTXLIBS += lib$(DELIM)libcxx$(LIBEXT)
    endif
    
    # Export all libraries
    
    EXPORTLIBS = $(NUTTXLIBS)
    
    

    tools/

    tools目录下包含了各种各样的脚本和Host C程序,这些都是Nuttx编译系统的必要的部分。README.txt有详尽的介绍。

    Makefile.unix

    Makefile.unix才是我们的核心,上述所介绍的文件,最终都要为它所用,直接看代码吧。

    TOPDIR := ${shell pwd | sed -e 's/ /\\ /g'}
    -include $(TOPDIR)/.config
    include $(TOPDIR)/tools/Config.mk
    -include $(TOPDIR)/Make.defs
    
    # 可以通过“make V=1”的形式来选择不同的编译方式,其中V=1/2时,会使能命令的回显,而在Makefile中“@”可以控制命令不回显。
    # Control build verbosity
    #
    #  V=1,2: Enable echo of commands
    #  V=2:   Enable bug/verbose options in tools and scripts
    
    ifeq ($(V),1)
    export Q :=
    else
    ifeq ($(V),2)
    export Q :=
    else
    export Q := @
    endif
    endif
    
    # Default tools
    
    # 定义符号链接和断开链接的宏
    ifeq ($(DIRLINK),)
    DIRLINK = $(TOPDIR)/tools/link.sh
    DIRUNLINK = $(TOPDIR)/tools/unlink.sh
    endif
    
    # This define is passed as EXTRADEFINES for kernel-mode builds.  It is also passed
    # during PASS1 (but not PASS2) context and depend targets.
    
    KDEFINE = ${shell $(TOPDIR)/tools/define.sh "$(CC)" __KERNEL__}
    
    # Process architecture and board-specific directories
    
    #架构和板级相关的目录宏定义
    ARCH_DIR = arch/$(CONFIG_ARCH)
    ARCH_SRC = $(ARCH_DIR)/src
    ARCH_INC = $(ARCH_DIR)/include
    
    ifeq ($(CONFIG_ARCH_BOARD_CUSTOM),y)
    ifeq ($(CONFIG_ARCH_BOARD_CUSTOM_DIR_RELPATH),y)
    BOARD_DIR = $(TOPDIR)$(DELIM)$(CONFIG_ARCH_BOARD_CUSTOM_DIR)
    else
    BOARD_DIR = $(CONFIG_ARCH_BOARD_CUSTOM_DIR)
    endif
    else
    BOARD_DIR = $(TOPDIR)$(DELIM)configs/hobot$(DELIM)$(CONFIG_ARCH_BOARD)
    endif
    
    # CONFIG_APPS_DIR can be over-ridden from the command line or in the .config file.
    # The default value of CONFIG_APPS_DIR is ../apps.  Ultimately, the application
    # will be built if APPDIR is defined.  APPDIR will be defined if a directory containing
    # a Makefile is found at the path provided by CONFIG_APPS_DIR
    
    #  当在CONFIG_APPS_DIR路径中存在Makefile时,APPDIR才会被定义
    ifeq ($(CONFIG_APPS_DIR),)
    CONFIG_APPS_DIR = ../apps
    endif
    APPDIR := ${shell if [ -r $(CONFIG_APPS_DIR)/Makefile ]; then echo "$(CONFIG_APPS_DIR)"; fi}
    
    # Add-on directories.  These may or may not be in place in the
    # NuttX source tree (they must be specifically installed)
    #
    # NUTTX_ADDONS is the list of directories built into the NuttX kernel.
    # USER_ADDONS is the list of directories that will be built into the user
    #   application
    #
    # FSDIRS depend on file descriptor support; NONFSDIRS do not (except for parts
    #   of FSDIRS).  We will exclude FSDIRS from the build if file descriptor
    #   support is disabled
    # CONTEXTDIRS include directories that have special, one-time pre-build
    #   requirements.  Normally this includes things like auto-generation of
    #   configuration specific files or creation of configurable symbolic links
    # USERDIRS - When NuttX is build is a monolithic kernel, this provides the
    #   list of directories that must be built
    # OTHERDIRS - These are directories that are not built but probably should
    #   be cleaned to prevent garbage from collecting in them when changing
    #   configurations.
    #
    # CLEANDIRS are the directories that will clean in.  These are
    #   all directories that we know about.
    # KERNDEPDIRS are the directories in which we will build target dependencies.
    #   If NuttX and applications are built separately (CONFIG_BUILD_PROTECTED or
    #   CONFIG_BUILD_KERNEL), then this holds only the directories containing
    #   kernel files.
    # USERDEPDIRS. If NuttX and applications are built separately (CONFIG_BUILD_PROTECTED),
    #   then this holds only the directories containing user files. If
    #   CONFIG_BUILD_KERNEL is selected, then applications are not build at all.
    
    # 定义了一系列文件夹相关的宏
    include Directories.mk
    
    #
    # Extra objects used in the final link.
    #
    # Pass 1 1ncremental (relative) link objects should be put into the
    # processor-specific source directory (where other link objects will
    # be created).  If the pass1 object is an archive, it could go anywhere.
    
    ifeq ($(CONFIG_BUILD_2PASS),y)
    EXTRA_OBJS += $(CONFIG_PASS1_OBJECT)
    endif
    
    # Library build selections
    #
    # NUTTXLIBS is the list of NuttX libraries that is passed to the
    #   processor-specific Makefile to build the final NuttX target.
    #   Libraries in FSDIRS are excluded if file descriptor support
    #   is disabled.
    # USERLIBS is the list of libraries used to build the final user-space
    #   application
    # EXPORTLIBS is the list of libraries that should be exported by
    #   'make export' is
    
    ifeq ($(CONFIG_BUILD_PROTECTED),y)
    include ProtectedLibs.mk
    else
    ifeq ($(CONFIG_BUILD_KERNEL),y)
    include KernelLibs.mk
    else
    include FlatLibs.mk
    endif
    endif
    
    # LINKLIBS derives from NUTTXLIBS and is simply the same list with the
    #   subdirectory removed
    
    #LINKLIBS链接库和NUTTXLIBS是一样的,只是通过patsubst将子目录lib去掉了而已
    LINKLIBS = $(patsubst lib/%,%,$(NUTTXLIBS))
    
    # Export tool definitions
    
    #用于'make export'
    MKEXPORT= tools/mkexport.sh
    MKEXPORT_ARGS = -w$(WINTOOL) -t "$(TOPDIR)"
    
    ifeq ($(CONFIG_BUILD_PROTECTED),y)
    MKEXPORT_ARGS += -u
    else
    ifeq ($(CONFIG_BUILD_KERNEL),y)
    MKEXPORT_ARGS += -u
    endif
    endif
    
    ifeq ($(V),2)
    MKEXPORT_ARGS += -d
    endif
    
    # This is the name of the final target (relative to the top level directorty)
    
    NUTTXNAME = nuttx
    BIN       = $(NUTTXNAME)$(EXEEXT)
    
    #编译的最终目标:nuttx, .PHONY用来声明伪目标
    all: $(BIN)
    .PHONY: dirlinks context clean_context check_context export subdir_clean clean subdir_distclean distclean apps_clean apps_distclean
    
    #头文件:math.h、float.h、stdarg.h,在不同的平台中可能有不同的实现
    # Target used to copy include/nuttx/lib/math.h.  If CONFIG_ARCH_MATH_H is
    # defined, then there is an architecture specific math.h header file
    # that will be included indirectly from include/math.h.  But first, we
    # have to copy math.h from include/nuttx/. to include/.  Logic within
    # include/nuttx/lib/math.h will hand the redirection to the architecture-
    # specific math.h header file.
    #
    # If the CONFIG_LIBM is defined, the Rhombus libm will be built at libc/math.
    # Definitions and prototypes for the Rhombus libm are also contained in
    # include/nuttx/lib/math.h and so the file must also be copied in that case.
    #
    # If neither CONFIG_ARCH_MATH_H nor CONFIG_LIBM is defined, then no math.h
    # header file will be provided.  You would want that behavior if (1) you
    # don't use libm, or (2) you want to use the math.h and libm provided
    # within your toolchain.
    
    ifeq ($(CONFIG_ARCH_MATH_H),y)
    NEED_MATH_H = y
    else
    ifeq ($(CONFIG_LIBM),y)
    NEED_MATH_H = y
    endif
    endif
    
    ifeq ($(NEED_MATH_H),y)
    include/math.h: include/nuttx/lib/math.h
        $(Q) cp -f include/nuttx/lib/math.h include/math.h
    else
    include/math.h:
    endif
    
    # The float.h header file defines the properties of your floating point
    # implementation.  It would always be best to use your toolchain's float.h
    # header file but if none is available, a default float.h header file will
    # provided if this option is selected.  However there is no assurance that
    # the settings in this float.h are actually correct for your platform!
    
    ifeq ($(CONFIG_ARCH_FLOAT_H),y)
    include/float.h: include/nuttx/lib/float.h
        $(Q) cp -f include/nuttx/lib/float.h include/float.h
    else
    include/float.h:
    endif
    
    # Target used to copy include/nuttx/lib/stdarg.h.  If CONFIG_ARCH_STDARG_H is
    # defined, then there is an architecture specific stdarg.h header file
    # that will be included indirectly from include/lib/stdarg.h.  But first, we
    # have to copy stdarg.h from include/nuttx/. to include/.
    
    ifeq ($(CONFIG_ARCH_STDARG_H),y)
    include/stdarg.h: include/nuttx/lib/stdarg.h
        $(Q) cp -f include/nuttx/lib/stdarg.h include/stdarg.h
    else
    include/stdarg.h:
    endif
    
    # Targets used to build include/nuttx/version.h.  Creation of version.h is
    # part of the overall NuttX configuration sequence. Notice that the
    # tools/mkversion tool is built and used to create include/nuttx/version.h
    
    # 先编译mkversion工具,再用该工具来创建version.h文件。下行make命令中,-C后边指定需要执行make的路径,此处指tools目录,
    # -f指定Makefile文件,此处指Makefile.host,并将TOPDIR这个宏的值传递给Makefile.unix,make的目标是mkversion$(HOSTEXEEXT)
    # 当make命令中带有多个参数时,注意'-'和'='等特殊符号,没特殊符号约束的就是make的目标,比如此处的mkversion$(HOSTEXEEXT)
    tools/mkversion$(HOSTEXEEXT):
        $(Q) $(MAKE) -C tools -f Makefile.host TOPDIR="$(TOPDIR)"  mkversion$(HOSTEXEEXT)
    
    # 查看是否存在.version文件
    $(TOPDIR)/.version:
        $(Q) if [ ! -f .version ]; then \
            echo "No .version file found, creating one"; \
            tools/version.sh -v 0.0 -b 0 .version; \
            chmod 755 .version; \
        fi
    
    # 创建version.h文件
    include/nuttx/version.h: $(TOPDIR)/.version tools/mkversion$(HOSTEXEEXT)
        $(Q) tools/mkversion $(TOPDIR) > include/nuttx/version.h
    
    # ROMFS,其中rcS.template为启动脚本,nsh_romfsimg.h是根据这个启动脚本而产生的头部信息
    arch/arm/include/board/nsh_romfsimg.h:
    ifeq ($(CONFIG_NSH_ARCHROMFS),y)
        $(Q) if [ ! -f $(BOARD_DIR)/include/rcS.template ]; then \
            echo "No rcS.template file create it!!!!!"; \
        fi
        $(Q) cp -f $(BOARD_DIR)/include/rcS.template $(TOPDIR)/rcS.template
    
        $(Q) tools/mkromfsimg.sh $(TOPDIR)
        $(Q) if [ ! -f $(TOPDIR)/nsh_romfsimg.h ]; then \
            echo "No nsh_romfsimg.h file create !!!!!"; \
        fi
        $(Q) cp -f nsh_romfsimg.h arch/arm/include/board/
        $(Q) rm -f $(TOPDIR)/rcS.template $(TOPDIR)/nsh_romfsimg.h
    else
        $(Q) echo "use nsh defalut nsh_romfsimg.h for romfs"
    endif
    
    # Targets used to build include/nuttx/config.h.  Creation of config.h is
    # part of the overall NuttX configuration sequence. Notice that the
    # tools/mkconfig tool is built and used to create include/nuttx/config.h
    
    # 创建config.h文件
    tools/mkconfig$(HOSTEXEEXT):
        $(Q) $(MAKE) -C tools -f Makefile.host TOPDIR="$(TOPDIR)"  mkconfig$(HOSTEXEEXT)
    
    include/nuttx/config.h: $(TOPDIR)/.config tools/mkconfig$(HOSTEXEEXT)
        $(Q) tools/mkconfig $(TOPDIR) > include/nuttx/config.h
    
    # Targets used to create dependencies
    
    # 编译Host上创建dependency的工具
    tools/mkdeps$(HOSTEXEEXT):
        $(Q) $(MAKE) -C tools -f Makefile.host TOPDIR="$(TOPDIR)" mkdeps$(HOSTEXEEXT)
    
    tools/cnvwindeps$(HOSTEXEEXT):
        $(Q) $(MAKE) -C tools -f Makefile.host TOPDIR="$(TOPDIR)" cnvwindeps$(HOSTEXEEXT)
    
    # dirlinks, and helpers
    #
    # Directories links.  Most of establishing the NuttX configuration involves
    # setting up symbolic links with 'generic' directory names to specific,
    # configured directories.
    
    # Make.defs:
    #   $(Q) echo "No Make.defs file found, creating one"
    #   $(Q) echo "include $(TOPDIR)$(DELIM).config" > Make.defs
    #   $(Q) echo "include $(TOPDIR)$(DELIM)tools$(DELIM)Config.mk" >> Make.defs
    
    # tools/initialconfig$(HOSTEXEEXT):
    #   $(Q) $(MAKE) -C tools -f Makefile.host TOPDIR="$(TOPDIR)" initialconfig$(HOSTEXEEXT)
    #
    # .config: tools/initialconfig$(HOSTEXEEXT)
    #   $(Q) echo "No .config file found, creating one"
    #   $(Q) tools/initialconfig$(HOSTEXEEXT)
    
    # Link the arch/<arch-name>/include directory to include/arch
    
    include/arch: .config
        @echo "LN: include/arch to $(ARCH_DIR)/include"
        $(Q) $(DIRLINK) $(TOPDIR)/$(ARCH_DIR)/include include/arch
    
    # Link the configs/<board-name>/include directory to include/arch/board
    
    include/arch/board: include/arch
        @echo "LN: include/arch/board to $(BOARD_DIR)/include"
        $(Q) $(DIRLINK) $(BOARD_DIR)/include include/arch/board
    
    # Link the configs/<board-name>/src dir to arch/<arch-name>/src/board
    
    $(ARCH_SRC)/board: .config
        @echo "LN: $(ARCH_SRC)/board to $(BOARD_DIR)/src"
        $(Q) $(DIRLINK) $(BOARD_DIR)/src $(ARCH_SRC)/board
    
    # Link arch/<arch-name>/include/<chip-name> to arch/<arch-name>/include/chip
    
    $(ARCH_SRC)/chip: .config
    ifneq ($(CONFIG_ARCH_CHIP),)
        @echo "LN: $(ARCH_SRC)/chip to $(ARCH_SRC)/$(CONFIG_ARCH_CHIP)"
        $(Q) $(DIRLINK) $(TOPDIR)/$(ARCH_SRC)/$(CONFIG_ARCH_CHIP) $(ARCH_SRC)/chip
    endif
    
    # Link arch/<arch-name>/src/<chip-name> to arch/<arch-name>/src/chip
    
    include/arch/chip: include/arch
    ifneq ($(CONFIG_ARCH_CHIP),)
        @echo "LN: include/arch/chip to $(ARCH_INC)/$(CONFIG_ARCH_CHIP)"
        $(Q) $(DIRLINK) $(TOPDIR)/$(ARCH_INC)/$(CONFIG_ARCH_CHIP) include/arch/chip
    endif
    
    # 根据依赖关系创建链接,进入nuttx/configs目录中,执行make dirlinks;进入apps/目录中,执行make dirlinks
    dirlinks: include/arch include/arch/board include/arch/chip $(ARCH_SRC)/board $(ARCH_SRC)/chip
        $(Q) $(MAKE) -C configs dirlinks TOPDIR="$(TOPDIR)"
        $(Q) $(MAKE) -C $(CONFIG_APPS_DIR) dirlinks TOPDIR="$(TOPDIR)"
    
    # context
    #
    # The context target is invoked on each target build to assure that NuttX is
    # properly configured.  The basic configuration steps include creation of the
    # the config.h and version.h header files in the include/nuttx directory and
    # the establishment of symbolic links to configured directories.
    
    # CONTEXTDIRS在Directories.mk中定义
    context: check_context include/nuttx/config.h include/nuttx/version.h include/math.h include/float.h include/stdarg.h dirlinks arch/arm/include/board/nsh_romfsimg.h
        $(Q) for dir in $(CONTEXTDIRS) ; do \
            $(MAKE) -C $$dir TOPDIR="$(TOPDIR)" context; \
        done
    
    # clean_context
    #
    # This is part of the distclean target.  It removes all of the header files
    # and symbolic links created by the context target.
    
    clean_context:
        $(Q) $(MAKE) -C configs TOPDIR="$(TOPDIR)" clean_context
        $(call DELFILE, include/nuttx/config.h)
        $(call DELFILE, include/nuttx/version.h)
        $(call DELFILE, arch/arm/include/board/nsh_romfsimg.h)
        $(call DELFILE, include/math.h)
        $(call DELFILE, include/stdarg.h)
        $(Q) $(DIRUNLINK) include/arch/board
        $(Q) $(DIRUNLINK) include/arch/chip
        $(Q) $(DIRUNLINK) include/arch
        $(Q) $(DIRUNLINK) $(ARCH_SRC)/board
        $(Q) $(DIRUNLINK) $(ARCH_SRC)/chip
    
    # 检查Nuttx是否已经被配置好
    # check_context
    #
    # This target checks if NuttX has been configured.  NuttX is configured using
    # the script tools/configure.sh.  That script will install certain files in
    # the top-level NuttX build directory.  This target verifies that those
    # configuration files have been installed and that NuttX is ready to be built.
    
    check_context:
        $(Q) if [ ! -e ${TOPDIR}/.config -o ! -e ${TOPDIR}/Make.defs ]; then \
            echo "" ; echo "Nuttx has not been configured:" ; \
            echo "  cd tools; ./configure.sh <target>" ; echo "" ; \
            exit 1 ; \
        fi
    
    # Archive targets.  The target build sequence will first create a series of
    # libraries, one per configured source file directory.  The final NuttX
    # execution will then be built from those libraries.  The following targets
    # build those libraries.
    
    #包含各种库文件
    include LibTargets.mk
    
    # pass1 and pass2
    #
    # If the 2 pass build option is selected, then this pass1 target is
    # configured to built before the pass2 target.  This pass1 target may, as an
    # example, build an extra link object (CONFIG_PASS1_OBJECT) which may be an
    # incremental (relative) link object, but could be a static library (archive);
    # some modification to this Makefile would be required if CONFIG_PASS1_OBJECT
    # is an archive.  Exactly what is performed during pass1 or what it generates
    # is unknown to this makefile unless CONFIG_PASS1_OBJECT is defined.
    
    # PASS1为apps部分
    pass1deps: pass1dep $(USERLIBS)
    
    # 如果定义了CONFIG_BUILD_2PASS,则需要先编译PASS1
    pass1: pass1deps
    ifeq ($(CONFIG_BUILD_2PASS),y)
        $(Q) if [ -z "$(CONFIG_PASS1_BUILDIR)" ]; then \
            echo "ERROR: CONFIG_PASS1_BUILDIR not defined"; \
            exit 1; \
        fi
        $(Q) if [ ! -d "$(CONFIG_PASS1_BUILDIR)" ]; then \
            echo "ERROR: CONFIG_PASS1_BUILDIR does not exist"; \
            exit 1; \
        fi
        $(Q) if [ ! -f "$(CONFIG_PASS1_BUILDIR)/Makefile" ]; then \
            echo "ERROR: No Makefile in CONFIG_PASS1_BUILDIR"; \
            exit 1; \
        fi
        $(Q) $(MAKE) -C $(CONFIG_PASS1_BUILDIR) TOPDIR="$(TOPDIR)" LINKLIBS="$(LINKLIBS)" USERLIBS="$(USERLIBS)" "$(CONFIG_PASS1_TARGET)"
    endif
    
    # PASS2为nuttx部分
    pass2deps: pass2dep $(NUTTXLIBS)
    
    pass2: pass2deps
        $(Q) $(MAKE) -C $(ARCH_SRC) TOPDIR="$(TOPDIR)" EXTRA_OBJS="$(EXTRA_OBJS)" LINKLIBS="$(LINKLIBS)" EXTRADEFINES=$(KDEFINE) $(BIN)
        $(Q) if [ -w /tftpboot ] ; then \
            cp -f $(BIN) /tftpboot/$(BIN).${CONFIG_ARCH}; \
        fi
    ifeq ($(CONFIG_RRLOAD_BINARY),y)
        @echo "MK: $(NUTTXNAME).rr"
        $(Q) $(TOPDIR)/tools/mkimage.sh --Prefix $(CROSSDEV) $(BIN) $(NUTTXNAME).rr
        $(Q) if [ -w /tftpboot ] ; then \
            cp -f $(NUTTXNAME).rr /tftpboot/$(NUTTXNAME).rr.$(CONFIG_ARCH); \
        fi
    endif
    ifeq ($(CONFIG_INTELHEX_BINARY),y)
        @echo "CP: $(NUTTXNAME).hex"
        $(Q) $(OBJCOPY) $(OBJCOPYARGS) -O ihex $(BIN) $(NUTTXNAME).hex
    endif
    ifeq ($(CONFIG_MOTOROLA_SREC),y)
        @echo "CP: $(NUTTXNAME).srec"
        $(Q) $(OBJCOPY) $(OBJCOPYARGS) -O srec $(BIN) $(NUTTXNAME).srec
    endif
    ifeq ($(CONFIG_RAW_BINARY),y)    #生成RAW格式文件,并生成nuttx.bin文件
        @echo "CP: $(NUTTXNAME).bin"
        $(Q) $(OBJCOPY) $(OBJCOPYARGS) -O binary $(BIN) $(NUTTXNAME).bin
    endif
    ifeq ($(CONFIG_UBOOT_UIMAGE),y)
        @echo "MKIMAGE: uImage"
        $(Q) mkimage -A arm -O linux -C none -T kernel -a $(CONFIG_UIMAGE_LOAD_ADDRESS) \
            -e $(CONFIG_UIMAGE_ENTRY_POINT) -n $(BIN) -d $(NUTTXNAME).bin uImage
        $(Q) if [ -w /tftpboot ] ; then \
            cp -f uImage /tftpboot/uImage; \
        fi
    endif
    
    # $(BIN)
    #
    # Create the final NuttX executable in a two pass build process.  In the
    # normal case, all pass1 and pass2 dependencies are created then pass1
    # and pass2 targets are built.  However, in some cases, you may need to build
    # pass1 dependencies and pass1 first, then build pass2 dependencies and pass2.
    # in that case, execute 'make pass1 pass2' from the command line.
    
    $(BIN): pass1deps pass2deps pass1 pass2
    
    # download
    #
    # This is a helper target that will rebuild NuttX and download it to the target
    # system in one step.  The operation of this target depends completely upon
    # implementation of the DOWNLOAD command in the user Make.defs file.  It will
    # generate an error an error if the DOWNLOAD command is not defined.
    
    download: $(BIN)
        $(call DOWNLOAD, $<)
    
    # pass1dep: Create pass1 build dependencies
    # pass2dep: Create pass2 build dependencies
    
    # 创建pass1的依赖关系,make depend后,将会生成Make.dep文件
    pass1dep: context tools/mkdeps$(HOSTEXEEXT) tools/cnvwindeps$(HOSTEXEEXT)
        $(Q) for dir in $(USERDEPDIRS) ; do \
            $(MAKE) -C $$dir TOPDIR="$(TOPDIR)" depend ; \
        done
    
    # 创建pass2的依赖关系,make depend后,将会生成Make.dep文件
    pass2dep: context tools/mkdeps$(HOSTEXEEXT) tools/cnvwindeps$(HOSTEXEEXT)
        $(Q) for dir in $(KERNDEPDIRS) ; do \
            $(MAKE) -C $$dir TOPDIR="$(TOPDIR)" EXTRADEFINES=$(KDEFINE) depend; \
        done
    
    # Configuration targets
    #
    # These targets depend on the kconfig-frontends packages.  To use these, you
    # must first download and install the kconfig-frontends package from this
    # location: http://ymorin.is-a-geek.org/projects/kconfig-frontends.  See
    # README.txt file in the NuttX tools GIT repository for additional information.
    
    # 配置目标
    do_config: dirlinks apps_preconfig
        $(Q) APPSDIR=${CONFIG_APPS_DIR} kconfig-conf Kconfig
    
    config: do_config clean_context
    
    do_oldconfig: dirlinks apps_preconfig
        $(Q) APPSDIR=${CONFIG_APPS_DIR} kconfig-conf --oldconfig Kconfig
    
    oldconfig: do_oldconfig clean_context
    
    do_olddefconfig: dirlinks apps_preconfig
        $(Q) APPSDIR=${CONFIG_APPS_DIR} kconfig-conf --olddefconfig Kconfig
    
    olddefconfig: do_olddefconfig clean_context
    
    do_menuconfig: dirlinks apps_preconfig
        $(Q) APPSDIR=${CONFIG_APPS_DIR} kconfig-mconf Kconfig
    
    menuconfig: do_menuconfig clean_context
    
    do_qconfig: dirlinks apps_preconfig
        $(Q) APPSDIR=${CONFIG_APPS_DIR} kconfig-qconf Kconfig
    
    qconfig: do_qconfig clean_context
    
    do_gconfig: dirlinks apps_preconfig
        $(Q) APPSDIR=${CONFIG_APPS_DIR} kconfig-gconf Kconfig
    
    gconfig: do_gconfig clean_context
    
    # export
    #
    # The export target will package the NuttX libraries and header files into
    # an exportable package.  Caveats: (1) These needs some extension for the KERNEL
    # build; it needs to receive USERLIBS and create a libuser.a). (2) The logic
    # in tools/mkexport.sh only supports GCC and, for example, explicitly assumes
    # that the archiver is 'ar'
    
    # 'make export'将生成一个打包文件,将nuttx内核中的库及头文件放置在一起
    export: pass2deps
        $(Q) MAKE=${MAKE} $(MKEXPORT) $(MKEXPORT_ARGS) -l "$(EXPORTLIBS)"
    
    # General housekeeping targets:  dependencies, cleaning, etc.
    #
    # depend:    Create both PASS1 and PASS2 dependencies
    # clean:     Removes derived object files, archives, executables, and
    #            temporary files, but retains the configuration and context
    #            files and directories.
    # distclean: Does 'clean' then also removes all configuration and context
    #            files.  This essentially restores the directory structure
    #            to its original, unconfigured stated.
    
    # 生成依赖关系
    depend: pass1dep pass2dep
    
    subdir_clean:
        $(Q) for dir in $(CLEANDIRS) ; do \
            if [ -e $$dir/Makefile ]; then \
                $(MAKE) -C $$dir TOPDIR="$(TOPDIR)" clean ; \
            fi \
        done
        $(Q) $(MAKE) -C tools -f Makefile.host TOPDIR="$(TOPDIR)" clean
    ifeq ($(CONFIG_BUILD_2PASS),y)
        $(Q) $(MAKE) -C $(CONFIG_PASS1_BUILDIR) TOPDIR="$(TOPDIR)" clean
    endif
    
    # make clean,将目录中生成的文件都删除掉
    clean: subdir_clean
        $(call DELFILE, $(BIN))
        $(call DELFILE, nuttx.*)
        $(call DELFILE, *.map)
        $(call DELFILE, _SAVED_APPS_config)
        $(call DELFILE, nuttx-export*)
        $(call DELFILE, nuttx_user*)
        $(call CLEAN)
    
    subdir_distclean:
        $(Q) for dir in $(CLEANDIRS) ; do \
            if [ -e $$dir/Makefile ]; then \
                $(MAKE) -C $$dir TOPDIR="$(TOPDIR)" distclean ; \
            fi \
        done
    
    # make distclean,将目录中生成的文件,以及配置项都删除掉
    distclean: clean subdir_distclean clean_context
    ifeq ($(CONFIG_BUILD_2PASS),y)
        $(Q) $(MAKE) -C $(CONFIG_PASS1_BUILDIR) TOPDIR="$(TOPDIR)" distclean
    endif
        $(call DELFILE, Make.defs)
        $(call DELFILE, .config)
        $(call DELFILE, .config.old)
    
    # Application housekeeping targets.  The APPDIR variable refers to the user
    # application directory.  A sample apps/ directory is included with NuttX,
    # however, this is not treated as part of NuttX and may be replaced with a
    # different application directory.  For the most part, the application
    # directory is treated like any other build directory in this script.  However,
    # as a convenience, the following targets are included to support housekeeping
    # functions in the user application directory from the NuttX build directory.
    #
    # apps_preconfig: Prepare applications to be configured
    # apps_clean:     Perform the clean operation only in the user application
    #                 directory
    # apps_distclean: Perform the distclean operation only in the user application
    #                 directory.
    
    # 针对apps目录下的配置及清除工作
    
    apps_preconfig:
    ifneq ($(APPDIR),)
        $(Q) $(MAKE) -C "$(TOPDIR)/$(APPDIR)" TOPDIR="$(TOPDIR)" preconfig
    endif
    
    apps_clean:
    ifneq ($(APPDIR),)
        $(Q) $(MAKE) -C "$(TOPDIR)/$(APPDIR)" TOPDIR="$(TOPDIR)" clean
    endif
    
    apps_distclean:
    ifneq ($(APPDIR),)
        $(Q) $(MAKE) -C "$(TOPDIR)/$(APPDIR)" TOPDIR="$(TOPDIR)" distclean
    endif
    
    

    顶层目录中的Makefile,通过make -C逐层进入子目录中,执行相应的编译动作,最终找到所有的依赖关系,生成nuttxnuttx.bin文件。
    apps目录中的编译方式也类似,从apps/Makefile开始分析即可。

    相关文章

      网友评论

        本文标题:Nuttx编译系统

        本文链接:https://www.haomeiwen.com/subject/gsegxqtx.html