建立 OpenWrt 軟件包

1、OpenWrt 目錄結構

1.1 根目錄

tools、toolchain、include、scripts、target、package、目錄爲解壓OpenWrt後系統自帶的目錄。
bin、build_dir、staging_dir、dl、feeds 目錄爲執行相關命令後自動從網絡下載目錄和編譯目錄。

clipboard.png

一、feeds
擴展軟件包目錄。html

# 執行該命令後自動建立feeds目錄,並下載相關文件至此目錄下。
$ ./scripts/feeds update -a

二、dl
編譯前將原始的軟件代碼包經過網絡下載到該目錄。ios

# 編譯時下載各軟件包保存至dl目錄下
$ make

三、package
待構建的軟件包源碼或patch文件。建立自定義軟件包時應保存至該目錄下。標準軟件包目錄結構:c++

目錄名稱 是否可選 說明
Makefile 必選 OpenWrt 構建文件
src 必選 Makefile 或 CMakefile 工程目錄
files 可選 配置文件和初始化文件
patches 可選 補丁文件

四、build_dir
自定義軟件包會拷貝至該目錄的 target-mipsel_mips32_musl 目錄下,不一樣構建架構目錄名稱不一樣。git

# package 目錄下的src軟件包會拷貝至此路徑下,並執行編譯安裝操做。
$ build_dir/target-mipsel_mips32_musl/你軟件包的src目錄內容

五、staging_dir
軟件包編譯後的安裝目錄,包含開發板的根目錄路徑。github

# 開發板根目錄路徑
$ staging_dir/target-mipsel_mips32_musl/root-brcm47xx/

六、bin
編譯完成後生成的安裝鏡像文件及ipk安裝包。網絡

七、config
包含全局編譯設置、開發人員編譯設置、目標文件格式設置和內核編譯設置等4部分。多線程

八、include
包含準備環境腳本、下載補丁腳本、編譯 Makefile 以及編譯指令等。架構

九、scripts
包含準備環境腳本、下載補丁腳本、編譯 Makefile 以及編譯指令等。app

十、target
指的是嵌入式平臺,包括特定嵌入式平臺的內容。ide

十一、toolchain
編譯器和C庫等,例如包含編譯工具 gcc 和 glibc 庫。

十二、tools
通用命令,用來生成固定的輔助工具,如打補丁工具 patch、編譯工具 make 及 squashfs 等。

1.2 重要目錄

# 假設自定義工程名爲 Hello
#########################################
# Hello
#    - Makefile     // OpenWrt 構建文件
#    + src          // Hello 工程
#       - Makefile  // Hello 工程構建文件
#       - hello.c
#
# openwrt 根目錄 ~/openwrt
#########################################


# 工程源碼存放路徑(手動)
~/openwrt/package/Hello

# 工程源碼構建路徑(自動)
~/openwrt/build_dir/target-mipsel_mips32_musl/Hello

# 工程目標安裝路徑(自動,移植後開發板的根目錄)
~/openwrt/staging_dir/target-mipsel_mips32_musl/root-brcm47xx

2、編譯流程與軟件包變量

2.1 編譯命令與流程

clipboard.png

說明

  1. 沒有 make package/hello/install 命令
  2. 執行 make package/hello/compile 命令時內部會自動執行編譯和安裝操做
  3. make clean 命令只能刪除構建的文件夾,不能刪除已安裝至 root-brcm47xx 目錄下的文件

2.2 軟件包變量

  1. openwrt 爲 OpenWrt SDK 根目錄
  2. 下文的 * 表示軟件包目錄名稱
  • 軟件包變量

    變量名 是否可選 含義
    PKG_NAME 必填 The name of the package, as seen via menuconfig and ipkg.
    PKG_RELEASE 必填 The version of this package Makefile
    PKG_VERSION 可選 The upstream version number that we're downloading.
    PKG_BUILD_DIR 可選 Where to compile the original sources
    PKG_SOURCE 可選 The filename of the original sources
    PKG_SOURCE_URL 可選 Where to download the sources from
    PKG_MD5SUM 可選 A Checksum to validate the downlaod
    PKG_CAT 可選 How to decompress the sources(zcat, bzcat, unzip)
    PKG_BUILD_DEPENDS 可選 Packages the need to build before this package, but are not required at runtime.
  • Package/* 軟件包描述

    名稱 是否可選 描述
    SECTION 目前未使用 軟件包類型(可自定義填寫)
    CATEGORY 必填 軟件包在 menuconfig 中的類別
    DESCRIPTION 已廢棄 軟件包的完整描述
    URL 可選 從哪裏下載原始軟件包
    MAINTAINER 可選 維護者信息,便於聯繫維護者。
    DEPENDS 可選 指定編譯該軟件包以前必須構建或安裝的軟件包
    conffiles 可選 該軟件包安裝的配置文件列表,每一個文件一行。
  • Build/* 軟件包構建指令

    名稱 是否可選 描述
    Build/Prepare 可選 針對源文件進行解壓縮或打補丁的一系列命令,能夠不定義。
    Build/Configure 可選 針對配置文件的一些列命令,能夠不定義。
    Build/Compile 可選 指定如何編譯源文件,絕大部分狀況下無需定義。
    Package/package-name/config 可選 可執行PACKAGE或CONFIG相關節點操做
    Package/package-name/install 必填 拷貝源碼編譯的文件至ipkg
    Package/package-name/preinst 可選 執行Package/install前的腳本,切記包含 #!/bin/sh, return false 退出安裝。
    Package/package-name/postinst 可選 執行Package/install後的腳本,切記包含 #!/bin/sh。
    Package/package-name/prerm 可選 刪除文件前執行的操做,規則相似Package/preinst
    Package/package-name/postrm 可選 刪除文件後執行的操做,規則相似Package/postrm
  • OpenWrt 系統變量

    變量名 變量定義 變量含義 變量值
    $(TOPDIR) ${CURDIR} OpenWrt 根目錄 /openwrt
    $(DL_DIR) $(TOPDIR)/dl 經過網絡下載的標準軟件包 /openwrt/dl
    ${OUTPUT_DIR} $(TOPDIR)/bin 最終編譯出的ipk軟件包 /openwrt/bin
    ${INCLUDE_DIR} $(TOPDIR)/include 包含文件 /openwrt/include
    $(SCRIPT_DIR) $(TOPDIR)/scripts 腳本文件 /openwrt/scripts
    $(BUILD_DIR_BASE) ??? $(TOPDIR)/build_dir /openwrt/build_dir
    $(PACKAGE_DIR) $(BIN_DIR)/packages

2.3 軟件包指令

全部指令位於 rules.mk 文件
指令名稱 指令定義 說明
INSTALL_DIR install -d -m0755 建立安裝目錄
INSTALL_BIN install -m0755 安裝可執行文件
INSTALL_SUID install -m4755 -
INSTALL_DATA install -m0644 安裝數據文件
INSTALL_CONF install -m0600 安裝配置文件

2.4 編譯指令

  • 全部軟件包編譯

    $ make menuconfig
    $ ... 勾選相關軟件包保存後退出
    $ make
  • 單個軟件包編譯

    # 編譯並安裝軟件包
    $ make package/${packageName}/compile
  • 編譯選項

    # 編譯全部軟件包,不輸出詳細信息,單線程編譯
    $ make
    
    # 單線程編譯(不帶j默認爲單線程)
    $ make -j=1
    
    # 多線程編譯(指定數目)
    $ make -j=2
    
    # 多線程編譯(根據硬件自動)
    $ make -j
    
    # 輸出詳細信息(默認不輸出詳細信息)
    $ make V=s
    
    # 組合使用示例
    $ make V=s -j=2
    
    # 說明:
    # 1. 多線程編譯速度快,但產生編譯錯誤時不便於定位故障緣由。
    # 2. 想快速編譯可採用以下形式:make -j,不輸出信息且根據CPU內核數自動多線程編譯。
    # 3. 想查看編譯錯誤可採用以下形式:make V=s 或 make V=s -j1。
    # 4. 若是是初次添加自定義軟件包,必須先經過 make menuconfig 而後 make 的方式構建。

3、建立基於Makefile的軟件包

3.1 文件結構和內容

  • 工程結構
    clipboard.png
  • sprite/Makefile

    include $(TOPDIR)/rules.mk
    
    PKG_NAME:=sprite
    PKG_RELEASE:=1
    PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
    
    include $(INCLUDE_DIR)/package.mk
    
    define Package/$(PKG_NAME)
        SECTION:=utils
        CATEGORY:=Suning
        TITLE:=promote information for $(PKG_NAME).
    endef
    
    define Package/$(PKG_NAME)/description
        This is a Makefile project.
    endef
    
    define Package/$(PKG_NAME)/install
        $(INSTALL_DIR) $(1)/usr/bin
        $(INSTALL_BIN) $(PKG_BUILD_DIR)/$(PKG_NAME) $(1)/usr/bin/
    endef
    
    $(eval $(call BuildPackage,$(PKG_NAME)))
    符號 等價值 說明
    $(INSTALL_DIR) install -d -m0755 建立特定權限的 /usr/bin 目錄
    $(INSTALL_BIN) install -m0755 修改文件權限並拷貝至/ usr/bin 目錄
  • sprite/src/sprite.c

    #include <stdio.h>
    
    int main(void)
    {
         printf("Hello World!\n");
         return 0;
    }
  • sprite/src/Makefile

    CC = gcc
    FLAG = -Wall
    
    sprite:
        $(CC) $(FLAG) sprite.c -o sprite

3.2 構建和清理

  • 編譯、安裝

    # $(1) 表示目標系統的根目錄
    # 或者經過 menuconfig 選中 sprite 選項,執行 make 命令
    $ make package/sprite/compile V=s
  • 刪除拷貝的構建目錄

    # 刪除 ~/openwrt/build_dir/target-mipsel_mips32_musl/sprite
    $ make package/sprite/clean

3.3 構建結果

  • 自動建立的構建目錄
    clipboard.png
  • 構建產生的可執行文件
    clipboard.png
  • 構建產生的安裝包文件
    clipboard.png
  • 安裝至目標系統根目錄
    clipboard.png

4、建立基於CMake的軟件包

4.1 文件結構和內容

  • 工程結構
    clipboard.png
  • clxye/Makefile

    include $(TOPDIR)/rules.mk
    
    PKG_NAME:=clxye
    PKG_RELEASE:=1
    PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
    
    include $(INCLUDE_DIR)/package.mk
    include $(INCLUDE_DIR)/cmake.mk
    
    define Package/${PKG_NAME}
        SECTION:=utils
        CATEGORY:=Suning
        DEPENDS:=+libstdcpp +libpthread
        TITLE:=promote information for ${PKG_NAME}.
    endef
    
    define Package/${PKG_NAME}/description
        This is a CMake project.
    endef
    
    define Package/${PKG_NAME}/install
        $(INSTALL_DIR) $(1)/usr/bin
        $(INSTALL_BIN) $(PKG_BUILD_DIR)/${PKG_NAME} $(1)/usr/bin/
    endef
    
    $(eval $(call BuildPackage,${PKG_NAME}))
    一、CMake 工程必須包含 include $(INCLUDE_DIR)/cmake.mk
    二、C++ 工程必須包含 libstdcpp
  • clxye/src/clxye.cpp

    #include <iostream>
    #include <thread>
    
    int main(void)
    {
        std::thread t( [](){ std::cout << "Hello World!" << std::endl; } );
    
        t.join();
        return 0;
    }
  • clxye/src/Makefile

    # 所需 cmake 工具的最低版本
    cmake_minimum_required(VERSION 2.6)
    
    # 工程名稱
    project(clxye)
    
    # 生成可執行程序
    add_executable(${PROJECT_NAME} clxye.cpp )
    
    # 連接共享庫
    target_link_libraries(${PROJECT_NAME}
        pthread
    )
    
    # 安裝可執行文件(必須提供install)
    install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION "/usr/bin")

4.2 構建和清理

  • 編譯、安裝

    # 初次編譯需採用 make menuconfig、check and save、make V=s 編譯
    $ make package/clxye/compile V=s
  • 刪除拷貝的構建目錄

    # 刪除 ~/openwrt/build_dir/target-mipsel_mips32_musl/clxye
    $ make package/sprite/clean

4.3 構建結果

結果與 Makefile 基本一致(clxye與sprite文件名不一樣),這裏再也不重複展現。

5、依賴軟件包

5.1 依賴包類型

  • Package 類型
    image.png
  • Config 類型
    image.png

    config GST1_LIBAV_DECODER_mp3
        bool "MP3 (MPEG Audio Layer 2)"

5.2 選中依賴包

  • DEPENDS 依賴項

    # 此方式只能爲 Package 類型,不支持 Config 類型
    define Package/$(PKG_NAME)
    SECTION:=utils
    CATEGORY:=Suning
    DEPENDS:=+libc +libgcc +librt +libpcre +libpthread +pulseaudio-daemon +portaudio \
             +gst1-libav +gstreamer1-libs +libgst1app
    TITLE:=promote information for $(PKG_NAME).
    endef
  • select 方法

    # Package 與 Config 兩種類型均支持
    define Package/$(PKG_NAME)/config
        select GST1_LIBAV_DECODER_mp3
        select GST1_LIBAV_PARSER_mpegaudio
        select PACKAGE_gst1-mod-alsa    
        select PACKAGE_gstreamer1-utils
    endef

5.3 GStreamer 最小依賴

efine Package/$(PKG_NAME)
    SECTION:=utils
    CATEGORY:=Suning
    DEPENDS:=+libc +libgcc +librt +libpcre +libpthread +pulseaudio-daemon +portaudio \
             +gst1-libav +gstreamer1-libs +libgst1app
    TITLE:=promote information for $(PKG_NAME).
endef

define Package/$(PKG_NAME)/config
    # ** gst1-libav **
    select GST1_LIBAV_DECODER_ac3
    select GST1_LIBAV_DECODER_mp3
    select GST1_LIBAV_DECODER_pcm_s16be
    select GST1_LIBAV_DECODER_pcm_s16le
    select GST1_LIBAV_DEMUXER_ac3
    select GST1_LIBAV_DEMUXER_mp3
    select GST1_LIBAV_PARSER_ac3
    select GST1_LIBAV_PARSER_mpegaudio

    # ** gstreamer1-plugins-base **
    select PACKAGE_gst1-mod-alsa
    select PACKAGE_gst1-mod-app
    select PACKAGE_gst1-mod-audioconvert
    select PACKAGE_gst1-mod-playback
    select PACKAGE_gst1-mod-typefindfunctions
    select PACKAGE_gst1-mod-volume

    # ** gstreamer1-plugins-good **
    select PACKAGE_gst1-mod-audioparsers
    select PACKAGE_gst1-mod-autodetect
    select PACKAGE_gst1-mod-id3demux
    select PACKAGE_gst1-mod-wavparse

    # ** gstreamer1-utils **
    select PACKAGE_gstreamer1-utils
endef

6、常見問題

一、Makefile:1: *** missing separator. Stop.

# 空格與Tab的問題,進入 Makefile 所在目錄執行以下腳本
$ perl -pi -e 's/^  */\t/' Makefile

二、make[2]: Nothing to be done for 'compile'.

# 暫時未找到從根本上解決問題的方法
# 可經過 make menuconfig 勾選後執行 make 操做的方式編譯

三、WARNING: your configuration is out of sync. Please run make menuconfig, oldconfig or defconfig!

# 執行 make package/${packagename}/compile 時的編譯警告
# 此時必須經過 make menuconfig... save... make 的方式編譯,不然 install 會致使目標系統沒有安裝文件的狀況。

四、Package xxx is missing dependencies for the following libraries: libstdc++.so.6

# 添加 c++ 依賴庫
DEPENDS:=+libstdcpp

五、Makefile:26: *** Package/clxye is missing the VERSION field. Stop

# Makefile 中該關鍵字不能省略(不是 PKG_VERSION)
PKG_RELEASE:=1

六、Package/$(PKG_NAME)/install 腳本未執行

# 此時構建目錄中未生成 「.pkgdir」 和 「ipkg-mipsel_mips32」 目錄。
# 經過 make menuconfig 勾選該軟件包,而後再執行 make package/xxx/compile 編譯指令,此問題耗費了兩天。

參考連接

1. OpenWrt Development Guide
2. Openwrt Examples
3. Creating packages
4. Openwrt package Makefile
5. Makefile 選項 CFLAGS,LDFLAGS,LIBS
6. OpenWRT的包依賴 package DEPEND
7. Alternative for missing __sync_fetch_and_add_8 on MIPS 32-bit
譯 《Documentation/kbuild/kconfig-language.txt》
kconfig語法整理)

相關文章
相關標籤/搜索