Nuttx編譯系統(tǒng)

Nuttx相關(guān)的歷史文章:

配置

Nuttx在編譯之前需要先進(jìn)行配置,而Nuttx是一個(gè)高度可配置的RTOS,Nuttx的配置文件使用kconfig-frontends工具來(lái)維護(hù)官卡,配置工具將使用Kconfig文件,而Kconfig文件在Nuttx的代碼文件夾中隨處可見(jiàn)蝗羊。每一個(gè)Kconfig文件包含了配置變量的聲明固棚,而每一個(gè)配置變量又給Nuttx提供了一種配置選擇统翩,Nuttx的最終配置都由這些Kconfig文件決定。
一般進(jìn)行Nuttx配置的時(shí)候此洲,都可以在Nuttx根目錄中通過(guò)make menuconfig命令來(lái)操作厂汗,前提是在根目錄中需要有.config文件存在,而.config文件是從某個(gè)特定的開(kāi)發(fā)板中的某個(gè)路徑下拷貝過(guò)來(lái)的呜师。

要獲取.config文件娶桦,又有兩種途徑:一種是通過(guò)手動(dòng)將.configMake.defs文件從特定開(kāi)發(fā)板中的某個(gè)路徑中拷貝至Nuttx的頂層路徑;一種是通過(guò)tools目錄下的configure.sh腳本完成拷貝工作汁汗。最終在進(jìn)行編譯的時(shí)候衷畦,需要依賴這兩個(gè)文件。

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

每個(gè)特定的開(kāi)發(fā)板文件夾中都有兩個(gè)文件Make.defsdefconfig文件來(lái)描述該開(kāi)發(fā)板的配置知牌。

Make.defs

  1. Make.defs提供架構(gòu)和特定工具的構(gòu)建選項(xiàng)祈争,在編譯時(shí)它將被其他所有的Makefile包含,它將定義如下內(nèi)容:
  • Tools: CC, LD, AR, NM, OBJCOPY, OBJDUMP
  • Tools options: CFLAGS, LDFLAGS
  1. 當(dāng)Make.defs運(yùn)行時(shí)角寸,TOPDIR會(huì)傳遞給它菩混,在Make.defs中將包含以下兩個(gè)文件:
  • $(TOPDIR)/.config: Nuttx的配置
  • $(TOPDIR)/tools/Config.mk:一些通用的定義忿墅。tools/Config.mk文件中包含了一些額外的宏定義,這些宏定義的值在需要的時(shí)候可能會(huì)在特定架構(gòu)中的Make.defs中被覆蓋沮峡,比如:COMPILE, ASSEMBLE, ARCHIVE, CLEAN, MKDEP等球匕。

defconfig
defconfig文件中包含一些如CONFIG_VARIABLE=value形式的定義,它拷貝至$(TOPDIR)路徑下后帖烘,在編譯時(shí)會(huì)被其他Makefile所包含,并且會(huì)用它來(lái)生成include/nuttx/config.h文件橄杨,這個(gè)文件在很多C文件中會(huì)用到秘症。

編譯

大概的目錄組織如下:

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

先羅列一下編譯時(shí)所需要的文件,其中$(TOPDIR)nuttx目錄式矫,編譯時(shí)是在nuttx目錄中進(jìn)行乡摹。

  • Makefile文件,包括各個(gè)目錄及子目錄下的Makefile文件
  • Make.defs文件采转,從特定開(kāi)發(fā)板目錄中拷貝過(guò)來(lái)的聪廉,見(jiàn)上文中的配置部分
  • .config文件,從特定開(kāi)發(fā)板目錄中拷貝過(guò)來(lái)的故慈,見(jiàn)上文中的配置部分
  • tools/Config.mk文件板熊,定義了某些通用的宏定義
  • tools/目錄,該目錄下提供了各類(lèi)工具(腳本/執(zhí)行文件)察绷,具體的功能也可以查看README.txt干签。
  • FlatLibs.mk/KernelLibs.mk/ProtectedLibs.mk文件,這三個(gè)文件分別對(duì)應(yīng)到內(nèi)存配置中的Flat模式拆撼、Kernel模式(需要MMU支持)容劳,保護(hù)模式(需要MPU支持),我使用的是Flat模式闸度,所以在實(shí)際編譯時(shí)只需要FlatLibs.mk文件即可竭贩。
  • Directories.mk文件,描述一些add-on目錄

完成配置后莺禁,編譯的過(guò)程很簡(jiǎn)單:

  • cd $(TOPDIR)
  • make
    上文中也提到過(guò)留量,$(TOPDIR)中的.config文件主要描述當(dāng)前的配置,Make.defs文件描述特定的開(kāi)發(fā)板配置睁宰。

系統(tǒng)第一次build的時(shí)候肪获,會(huì)有一些額外的配置動(dòng)作,包括:

  • 自動(dòng)使用$(TOPDIR)/.config來(lái)生成include/nuttx/config.h文件
  • 如果$(TOPDIR)/.version文件不存在的話柒傻,自動(dòng)使用version 0.0來(lái)生成
  • 自動(dòng)使用$(TOPDIR)/.version來(lái)生成include/nuttx/version.h文件
  • 創(chuàng)建鏈接孝赫,將$(TOPDIR)/include/arch鏈接到$(TOPDIR)/arch/<arch-name>/include目錄
  • 創(chuàng)建鏈接,將$(TOPDIR)/include/arch/board鏈接到$(TOPDIR)/configs/<board-name>/include目錄
  • 創(chuàng)建鏈接红符,將$(TOPDIR)/arch/<arch-name>/src/board鏈接到$(TOPDIR)/configs/<board-name>/src目錄
  • 創(chuàng)建鏈接青柄, 將$(TOPDIR)/include/apps鏈接到$(APPDIR)/include目錄
  • 創(chuàng)建make dependencies伐债,描述Makefile中的自動(dòng)依賴關(guān)系,文件為Make.dep

講這么多致开,還是直接從Makefile開(kāi)始入手跟蹤吧峰锁。在$(TOPDIR)目錄中,Makefile內(nèi)容如下:

...
-include .config    #將.config文件包含進(jìn)來(lái)双戳,其中`-`表示如果.config文件不存在虹蒋,Makefile也不會(huì)報(bào)錯(cuò),并繼續(xù)運(yùn)行
ifeq ($(CONFIG_WINDOWS_NATIVE),y)
include Makefile.win
else
include Makefile.unix    #根據(jù)編譯環(huán)境飒货,選擇對(duì)應(yīng)的Makefile魄衅,真正的入口
endif

下面將分別介紹上面講到的文件,核心是圍繞Makefile.unix文件塘辅。

.config

整個(gè).config文件內(nèi)容格式如下所示晃虫,用來(lái)定義配置選項(xiàng),在編譯時(shí)需要用到扣墩。

...
# 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)形式來(lái)使用呻惕,其中XXX表示定義的這些宏荆责。

# These are configuration variables that are quoted by configuration tool
# but which must be unquoated when used in the build system.

# 調(diào)整架構(gòu)相關(guān)宏的值,其中patsubst為Makefile匹配與替換函數(shù)蟆融,strip為去空格函數(shù)
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
# 預(yù)處理宏
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中定義了一些板級(jí)相關(guān)的宏定義草巡。

# 包含需要依賴的文件
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環(huán)境下使用的工具鏈
  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

# 定義所有編譯時(shí)的FLAG選項(xiàng)
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包含了一系列文件夾山憨,最終將編譯進(jìn)Nuttx內(nèi)核中,而USER_ADDONS包含了一系列文件夾弥喉,最終會(huì)編譯進(jìn)Apps中郁竟。Directories.mk將Nuttx內(nèi)核中的文件夾都包含了進(jìn)來(lái)。

# 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

內(nèi)存配置在Flat模式情況下由境,會(huì)使用FlatLibs.mk文件棚亩,該文件主要定義NUTTXLIBSUSERLIBS,其中NUTTXLIBS包含了一系列的庫(kù)文件虏杰,最終用于特定處理器來(lái)編譯Nuttx Image讥蟆,USERLIBS包含一系列庫(kù)文件用于用戶層的Apps。此外纺阔,還定義了EXPORTLIBS瘸彤,用于在make export時(shí),生成庫(kù)文件笛钝。

# 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編譯系統(tǒng)的必要的部分愕宋。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

# 可以通過(guò)“make V=1”的形式來(lái)選擇不同的編譯方式邻寿,其中V=1/2時(shí),會(huì)使能命令的回顯视哑,而在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

# 定義符號(hào)鏈接和斷開(kāi)鏈接的宏
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

#架構(gòu)和板級(jí)相關(guān)的目錄宏定義
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

#  當(dāng)在CONFIG_APPS_DIR路徑中存在Makefile時(shí),APPDIR才會(huì)被定義
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.

# 定義了一系列文件夾相關(guān)的宏
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鏈接庫(kù)和NUTTXLIBS是一樣的黎炉,只是通過(guò)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)

#編譯的最終目標(biāo):nuttx, .PHONY用來(lái)聲明偽目標(biāo)
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慷嗜,在不同的平臺(tái)中可能有不同的實(shí)現(xiàn)
# 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工具,再用該工具來(lái)創(chuàng)建version.h文件丹壕。下行make命令中庆械,-C后邊指定需要執(zhí)行make的路徑,此處指tools目錄菌赖,
# -f指定Makefile文件缭乘,此處指Makefile.host,并將TOPDIR這個(gè)宏的值傳遞給Makefile.unix琉用,make的目標(biāo)是mkversion$(HOSTEXEEXT)
# 當(dāng)make命令中帶有多個(gè)參數(shù)時(shí)堕绩,注意'-'和'='等特殊符號(hào),沒(méi)特殊符號(hào)約束的就是make的目標(biāo)邑时,比如此處的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

# 創(chuàng)建version.h文件
include/nuttx/version.h: $(TOPDIR)/.version tools/mkversion$(HOSTEXEEXT)
    $(Q) tools/mkversion $(TOPDIR) > include/nuttx/version.h

# ROMFS奴紧,其中rcS.template為啟動(dòng)腳本,nsh_romfsimg.h是根據(jù)這個(gè)啟動(dòng)腳本而產(chǎn)生的頭部信息
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

# 創(chuàng)建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上創(chuàng)建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

# 根據(jù)依賴關(guān)系創(chuàng)建鏈接晶丘,進(jìn)入nuttx/configs目錄中黍氮,執(zhí)行make dirlinks;進(jìn)入apps/目錄中浅浮,執(zhí)行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是否已經(jīng)被配置好
# 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.

#包含各種庫(kù)文件
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

# 創(chuàng)建pass1的依賴關(guān)系滚秩,make depend后专执,將會(huì)生成Make.dep文件
pass1dep: context tools/mkdeps$(HOSTEXEEXT) tools/cnvwindeps$(HOSTEXEEXT)
    $(Q) for dir in $(USERDEPDIRS) ; do \
        $(MAKE) -C $$dir TOPDIR="$(TOPDIR)" depend ; \
    done

# 創(chuàng)建pass2的依賴關(guān)系,make depend后叔遂,將會(huì)生成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.

# 配置目標(biāo)
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'將生成一個(gè)打包文件他炊,將nuttx內(nèi)核中的庫(kù)及頭文件放置在一起
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.

# 生成依賴關(guān)系
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,將目錄中生成的文件痊末,以及配置項(xiàng)都刪除掉
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.

# 針對(duì)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蚕苇,通過(guò)make -C逐層進(jìn)入子目錄中,執(zhí)行相應(yīng)的編譯動(dòng)作凿叠,最終找到所有的依賴關(guān)系涩笤,生成nuttxnuttx.bin文件。
apps目錄中的編譯方式也類(lèi)似盒件,從apps/Makefile開(kāi)始分析即可蹬碧。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市炒刁,隨后出現(xiàn)的幾起案子恩沽,更是在濱河造成了極大的恐慌,老刑警劉巖翔始,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件罗心,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡城瞎,警方通過(guò)查閱死者的電腦和手機(jī)渤闷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)脖镀,“玉大人飒箭,你說(shuō)我怎么就攤上這事⊙鸦遥” “怎么了弦蹂?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)强窖。 經(jīng)常有香客問(wèn)我盈匾,道長(zhǎng),這世上最難降的妖魔是什么毕骡? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任削饵,我火速辦了婚禮,結(jié)果婚禮上未巫,老公的妹妹穿的比我還像新娘窿撬。我一直安慰自己,他們只是感情好叙凡,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布劈伴。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪跛璧。 梳的紋絲不亂的頭發(fā)上严里,一...
    開(kāi)封第一講書(shū)人閱讀 51,688評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音追城,去河邊找鬼刹碾。 笑死,一個(gè)胖子當(dāng)著我的面吹牛座柱,可吹牛的內(nèi)容都是我干的迷帜。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼色洞,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼戏锹!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起火诸,我...
    開(kāi)封第一講書(shū)人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤锦针,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后置蜀,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體伞插,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年盾碗,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舀瓢。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡廷雅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出京髓,到底是詐尸還是另有隱情航缀,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布堰怨,位于F島的核電站芥玉,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏备图。R本人自食惡果不足惜灿巧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望揽涮。 院中可真熱鬧抠藕,春花似錦、人聲如沸蒋困。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)雪标。三九已至零院,卻和暖如春溉跃,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背告抄。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工撰茎, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人玄妈。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓乾吻,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親拟蜻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子绎签,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容