【Buildroot】工具包使用

2023-12-13 18:00:39

一、測試環境

  • 開發板:rv1126

  • buildroot版本:2018.02-rc3

二、.mk規則

  • PKG_NAME:定義軟體包的名稱。通常與軟體包原始碼的目錄名相同。

  • PKG_VERSION:定義軟體包的版本號。

  • PKG_SOURCE:定義軟體包原始碼的下載連結或路徑。可以是遠端 URL 或本地路徑。

  • PKG_HASH:定義軟體包原始碼的雜湊值,用於驗證下載檔案的完整性。通常使用 MD5 或 SHA256 演演算法計算。

  • PKG_LICENSE:定義軟體包的許可證型別。可以是單個許可證或多個許可證的組合。

  • PKG_BUILD_DIR:定義軟體包構建過程中的臨時目錄。通常是 ${BUILD_DIR}/${PKG_NAME}-${PKG_VERSION}。

  • PKG_INSTALL_DIR:定義軟體包安裝到目標系統的目錄。通常是 ${TARGET_DIR}。

  • PKG_CONFIG_DEPENDS:定義軟體包構建過程中依賴的其他軟體包。這些依賴將被自動解析和構建。

  • PKG_BUILD_CMDS結尾的變數會在 buildroot 框架編譯的時候執行,用於給原始碼的 Makefile 傳遞編譯選項和連結選項,呼叫原始碼的Makefile。

  • PKG_INSTALL_TARGET_CMDS結尾的變數是在編譯完之後,自動安裝執行,一般是讓 buildroot 把編譯出來的的 bin 或 lib 拷貝到指定目錄。

  • $(eval $(autotools-package)):使用 Autotools 構建系統的軟體包規則。適用於使用 configure 指令碼的軟體包。

  • $(eval $(cmake-package)):使用 CMake 構建系統的軟體包規則。適用於使用 CMakeLists.txt 的軟體包。

  • $(eval $(generic-package)):通用的軟體包規則,適用於沒有特定構建系統的軟體包。需要手動定義構建和安裝過程。

  • $(eval $(host-generic-package)):適用於主機(開發機)上構建的通用軟體包規則。與目標系統無關。

  • $(eval $(python-package)):適用於 Python 軟體包的規則。用於構建和安裝 Python 模組。

三、建立自定義軟體包

對 buildroot 目錄還不熟的小夥伴可以看我之前的筆記【Buildroot】使用記錄

3.1 Makefile

  1. 建立 Buildroot 專案
    在 SDK/app 目錄下建立 app_demo 檔案,並在檔案中建立 test.c 和 Makefile 檔案,內容如下

    檔案目錄

    app_demo
    ├── test.c
    └── Makefile 
    

    Makefile 檔案

    OPT = -O2
    DEBUG = -g
    OTHER = -Wall -Wno-deprecated
    CFLAGS = $(OPT) $(OTHER)
    INCDIR = -I
    LIBDIR = -L
    LIBS =
    APP=app_demo
    SRCS=test.c
    
    
    .PHONY: all
    all:
    	$(CC) -o $(APP) $(SRCS) $(CFLAGS) $(LIBDIR) $(INCDIR) $(LIBS)
    
    .PHONY: clean
    clean:
    	rm -f *.o *~ $(APP)
    
    .PHONY: install
    install:
    	cp -f $(APP) $(TARGET_DIR)/../oem
    
    .PHONY: uninstall
    uninstall:
    	rm -f $(TARGET_DIR)/../oem/$(APP)
    

    test.c 檔案

    #include <stdio.h>
    
    int main()
    {
    	printf("buildroot helloworld\n");
    	return 0;
    }
    
  2. APP 的版本和編譯規則
    在 Buildroot/package 目錄下建立 app_demo 目錄,並在目錄中建立 app_demo.mk 和 Config.in 檔案,內容如下

    檔案目錄

    app_demo
    ├── app_demo.mk
    └── Config.in
    

    app_demo.mk 檔案

    ##################################################
    #
    # app_demo.mk
    #
    ##################################################
    
    ifeq ($(BR2_PACKAGE_APP_DEMO), y)
    
    	APP_DEMO_VERSION:=1.0.0
    	APP_DEMO_SITE=$(TOPDIR)/../app/app_demo
    	APP_DEMO_SITE_METHOD=local
    	#APP_INSTALL_TARGET:=YES
    
    define APP_DEMO_BUILD_CMDS
    	$(TARGET_MAKE_ENV) $(MAKE) CC=$(TARGET_CC) CXX=$(TARGET_CXX) -C $(@D)
    endef
    
    define APP_DEMO_CLEAN_CMDS
    	$(TARGET_MAKE_ENV) $(MAKE) -C $(@D) clean
    endef
    
    define APP_DEMO_INSTALL_TARGET_CMDS
    	$(TARGET_MAKE_ENV) $(MAKE) -C $(@D) install
    endef
    
    define APP_DEMO_UNINSTALL_TARGET_CMDS
    	$(TARGET_MAKE_ENV) $(MAKE) -C $(@D) uninstall
    endef
    
    $(eval $(generic-package))
    endif
    

    Config.in 檔案

    config BR2_PACKAGE_APP_DEMO
    bool "app_demo"
    help
    	This is a demo to add app_demo.
    
  3. 加到 menuconfig 設定中
    開啟「buildroot/package/Config.in」檔案。跳轉到最後一個「endmenu」下新增如下範例程式碼(注意:必須在此檔案的最後一個 endmenu 前新增)。程式碼如下所示:

    menu "app_demo"
    	source "package/app_demo/Config.in"
    endmenu
    

  4. 在 menuconfig 開啟專案
    這裡需要注意的是,需要編譯專案時,在 menuconfig 中設定完成後,需要使用命令 make savedefconfig 儲存設定。開啟專案如下圖所示:

  5. 編譯專案
    每次編譯完成後都會在 output/build 目錄下生成對應的包

    # 編譯專案
    make app_demo
    
    # 清除專案
    make app_demo-dirclean
    

3.2 cmake

不論是使用 make 構建還是使用 cmake 構建,所操作的流程都是一樣的,只是編譯規則有一點區別,所以這裡就不描述具體的流程了,只將不同的檔案貼上即可,其他流程是一樣的

  1. 在 SDK/app/app_demo 檔案中建立 CMakeLists.txt 檔案,內容如下

    cmake_minimum_required(VERSION 3.1.0)
    set(CMAKE_CXX_STANDARD 11)
    
    project(app_demo1)
    
    set(SOURCES test.c)
    
    add_executable(${PROJECT_NAME} ${SOURCES})
    
    install(TARGETS ${PROJECT_NAME} DESTINATION ../../oem)
    

    注意:install 預設安裝的位置是 $(TARGET_DIR)/usr 目錄下

  2. 將 Buildroot/package/app_demo 目錄下的 app_demo.mk 檔案內容更改成以下內容

    ##################################################
    #
    # app_demo.mk
    #
    ##################################################
    
    ifeq ($(BR2_PACKAGE_APP_DEMO), y)
    
        APP_DEMO_VERSION:=1.0.0
        APP_DEMO_SITE=$(TOPDIR)/../app/app_demo
        APP_DEMO_SITE_METHOD=local
        #UVC_APP_DEPENDENCIES = libdrm mpp
    
    $(eval $(cmake-package))
    endif
    
  3. 編譯結果如下所示

四、修改軟體版本

完成上面操作後,應給會發現,軟體包不只是自定義的,也有從線上下載的。有時候需要更改線上包的版本,情況稍微有一點不一樣,所以這裡記錄了一下。

可能會有小夥伴和我做同樣的嘗試,上一篇筆記中有提到軟體包下載的目錄在 Buildroot/dl 下,所以就將需要的版本軟體下載到 dl 目錄下,便會發現這樣的操作是不可行的,需要更改一下組態檔,這裡以 iperf3 為例,流程如下:

  1. 進入 buildroot/package/iperf3/ 目錄,如下圖所示

  2. 重要檔案
    圖中的檔案中,有三個比較重要的檔案,分別是:

    • Config.in 相當於核心的 Kconfig;
    • iperf3.hash 軟體包的校驗碼;
    • iperf3.mk 相對於核心的 Makefile;
  3. 修改軟體版本
    開啟 iperf3.mk 檔案,可以看到包的下載地址和版本號(有時候下載地址在 Config.in 裡),進入下載網站後,可以找到自己需要的版本,然後修改檔案,如下圖所示:

  4. 下載測試
    使用命令 make iperf3-source 可以進行下載,如下圖所示

  5. 生成原始碼的 hash 值

    sha256sum buildroot/dl/iperf-3.9.tar.gz
    

  6. 修改 iperf3.hash 檔案

    注意:因為 3.9 版本沒有修補程式檔案的,所以將對應的修補程式檔案刪除即可

五、開機自啟

開機時啟動自己的應用程式有兩種辦法,一種是進入檔案系統後,在 /etc/init.d/ 目錄新增自己的啟動指令碼;另一種將指令碼放在 buildroot 中,在編譯的時候,自動放在 /etc/init.d/ 目錄下。

由於在 /etc/init.d/ 目錄下建立指令碼的方式比較簡單,這裡就不介紹了,主要分析方式二,將啟動指令碼放在 buildroot 中進行替換。

在操作之前,先來科普一些東西,在 buildroot 編譯完成後,有一個最終確定目標的過程,在設定選項中預留了幾個介面,如下:

  • BR2_ROOTFS_OVERLAY:指向一個目錄,此目錄下的所有檔案將會覆蓋到output/target下。比如一些組態檔,或者預編譯的庫等可以在此階段處理。

  • BR2_ROOTFS_POST_BUILD_SCRIPT:一個指令碼,更加複雜的對檔案進行刪除、重新命名、strip等等功能。

  • BR2_ROOTFS_POST_IMAGE_SCRIPT:對最終生成的images進行打包處理等。

注意: 組態檔在 Buildroot/configs 目錄下。可以通過命令 make menuconfig 進行設定和檢視,如下圖所示:

  1. fs overlay
    buildroot 會將 BR2_ROOTFS_OVERLAY 設定路徑的檔案替換到 buildroot/output/xxx/build/target/ 目錄下存在或不存在的檔案,所以只需要將指令碼放在 BR2_ROOTFS_OVERLAY 中對應的目錄下即可

  2. 通過指令碼操作
    除了fs overlay這種方式,buildroot還提供了一個指令碼進行更加複雜的處理。可以進行檔案刪除、重新命名,甚至對帶偵錯資訊的檔案進行strip等。

    @$(foreach s, $(call qstrip,$(BR2_ROOTFS_POST_BUILD_SCRIPT)), \
            $(call MESSAGE,"Executing post-build script $(s)"); \
            $(EXTRA_ENV) $(s) $(TARGET_DIR) $(call qstrip,$(BR2_ROOTFS_POST_SCRIPT_ARGS))$(sep))
    

  3. 指令碼打包
    除了上面兩種方式進行替換之外,還可以在指令碼打包的環節進行替換,這個方式我沒有研究過,有需要的小夥伴可以自行嘗試一下。

常見問題

  1. tar: ./usr/bin/pkg:警告:無法 stat: 沒有那個檔案或目錄
    當安裝包的路徑變動時,可能會出現這個警告,只需要將 output/build 路徑下的 packages-file-list.txt 中的路徑給刪除即可,如下圖所示:

參考資料

buildroot/packages/app/的.mk規則的詳細解釋:https://blog.csdn.net/benco1986/article/details/131455637
嵌入式Linux構建框架Buildroot建立自己的軟體包(基於傳統makefile和cmake):https://zhuanlan.zhihu.com/p/451071335
【Buildroot】基礎知識:目錄、根檔案系統目錄覆蓋、編譯效能分析(編譯時間、目標尺寸、包依賴圖):https://blog.csdn.net/qq_28877125/article/details/130347075