Nuttx在编译之前需要先进行配置,而Nuttx是一个高度可配置的RTOS,Nuttx的配置文件使用kconfig-frontends工具来维护,配置工具将使用Kconfig文件,而Kconfig文件在Nuttx的代码文件夹中随处可见。每一个Kconfig文件包含了配置变量的声明,而每一个配置变量又给Nuttx提供了一种配置选择,Nuttx的最终配置都由这些Kconfig文件决定。
一般进行Nuttx配置的时候,都可以在Nuttx根目录中通过make menuconfig命令来操作,前提是在根目录中需要有.config文件存在,而.config文件是从某个特定的开发板中的某个路径下拷贝过来的。
要获取.config文件,又有两种途径:一种是通过手动将.config和Make.defs文件从特定开发板中的某个路径中拷贝至Nuttx的顶层路径;一种是通过tools目录下的configure.sh脚本完成拷贝工作。最终在进行编译的时候,需要依赖这两个文件。
手动配置
Copy configs/<board-name>/[<config-dir>/]Make.defs to ${TOPDIR}/Make.defs
Copy configs/<board-name>/[<config-dir>/]defconfig to ${TOPDIR}/.config
自动配置
tools/confiure.sh [OPTIONS] <board-name>[/<config-dir>]
每个特定的开发板文件夹中都有两个文件Make.defs和defconfig文件来描述该开发板的配置。
Make.defs
Make.defs提供架构和特定工具的构建选项,在编译时它将被其他所有的Makefile包含,它将定义如下内容:
Tools: CC, LD, AR, NM, OBJCOPY, OBJDUMP
Tools options: CFLAGS, LDFLAGS
当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.winelseinclude Makefile.unix #根据编译环境,选择对应的Makefile,真正的入口endif
.config下面将分别介绍上面讲到的文件,核心是围绕Makefile.unix文件。
整个.config文件内容格式如下所示,用来定义配置选项,在编译时需要用到。
...# Build Setup## CONFIG_EXPERIMENTAL is not set# CONFIG_DEFAULT_SMALL is not setCONFIG_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 definedOBJEXT ?= .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 buildifeq ($(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 $2endef# 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 compilerdefine COMPILE @echo "CC: $1" $(Q) $(CC) -c $(CFLAGS) $1 -o $2endef# 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++ compilerdefine COMPILEXX @echo "CXX: $1" $(Q) $(CXX) -c $(CXXFLAGS) $1 -o $2endef# 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+compilerdefine ASSEMBLE @echo "AS: $1" $(Q) $(CC) -c $(AFLAGS) $1 -o $2endef# 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 MOVEOBJendef# 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 buildifeq ($(CONFIG_WINDOWS_NATIVE),y)define ARCHIVE @echo AR: $2 $(Q) $(AR) $1 $(2)endefelsedefine ARCHIVE @echo "AR: $2" $(Q) $(AR) $1 $(2) || { echo "$(AR) $1 FAILED!" ; exit 1 ; }endefendif# 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 buildifeq ($(CONFIG_WINDOWS_NATIVE),y)define PRELINK @echo PRELINK: $1 $(Q) $(LD) -Ur -o $1 $2 && $(OBJCOPY) --localize-hidden $1endefelsedefine PRELINK @echo "PRELINK: $1" $(Q) $(LD) -Ur -o $1 $2 && $(OBJCOPY) --localize-hidden $1endefendif# DELFILE - Delete one fileifeq ($(CONFIG_WINDOWS_NATIVE),y)define DELFILE $(Q) if exist $1 (del /f /q $1)endefelsedefine DELFILE $(Q) rm -f $1endefendif# DELDIR - Delete one directoryifeq ($(CONFIG_WINDOWS_NATIVE),y)define DELDIR $(Q) if exist $1 (rmdir /q /s $1)endefelsedefine DELDIR $(Q) rm -rf $1endefendif# MOVEFILE - Move one fileifeq ($(CONFIG_WINDOWS_NATIVE),y)define MOVEFILE $(Q) if exist $1 (move /Y $1 $2)endefelsedefine MOVEFILE $(Q) mv -f $1 $2endefendif# CLEAN - Default clean targetifeq ($(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)endefelsedefine CLEAN $(Q) rm -f *$(OBJEXT) *$(LIBEXT) *~ .*.swpendefendifMake.defs
Make.defs中定义了一些板级相关的宏定义。
# 包含需要依赖的文件include ${TOPDIR}/.config include ${TOPDIR}/tools/Config.mk include ${TOPDIR}/arch/arm/src/arm/Toolchain.defsifeq ($(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.scriptendif# 定义工具,其中$(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-prologendififneq ($(CONFIG_DEBUG_NOOPT),y) ARCHOPTIMIZATION += $(MAXOPTIMIZATION) -fno-strict-aliasing -fno-strength-reduce -fomit-frame-pointerendififeq ($(ARCHCCMAJOR),4) ARCHCPUFLAGS = -mtune=arm9tdmi -march=armv5te -mfloat-abi=soft -fno-builtinelse ARCHCPUFLAGS = -mapcs-32 -mtune=arm9tdmi -march=armv5te -msoft-float -fno-builtinendifARCHCFLAGS = -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 -nodefaultlibsendififeq ($(CONFIG_DEBUG_SYMBOLS),y) LDFLAGS += -gendif# 定义Host的编译器HOSTCC = gcc HOSTINCLUDES = -I. HOSTCFLAGS = -Wall -Wstrict-prototypes -Wshadow -Wundef -g -pipe HOSTLDFLAGS =Directories.mk
Directories.mk主要定义了NUTTX_ADDONS和USER_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# applicationNUTTX_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)elseifneq ($(CONFIG_BUILD_KERNEL),y) NUTTX_ADDONS += $(APPDIR)endifendif# 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 = libifeq ($(CONFIG_BUILD_PROTECTED),y) USERDIRS += libc mm $(USER_ADDONS)ifeq ($(CONFIG_HAVE_CXX),y) USERDIRS += libxxendifelseifeq ($(CONFIG_BUILD_KERNEL),y) USERDIRS += libc mmifeq ($(CONFIG_HAVE_CXX),y) USERDIRS += libxxendifelseNONFSDIRS += libc mm OTHERDIRS += $(USER_ADDONS)ifeq ($(CONFIG_HAVE_CXX),y) NONFSDIRS += libxxelseOTHERDIRS += libxxendifendifendififeq ($(CONFIG_LIB_SYSCALL),y) NONFSDIRS += syscall CONTEXTDIRS += syscall USERDIRS += syscallelseOTHERDIRS += syscallendififeq ($(CONFIG_LIB_ZONEINFO_ROMFS),y) CONTEXTDIRS += libcendififeq ($(CONFIG_NX),y) NONFSDIRS += graphics libnx CONTEXTDIRS += graphics libnxelseOTHERDIRS += graphics libnxendififeq ($(CONFIG_AUDIO),y) NONFSDIRS += audioelseOTHERDIRS += audioendififeq ($(CONFIG_DRIVERS_WIRELESS),y) NONFSDIRS += wirelesselseOTHERDIRS += wirelessendif# 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 += fsendifKERNDEPDIRS += driversendifelseKERNDEPDIRS += $(FSDIRS)endif# Add networking directories to KERNDEPDIRS and CLEANDIRSifeq ($(CONFIG_NET),y) KERNDEPDIRS += netendifCLEANDIRS += netifeq ($(CONFIG_CRYPTO),y) KERNDEPDIRS += cryptoendifCLEANDIRS += cryptoFlatLibs.mk
内存配置在Flat模式情况下,会使用FlatLibs.mk文件,该文件主要定义NUTTXLIBS和USERLIBS,其中NUTTXLIBS包含了一系列的库文件,最终用于特定处理器来编译Nuttx Image,USERLIBS包含一系列库文件用于用户层的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' isNUTTXLIBS = 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 supportNUTTXLIBS += 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 supportifeq ($(CONFIG_NET),y) NUTTXLIBS += lib$(DELIM)libnet$(LIBEXT)endif# Add libraries for Crypto API supportifeq ($(CONFIG_CRYPTO),y) NUTTXLIBS += lib$(DELIM)libcrypto$(LIBEXT)endif# Add libraries for file system supportifeq ($(CONFIG_NFILE_DESCRIPTORS),0)ifneq ($(CONFIG_NSOCKET_DESCRIPTORS),0) NUTTXLIBS += lib$(DELIM)libfs$(LIBEXT)endifelseNUTTXLIBS += lib$(DELIM)libfs$(LIBEXT) lib$(DELIM)libbinfmt$(LIBEXT)endif# Add libraries for the NX graphics sub-systemifeq ($(CONFIG_NX),y) NUTTXLIBS += lib$(DELIM)libgraphics$(LIBEXT)NUTTXLIBS += lib$(DELIM)libnx$(LIBEXT)endif# Add libraries for the Audio sub-systemifeq ($(CONFIG_AUDIO),y) NUTTXLIBS += lib$(DELIM)libaudio$(LIBEXT)endif# Add libraries for the Wireless sub-systemifeq ($(CONFIG_WIRELESS),y) NUTTXLIBS += lib$(DELIM)libwireless$(LIBEXT)endif# Add C++ libraryifeq ($(CONFIG_HAVE_CXX),y) NUTTXLIBS += lib$(DELIM)libcxx$(LIBEXT)endif# Export all librariesEXPORTLIBS = $(NUTTXLIBS)tools/
Makefile.unixtools目录下包含了各种各样的脚本和Host C程序,这些都是Nuttx编译系统的必要的部分。README.txt有详尽的介绍。
Makefile.unix才是我们的核心,上述所介绍的文件,最终都要为它所用,直接看代码吧。
TOPDIR := ${shell pwd | sed -e 's/ /\\ /g'}-include $(TOPDIR)/.configinclude $(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 scriptsifeq ($(V),1)export Q :=elseifeq ($(V),2)export Q :=elseexport Q := @endifendif# Default tools# 定义符号链接和断开链接的宏ifeq ($(DIRLINK),) DIRLINK = $(TOPDIR)/tools/link.sh DIRUNLINK = $(TOPDIR)/tools/unlink.shendif# 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)/includeifeq ($(CONFIG_ARCH_BOARD_CUSTOM),y)ifeq ($(CONFIG_ARCH_BOARD_CUSTOM_DIR_RELPATH),y) BOARD_DIR = $(TOPDIR)$(DELIM)$(CONFIG_ARCH_BOARD_CUSTOM_DIR)elseBOARD_DIR = $(CONFIG_ARCH_BOARD_CUSTOM_DIR)endifelseBOARD_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 = ../appsendifAPPDIR := ${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' isifeq ($(CONFIG_BUILD_PROTECTED),y)include ProtectedLibs.mkelseifeq ($(CONFIG_BUILD_KERNEL),y)include KernelLibs.mkelseinclude FlatLibs.mkendifendif# 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 += -uelseifeq ($(CONFIG_BUILD_KERNEL),y) MKEXPORT_ARGS += -uendifendififeq ($(V),2) MKEXPORT_ARGS += -dendif# 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 = yelseifeq ($(CONFIG_LIBM),y) NEED_MATH_H = yendifendififeq ($(NEED_MATH_H),y)include/math.h: include/nuttx/lib/math.h $(Q) cp -f include/nuttx/lib/math.h include/math.helseinclude/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.helseinclude/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.helseinclude/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.helse $(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/archinclude/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/boardinclude/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: .configifneq ($(CONFIG_ARCH_CHIP),) @echo "LN: $(ARCH_SRC)/chip to $(ARCH_SRC)/$(CONFIG_ARCH_CHIP)" $(Q) $(DIRLINK) $(TOPDIR)/$(ARCH_SRC)/$(CONFIG_ARCH_CHIP) $(ARCH_SRC)/chipendif# Link arch/<arch-name>/src/<chip-name> to arch/<arch-name>/src/chipinclude/arch/chip: include/archifneq ($(CONFIG_ARCH_CHIP),) @echo "LN: include/arch/chip to $(ARCH_INC)/$(CONFIG_ARCH_CHIP)" $(Q) $(DIRLINK) $(TOPDIR)/$(ARCH_INC)/$(CONFIG_ARCH_CHIP) include/arch/chipendif# 根据依赖关系创建链接,进入nuttx/configs目录中,执行make dirlinks;进入apps/目录中,执行make dirlinksdirlinks: 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,则需要先编译PASS1pass1: pass1depsifeq ($(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}; \ fiifeq ($(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); \ fiendififeq ($(CONFIG_INTELHEX_BINARY),y) @echo "CP: $(NUTTXNAME).hex" $(Q) $(OBJCOPY) $(OBJCOPYARGS) -O ihex $(BIN) $(NUTTXNAME).hexendififeq ($(CONFIG_MOTOROLA_SREC),y) @echo "CP: $(NUTTXNAME).srec" $(Q) $(OBJCOPY) $(OBJCOPYARGS) -O srec $(BIN) $(NUTTXNAME).srecendififeq ($(CONFIG_RAW_BINARY),y) #生成RAW格式文件,并生成nuttx.bin文件 @echo "CP: $(NUTTXNAME).bin" $(Q) $(OBJCOPY) $(OBJCOPYARGS) -O binary $(BIN) $(NUTTXNAME).binendififeq ($(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; \ fiendif# $(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 Kconfigconfig: do_config clean_contextdo_oldconfig: dirlinks apps_preconfig $(Q) APPSDIR=${CONFIG_APPS_DIR} kconfig-conf --oldconfig Kconfigoldconfig: do_oldconfig clean_contextdo_olddefconfig: dirlinks apps_preconfig $(Q) APPSDIR=${CONFIG_APPS_DIR} kconfig-conf --olddefconfig Kconfigolddefconfig: do_olddefconfig clean_contextdo_menuconfig: dirlinks apps_preconfig $(Q) APPSDIR=${CONFIG_APPS_DIR} kconfig-mconf Kconfigmenuconfig: do_menuconfig clean_contextdo_qconfig: dirlinks apps_preconfig $(Q) APPSDIR=${CONFIG_APPS_DIR} kconfig-qconf Kconfigqconfig: do_qconfig clean_contextdo_gconfig: dirlinks apps_preconfig $(Q) APPSDIR=${CONFIG_APPS_DIR} kconfig-gconf Kconfiggconfig: 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 pass2depsubdir_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)" cleanifeq ($(CONFIG_BUILD_2PASS),y) $(Q) $(MAKE) -C $(CONFIG_PASS1_BUILDIR) TOPDIR="$(TOPDIR)" cleanendif# 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_contextifeq ($(CONFIG_BUILD_2PASS),y) $(Q) $(MAKE) -C $(CONFIG_PASS1_BUILDIR) TOPDIR="$(TOPDIR)" distcleanendif $(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)" preconfigendifapps_clean:ifneq ($(APPDIR),) $(Q) $(MAKE) -C "$(TOPDIR)/$(APPDIR)" TOPDIR="$(TOPDIR)" cleanendifapps_distclean:ifneq ($(APPDIR),) $(Q) $(MAKE) -C "$(TOPDIR)/$(APPDIR)" TOPDIR="$(TOPDIR)" distcleanendif
顶层目录中的Makefile,通过make -C逐层进入子目录中,执行相应的编译动作,最终找到所有的依赖关系,生成nuttx及nuttx.bin文件。
apps目录中的编译方式也类似,从apps/Makefile开始分析即可。
作者:Loyen