NuttX編譯系統

來源:互聯網
上載者:User

NuttX 編譯系統1 簡介NuttX 是通過 Makefile 檔案組織編譯的。Makefile 檔案描述了整個 NuttX 工程的編譯、連結等規則,告訴 make 要編譯哪些檔案、怎樣編譯以及在什麼條件下編譯。NuttX 沒有使用 Autoconf、 Automake、 CMake、 SCons 等自動化編譯工具,它的 Makefile 檔案完全由手工編寫,比那些自動化編譯工具所使用的編譯檔案更容易閱讀,更容易理解軟體的編譯過程。正應了那句話:試圖用一種方法使事情變得簡單,結果卻使事情變得更複雜。2 Makefile 檔案組織圖nuttx/Makefile: 頂層 Makefile 檔案,內容很簡單,根據主機環境,條件包含 Makefile.unix 或 Makefile.win。nuttx/Makefile.unix:Linux 環境下的 Makefile 檔案。nuttx/Makefile.win:Windows 環境下的 Makefile 檔案。nuttx/Make.defs:從 nuttx/config/<板卡>/<目標配置>/Make.defs 複製而來。各級子目錄下的 Makefile、 Make.defs 和 Make.dep。3 Makefile 檔案包含樹(頂層目錄是 nuttx)

`        |<--.config         |         |                 |<--.config         |                 |<--tools/Config.mk         |<--Makefile.unix-|Makefile-|                 |             |<--.config         |                 |<--Make.defs-|<--tools/Config.mk         |                               |<--arch/arm/src/armv7-m/Toolchain.defs         |         |<--Makefile.win-(略)
可以看出,《nuttx 配置系統》中所產生的 .config 檔案被包含在 Makefile 檔案中。

各級子目錄下的 Makefile、 Make.defs 和 Make.dep 並不是通過 include 包含的,而是在執行 Makefile 檔案中的 make 命令時調用的。4 構建目標和選項4.1 構建目標:以下是在頂層 Makefile 檔案中可用的構建目標的概述:

all
預設目標,按已選擇的輸出格式構建 NuttX 可執行檔。

clean
移除派生對象檔案、靜態庫檔案、可執行檔和臨時檔案,但保留配置和內容相關的檔案和目錄。還保留 Make.dep 檔案。

distclean
除了完成 “clean” 的工作之外,還包括移除所有配置和內容相關的檔案。本質是將目錄結構還原為其原始的、未配置的狀態。4.2 應用程式內務處理目標APPDIR 變數引用使用者應用程式目錄。如 NuttX 包含的 app/ 目錄,然而,這不被看作是 NuttX 的一部分,可以被一個不同的應用程式目錄替代。在大多數情況下,應用程式目錄在 Makefile 指令碼中被看作像任何其它構建目錄。但是,為方便起見,包含了以下目標,以支援從 NuttX 構建目錄處理使用者應用程式目錄中的內務處理功能。

apps_clean
僅對使用者應用程式目錄執行 clean 操作。

apps_distclean
僅對使用者應用程式目錄執行 distclean 操作。 apps/.config 檔案被保留,所以這不是一個完全的 distclean,但多於配置複位。

export
export 目標將打包 NuttX 庫和標頭檔到可輸出包。注意事項:(1) 需要對 KERNEL 構建做一些擴充。 (2) tools/mkexport.sh 中的邏輯只支援 GCC,例如,顯式地假定靜態庫產生器為“ar”。

download
這是一個助手目標,它將重建 NuttX 並將其下載到目標系統,只需一步。此目標的操作完全依賴於使用者 Make.defs 檔案中的 DOWNLOAD 命令的實現。如果未定義 DOWNLOAD 命令,它將產生一個錯誤。4.3 內部目標以下目標是由 make 邏輯內部使用的,但如果有必要,可以在某些條件下從命令列調用。

depend
建立構建依賴關係,產生 Make.dep 檔案和 .depend 檔案。(注意:當前在使用 Windows 本地工具鏈的 Cygwin 下不支援構建依賴關係)

context
在每次目標構建時調用 context 目標以確保正確配置了 NuttX。基本配置步驟包括在 include/nuttx 目錄中建立 config.h 和 version.h 標頭檔,建立連結到配置目錄的符號連結。

clean_context
這是 distclean 目標的一部分。它移除由 context 目標建立的所有標頭檔和符號連結。4.4 構建選項當然,任何 make 變數的值都可以從命令列覆蓋。然而,有一個特殊的變數賦值選項可能對你非常有用:

V=1

這是產生詳細資訊層級標誌。如果你在命令列上指定 V=1,你將在構建時看到所使用的確切命令。當添加新的板卡或追蹤編譯時間錯誤和警告時可能非常有用。5 all 目標依賴樹
`                          |<--pass1dep-|<----------------------------------------╮             |<--pass1deps-|            |<--tools/mkdeps$(HOSTEXEEXT)             |             |     |       |                                                      |             |  ╭--╯       |<--$(USERLIBS)(平面構建時為空白)                          |             |  |                                                                 |             |  |           |<--pass2dep-|<---------------------------------------|             |<---pass2deps-|            |<--tools/mkdeps$(HOSTEXEEXT)            |             |  |  |        |                                                     |             |  |  |        |<--$(NUTTXLIBS)(與配置有關)<--╮                       |             |  |  |                                      |                       |             |  |  |  ╭-----------------------------------╯                       |             |  |  |  |                                                           |             |  |  |  |<--lib/libsched$(LIBEXT)<--sched/libsched$(LIBEXT)<--------|             |  |  |  |<--lib/libc$(LIBEXT)<--libc/libc$(LIBEXT)<-----------------|             |  |  |  |<--lib/libmm$(LIBEXT)<--mm/libmm$(LIBEXT)<-----------------|all<--$(BIN)-|  |  |  |<--lib/libarch$(LIBEXT)<--$(ARCH_SRC)/libarch$(LIBEXT)<----|             |  |  |  |<--lib/libcxx$(LIBEXT)<--libxx/libcxx$(LIBEXT)<------------|             |  |  |  |<--lib/libapps$(LIBEXT)<--$(APPDIR)/libapps$(LIBEXT)<------|             |  |  |  |<--lib/libnet$(LIBEXT)<--net/libnet$(LIBEXT)<--------------|             |  |  |  |<--lib/libfs$(LIBEXT)<--fs/libfs$(LIBEXT)<-----------------|             |  |  |  |<--lib/libdrivers$(LIBEXT)<--drivers/libdrivers$(LIBEXT)<--|             |  |  |  |<--lib/libbinfmt$(LIBEXT)<--binfmt/libbinfmt$(LIBEXT)<-----|             |  |  |                                                              |             |  |  ╰---------╮                                                    |             |  |            |                                                    |             |  ╰--------╮   |                                                    |             |           |   |                                                    |             |<--pass1<--╯   |                                                    |             |               |                                                    |             |<--pass2<------╯                                                    |                                                                                  |      ╭---------------------------------------------------------------------------╯      |      |           |<--check_context      |           |      |           |<--include/nuttx/config.h-|<--$(TOPDIR)/.config      |           |                          |<--tools/mkconfig$(HOSTEXEEXT)      |           |      |           |<--include/nuttx/version.h-|<--$(TOPDIR)/.version      |           |                           |<--tools/mkversion$(HOSTEXEEXT)      |           |      |<--context-|<--include/math.h<--include/nuttx/math.h                  |<--include/float.h<--include/nuttx/float.h                  |<--include/stdarg.h<--include/nuttx/stdarg.h                  |                  |            |<--include/arch<-Make.defs                  |            |                  |            |<--include/arch/board-|<--include/arch<--Make.defs                  |            |                      |<--Make.defs                  |            |                  |<--dirlinks-|<--include/arch/chip-|<--include/arch<--Make.defs                               |                     |<--Make.defs                               |                               |<--$(ARCH_SRC)/board<--Make.defs                               |<--$(ARCH_SRC)/chip<--Make.defs                               |<--include/apps<--Make.defs
6 all 目標編譯過程6.1 context 目標因為 all 目標是預設目標,所以執行無參數的 make 命令即為編譯 all 目標,首先會嘗試編譯 context 目標,其中,根據 .config 檔案產生 config.h,有許多 C 檔案包含了 config.h,以獲得使用者配置。注意其中的2個目錄軟連結,下文會用到:

$(ARCH_SRC)/board:
將 nuttx/configs/shenzhou/src 目錄連結到 nuttx/arch/arm/src/board 目錄。

$(ARCH_SRC)/chip:
將 nuttx/arch/arm/src/stm32 目錄連結到 nuttx/arch/arm/src/chip 目錄。

但是因為在安裝 buildroot 時已經執行過一次 make context,而且執行 make clean 也不會刪除 context 目標所產生的檔案,所以這一步沒做任何事。6.2 pass1dep 目標
pass1dep: context tools/mkdeps$(HOSTEXEEXT)        $(Q) for dir in $(USERDEPDIRS) ; do \                $(MAKE) -C $$dir TOPDIR="$(TOPDIR)" depend ; \        done
平面構建是指將 NuttX 編譯成單個二進位檔案,構建的所有組件位於相同的地址空間,所有組件都可以訪問所有其它組件。平面構建時 $(USERDEPDIRS) 為空白,它也沒做任何事。6.3 $(USERLIBS) 目標平面構建時 $(USERLIBS) 為空白,它也沒做任何事。這樣整個 pass1deps 目標就完成了。6.4 pass2dep 目標
pass2dep: context tools/mkdeps$(HOSTEXEEXT)        $(Q) for dir in $(KERNDEPDIRS) ; do \                $(MAKE) -C $$dir TOPDIR="$(TOPDIR)" EXTRADEFINES=$(KDEFINE) depend; \        done
根據 $(KERNDEPDIRS) 變數的值,在各級子目錄下產生 Make.dep 和 .depend檔案。

nuttx 目錄下產生 Make.dep 和 .depend 檔案的子目錄有:
nuttx/arch/arm/srcnuttx/binfmtnuttx/configs/shenzhou/srcnuttx/driversnuttx/fsnuttx/libcnuttx/libxxnuttx/mmnuttx/netnuttx/sched6.5 $(NUTTXLIBS) 目標接下來就編譯 pass2deps 目標中的 $(NUTTXLIBS),這是一個多目標,根據配置的不同,具體的目標也不同。它的工作是產生多個靜態庫檔案。這裡產生了10個靜態庫檔案:
nuttx/lib/libapps.anuttx/lib/libarch.anuttx/lib/libbinfmt.anuttx/lib/libc.anuttx/lib/libcxx.anuttx/lib/libdrivers.anuttx/lib/libfs.anuttx/lib/libmm.anuttx/lib/libnet.anuttx/lib/libsched.a 下面以 libarch.a 為例,考查靜態庫的編譯過程。
$(ARCH_SRC)/libarch$(LIBEXT): context        $(Q) $(MAKE) -C $(ARCH_SRC) TOPDIR="$(TOPDIR)" libarch$(LIBEXT)
其中: $(ARCH_SRC) = nuttx/arch/arm/src,$(LIBEXT) = .a。傳遞的不是變數名,而是變數中的值。第2行的意思是先切換到目錄 nuttx/arch/arm/src,再執行 make 命令,傳遞參數 TOPDIR,編譯目標 libarch.a,這裡的 make 調用的是目錄 nuttx/arch/arm/src 中的 Makefile,編譯的是該 Makefile 中的目標。在 nuttx/arch/arm/src/Makefile 中先定義 BIN = libarch$(LIBEXT),然後:
$(BIN) $(KBIN): $(OBJS)        $(call ARCHIVE, $@, $(OBJS))
其中:OBJS = $(AOBJS) $(COBJS),而
AOBJS = $(ASRCS:.S=$(OBJEXT))
ASRCS = $(CHIP_ASRCS) $(CMN_ASRCS)

COBJS = $(CSRCS:.c=$(OBJEXT))
CSRCS = $(CHIP_CSRCS) $(CMN_CSRCS)

nuttx/arch/arm/src/Makefile 包含了 nuttx/arch/arm/src/chip/Make.defs,4個變數 CHIP_ASRCS、 CMN_ASRCS、 CHIP_CSRCS、 CMN_CSRCS 都是在 nuttx/arch/arm/src/chip/Make.defs 中定義的,多次賦值後的變數值如下:

CHIP_ASRCS = (空)

CMN_ASRCS = up_saveusercontext.S up_fullcontextrestore.S up_switchcontext.S vfork.S

CHIP_CSRCS = stm32_allocateheap.c stm32_start.c stm32_rcc.c stm32_lse.c stm32_lsi.c stm32_gpio.c stm32_exti_gpio.c stm32_flash.c stm32_irq.c stm32_timerisr.c stm32_dma.c stm32_lowputc.c stm32_serial.c stm32_spi.c stm32_sdio.c stm32_tim.c stm32_waste.c stm32_ccm.c stm32_i2c.c stm32_idle.c stm32_pmstop.c stm32_pmstandby.c stm32_pmsleep.c stm32_pminitialize.c stm32_eth.c stm32_pwr.c stm32_rtc.c

CMN_CSRCS = up_assert.c up_blocktask.c up_copyfullstate.c up_createstack.c up_mdelay.c up_udelay.c up_exit.c up_initialize.c up_initialstate.c up_interruptcontext.c up_memfault.c up_modifyreg8.c up_modifyreg16.c up_modifyreg32.c up_releasepending.c up_releasestack.c up_reprioritizertr.c up_schedulesigaction.c up_sigdeliver.c up_systemreset.c up_unblocktask.c up_usestack.c up_doirq.c up_hardfault.c up_svcall.c up_vfork.c

從這裡可以查到哪些源檔案被編譯,哪些源檔案沒有被編譯。

命令 $(call ARCHIVE, $@, $(OBJS)) 打包靜態庫 libarch.a。

現在回到nuttx/Makefile.unix:
lib/libarch$(LIBEXT): $(ARCH_SRC)/libarch$(LIBEXT)        $(Q) install $(ARCH_SRC)/libarch$(LIBEXT) lib/libarch$(LIBEXT)
其中: install 是 Linux 命令,這裡等同於複製,將 libarch.a 複製到 nuttx/lib 目錄。6.6 pass1 目標
pass1: 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
平面構建時不做任何事。6.7 pass2 目標最後編譯pass2
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: $(BIN).rr"        $(Q) $(TOPDIR)/tools/mkimage.sh --Prefix $(CROSSDEV) $(BIN) $(BIN).rr        $(Q) if [ -w /tftpboot ] ; then \                cp -f $(BIN).rr /tftpboot/$(BIN).rr.$(CONFIG_ARCH); \        fiendififeq ($(CONFIG_INTELHEX_BINARY),y)        @echo "CP: $(BIN).hex"        $(Q) $(OBJCOPY) $(OBJCOPYARGS) -O ihex $(BIN) $(BIN).hexendififeq ($(CONFIG_MOTOROLA_SREC),y)        @echo "CP: $(BIN).srec"        $(Q) $(OBJCOPY) $(OBJCOPYARGS) -O srec $(BIN) $(BIN).srecendififeq ($(CONFIG_RAW_BINARY),y)        @echo "CP: $(BIN).bin"        $(Q) $(OBJCOPY) $(OBJCOPYARGS) -O binary $(BIN) $(BIN).binendif        @echo "DUMP: $(BIN).out"        $(Q) $(OBJDUMP) -x $(BIN) > $(HOME)/$(BIN).out        @echo "DUMP: $(BIN).S"        $(Q) $(OBJDUMP) -d -j .text -j .init_section -j .ARM.exidx -j .data -j .bss $(BIN) > $(HOME)/$(BIN).S        cp -f $(BIN) $(BIN).hex $(BIN).bin $(HOME)
把靜態庫連結成 elf 格式的可執行檔,並轉換成 .hex、 .bin 等其它格式的檔案。最後5行是我加上去的,產生符號檔案、反組譯碼檔案,並把一些最終檔案複製到 Linux 使用者主目錄。由《NuttX 安裝指令碼》中的以下幾行實現:
if !(grep -q '    @echo "DUMP: $(BIN).out"' Makefile.unix); then  sed -i '/pass2:/,/^$/{    /^$/i\    @echo "DUMP: $(BIN).out"    /^$/i\    $(Q) $(OBJDUMP) -x $(BIN) > $(HOME)/$(BIN).out    /^$/i\    @echo "DUMP: $(BIN).S"    /^$/i\    $(Q) $(OBJDUMP) -d -j .text -j .init_section -j .ARM.exidx -j .data -j .bss $(BIN) > $(HOME)/$(BIN).S    /^$/i\    cp -f $(BIN) $(BIN).hex $(BIN).bin $(HOME)  }' Makefile.unixfi
7 nuttx/Make.defs 檔案nuttx/Make.defs 檔案是 Makefile 片斷,從 nuttx/config/<板卡>/<目標配置>/Make.defs 複製而來。由《NuttX 安裝指令碼》中的以下幾行實現:
echo "nuttx配置"cd $BASEDIR/$TOPDIR/nuttx/tools./configure.sh $TARGETCONFIG
該 Makefile 片斷提供架構和工具特定的構建選項。它將在構建時被所有其它 Makefile 檔案包含(一旦它被安裝)。該 makefile 片斷應定義:
工具: CC、 LD、 AR、 NM、 OBJCOPY、 OBJDUMP 工具選項: CFLAGS、 LDFLAGS 當該 Makefile 片斷運行時,它將被傳遞構建根目錄的路徑 TOPDIR。該 Makefile 片斷應包含:

$(TOPDIR)/.config: Nuttx 配置
$(TOPDIR)/tools/Config.mk: 一般定義

nuttx/Make.defs 檔案中的定義可能依賴於 .config 檔案中的一些設定。例如,如果 CONFIG_DEBUG=y, CFLAGS將最有可能不同。

tools/Config.mk 檔案包含額外的定義,這些定義可能在必要時被架構特定的 Make.defs 檔案覆蓋:
COMPILE、 ASSEMBLE、 ARCHIVE、 CLEAN 和 MKDEP 宏

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.