1. 程式人生 > 實用技巧 >ESP32構建系統 (傳統 GNU Make)

ESP32構建系統 (傳統 GNU Make)

概述:

一個 ESP-IDF 專案可以看作是多個不同元件的集合,ESP-IDF 可以顯式地指定和配置每個元件。在構建專案的時候,構建系統會前往 ESP-IDF 目錄、專案目錄和使用者自定義目錄(可選)中查詢所有元件,允許使用者通過文字菜單系統配置 ESP-IDF 專案中用到的每個元件。在所有元件配置結束後,構建系統開始編譯整個專案。

概念:

專案:  特指一個目錄,其中包含了構建可執行應用程式所需的全部檔案和配置,以及其他支援型檔案,例如分割槽表、資料/檔案系統分割槽和載入程式。
專案配置:儲存在專案根目錄下名為 sdkconfig 的檔案中,可以通過 idf.py menuconfig 進行修改,且一個專案只能包含一個專案配置。
應用程式:是由 ESP-IDF 構建得到的可執行檔案。一個專案通常會構建兩個應用程式:專案應用程式(可執行的主檔案,即使用者自定義的韌體)和載入程式(啟動並初始化專案應用程式)。
元件:  是模組化且獨立的程式碼,會被編譯成靜態庫(.a 檔案)並連結到應用程式。部分元件由 ESP-IDF 官方提供,其他元件則來源於其它開源專案。
目標:  特指執行構建後應用程式的硬體裝置。ESP-IDF 當前僅支援 ESP32 這一個硬體目標。


示例專案

 1 - myProject/
 2       - Makefile                        //設定了 PROJECT_NAME 變數,還可以定義作用於整個專案的其它 make 變數(可選)。
 3       - sdkconfig                       //配置檔案
 4       - components/                     //可選元件目錄
 5               - component1/ 
 6                       - component.mk    //元件的makefile檔案
 7
- Kconfig 8 - src1.c 9 - component2/ 10 - component.mk 11 - Kconfig 12 - src1.c 13 - include/ - component2.h 14 - main/ //特殊元件,包含專案原始碼。
15 - src1.c 16 - src2.c 17 - component.mk 18 - build/ //編譯輸出目錄

元件目錄中會包含元件自己的 Makefile 檔案 component.mk ,裡面會定義一些變數來控制該元件的構建過程,以及它與整個專案的整合。

專案 Makefiles

每個專案都有一個 Makefile ,它包含整個專案的構建設定。預設情況下,專案 Makefile 可以非常小。

PROJECT_NAME := myProject //專案名稱
include $(IDF_PATH)/make/project.mk // 頂層專案目錄,預設是包含 Makefile 檔案的目錄,許多其他的專案變數都基於此變數。

以下這些可選變數都有預設值,使用者可以重寫這些變數以自定義構建行為。

  • BUILD_DIR_BASE: 所有物件、庫、二進位制檔案的輸出目錄,預設為 $(PROJECT_PATH)/build。
  • COMPONENT_DIRS: 元件的搜尋目錄,預設為 $(IDF_PATH)/components,$(PROJECT_PATH)/components,$(PROJECT_PATH)/main 和 EXTRA_COMPONENT_DIRS 。
  • EXTRA_COMPONENT_DIRS: 元件額外的搜尋路徑,可選。
  • COMPONENTS: 要構建進專案中的元件列表,預設為 COMPONENT_DIRS 指定目錄中所有的元件。
  • EXCLUDE_COMPONENTS: 在構建的過程中需要剔除的元件列表,可選。請注意這隻會減少構建的時間,並不會減少最終二進位制檔案的大小。

元件Makefiles

每個專案都包含一個或者多個元件,這些元件可以是 ESP-IDF 的一部分,也可以從其他元件目錄新增。元件是包含 component.mk 檔案的任何目錄。
搜尋 COMPONENT_DIRS 中指定的目錄以查詢專案會使用的元件,目錄可以是元件本身(即他們包含 component.mk 檔案),也可以是包含元件的上層目錄。
ESP-IDF 搜尋元件時,會按照 COMPONENT_DIRS 指定的順序依次進行,這意味著在預設情況下,首先是 ESP-IDF 元件,然後是專案元件,最後是 EXTRA_COMPONENT_DIRS 中的元件。如果這些目錄中的兩個或者多個包含具有相同名字的元件,則使用搜索到的最後一個位置的元件。這就允許將元件複製到專案目錄中再修改來覆蓋 ESP-IDF 元件。


最簡單的 component.mk 檔案可以是一個空檔案,如果檔案為空,則元件的預設構建行為會被設定為:

  • makefile 所在目錄中的所有原始檔(*.c,*.cpp,*.cc,*.S)將會被編譯進元件庫中。
  • 子目錄 include 將被新增到其他元件的全域性標頭檔案搜尋路徑中。
  • 元件庫將會被連結到專案的應用程式中。

空的 component.mk 檔案同沒有 component.mk 檔案之間存在本質差異,前者會呼叫預設的元件構建行為,後者不會發生預設的元件構建行為。


元件變數:

  • COMPONENT_PATH: 元件的目錄,即包含 component.mk 檔案的絕對路徑
  • COMPONENT_NAME: 元件的名字,預設為元件目錄的名稱。
  • COMPONENT_BUILD_DIR: 元件的構建目錄,即存放元件構建輸出的絕對路徑,它是 $(BUILD_DIR_BASE) 的子目錄。
  • COMPONENT_LIBRARY: 元件構建後的靜態庫檔案(相對於元件的構建目錄)的名字,預設為 $(COMPONENT_NAME).a。
  • COMPONENT_ADD_INCLUDEDIRS: 相對於元件目錄的路徑,將被新增到專案中所有元件的標頭檔案搜尋路徑中。
  • COMPONENT_ADD_LDFLAGS: 新增連結引數到全域性 LDFLAGS 中用以指導連結最終的可執行檔案,預設為 -l$(COMPONENT_NAME)。
  • COMPONENT_DEPENDS: 需要在當前元件之前構建的元件列表,這對於處理連結時的依賴不是必需的,因為所有元件的標頭檔案目錄始終可用。
  • COMPONENT_ADD_LINKER_DEPS: 儲存一些檔案的路徑,當這些檔案發生改變時,會觸發 ELF 檔案重新連結。
  • COMPONENT_SUBMODULES: 元件使用的 git 子模組的路徑列表(相對於 COMPONENT_PATH)。這些路徑會在構建的過程中被檢查(並在必要的時候初始化)。
  • COMPONENT_PRIV_INCLUDEDIRS: 相對於元件目錄的目錄路徑,該目錄僅會被新增到該元件原始檔的標頭檔案搜尋路徑中。
  • COMPONENT_EXTRA_INCLUDES: 編譯元件的原始檔時需要指定的額外的標頭檔案搜尋路徑,這些路徑將以 -l 為字首傳遞給編譯器。
  • COMPONENT_SRCDIRS: 相對於元件目錄的目錄路徑,這些路徑用於搜尋原始檔(*.cpp,*.c,*.S),預設為 .,即元件目錄本身。
  • COMPONENT_OBJS: 要編譯生成的目標檔案,預設是 COMPONENT_SRCDIRS 中每個原始檔的 .o 檔案。
  • COMPONENT_EXTRA_CLEAN: 相對於元件構建目錄的路徑,指向 component.mk 檔案中自定義 make 規則生成的任何檔案,它們也是 make clean 命令需要刪除的檔案。
  • COMPONENT_OWNBUILDTARGET & COMPONENT_OWNCLEANTARGET: 這些目標允許您完全覆蓋元件的預設編譯行為。
  • COMPONENT_CONFIG_ONLY: 如果設定了此標誌,則表示元件根本不會產生構建輸出(即不會構建得到 COMPONENT_LIBRARY),並且會忽略大多數其它元件變數。
  • CFLAGS: 傳遞給 C 編譯器的標誌。根據專案設定已經定義一組預設的 CFLAGS,可以通過 CFLAGS += 來為元件新增特定的標誌,也可以完全重寫該變數(儘管不推薦這麼做)。
  • CPPFLAGS: 傳遞給 C 前處理器的標誌(用於 .c,.cpp 和 .S 檔案)。
  • CXXFLAGS: 傳遞給 C++ 編譯器的標誌。

配置元件

每個元件都可以包含一個 Kconfig 檔案,和 component.mk 放在同一個目錄下。Kconfig 中包含此元件在 make menuconfig 時要展示的配置規則的設定。執行 menuconfig 時,可以在 Component Settings 選單欄下找到這些設定。

參考:https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-guides/build-system-legacy.html