Nuttx編譯系統
配置
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.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 orcharacters 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 orcharacters 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_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 #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
檔案,該檔案主要定義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' 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逐層進入子目錄中,執行相應的編譯動作,最終找到所有的依賴關係,生成nuttx
及nuttx.bin
檔案。
apps目錄中的編譯方式也類似,從apps/Makefile開始分析即可。