1. 程式人生 > >openwrt簡單ipk生成及Makefile解釋

openwrt簡單ipk生成及Makefile解釋

前言

類似的文章其實網上比較多了,我寫這個的目的:

1,網上文章良莠不齊,有些自己都沒實際動手操作,隨便複製貼上,實際操作不可行.
2,基本只講了操作,我當時最關心的Makefile檔案的解釋沒有.

所以我自己總結了一篇.

說明

開發板為MT7620a,openwrt版本為:barrier_breaker_14.07.編譯主機為ubuntu 14.04 32位.
git clone git://git.openwrt.org/14.07/openwrt.git
關於怎麼搭建編譯環境以及編譯請參考網上

正文

下面我們開始,我們遵循傳統以helloworld開始.

1.建立helloworld專案

首先我們新建helloworld.c檔案和對應的Makefile檔案

$mkdir -p ~/temp/hellworld/src
$cd ~/temp/helloworld/src
$touch helloworld.c Makefile

如下為helloworld.c的內容:

#include <stdio.h>
int main()
{
    printf("This is my helloworld!\n");
    return 0;
}

如下為Makefile檔案的內容:

helloworld : helloworld.o
    $(CC) $(LDFLAGS) helloworld.o
-o helloworld helloworld.o : helloworld.c $(CC) $(CFLAGS) -c helloworld.c clean : rm *.o helloworld
$(CC)
這個值由其他Makefile檔案規定,表示我們使用編譯器.
$(LDFLAGS)\&$(CFLAGS)
這個表示編譯器的一些選項,這裡是可選的,去掉也沒有問題.

下面可以輸入$make看看有沒有問題,注意Makefile檔案的書寫格式.
最後,輸入$make clean來清理掉生成的二進位制檔案.因為上一步make所使用的編譯器並不是我們的交叉編譯鏈,生成的二進位制檔案並不能在開發板中執行.上一步只是驗證我們的src中的內容正確與否.

2.建立helloworld包

下一步我們要建立一個新的Makefile檔案,在這個檔案中我們要描述的是helloworld包的資訊,比如:如何配置,如何編譯,如何打包,安裝位置等.

$cd ~/temp/helloworld
$touch Makefile

如下為Makefile內容:

include $(TOPDIR)/rules.mk

PKG_NAME:=helloworld
PKG_RELEASE:=1
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)

include $(INCLUDE_DIR)/package.mk

define Package/helloworld
    SECTION:=utils
    CATEGORY:=Utilities
    TITLE:=Helloworld -- prints a snarky message
endef

define Package/helloworld/description
    It's my first package demo.
endef

define Build/Prepare
    echo "Here is Package/Prepare"
    mkdir -p $(PKG_BUILD_DIR)
    $(CP) ./src/* $(PKG_BUILD_DIR)/
endef

define Package/helloworld/install
    echo "Here is Package/install"
    $(INSTALL_DIR) $(1)/bin
    $(INSTALL_BIN) $(PKG_BUILD_DIR)/helloworld $(1)/bin/
endef

$(eval $(call BuildPackage,helloworld))

如下是最後的檔案樹形圖:
樹形圖

3.Makefile註釋

第1行include $(TOPDIR)/rules.mk
一般在Makefile的開頭,包含了包的基本資訊,比如Makefile中的$(BUILD_DIR),$(INCLUDE_DIR),$(CP),$(INSTALL_DIR),$(INSTALL_BIN)都是這裡定義的.具體內容可以到原始碼主目錄下,檢視rules.mk檔案.
3~5行,軟體包的資訊均以“PKG_”開頭,其意思和作用如下
PKG_NAME:軟體包名稱,將在menuconfig和ipkg可以看到。
PKG_VERSION:軟體版本號。
PKG_RELEASE:Makefile的版本號
PKG_SOURCE:原始碼的檔名。
PKG_SOURCE_URL:原始碼的下載網站位置。
PKG_MD5SUM:原始碼檔案的效驗碼。用於核對軟體包是否下載正確。
PKG_CAT:原始碼檔案的解壓方法。包括zcat, bzcat, unzip等。
PKG_BUILD_DIR:軟體包編譯目錄。它的父目錄為$(BUILD_DIR)。
第7行include $(INCLUDE_DIR)/package.mk
一般在軟體包的基本資訊完成後再引入,他定義了使用者態軟體包的規則。編譯包分為使用者態和核心模組,使用者態軟體包使用Package,核心模組使用KernelPackage.$(INCLUDE_DIR)/Kernel.mk檔案對於軟體包為核心時不可缺少,$(INCLUDE_DIR)/package.mk應用在使用者態。接下來講述使用者態軟體包。使用者程式的編譯包以Package/開頭,然後接著軟體名,在Package定義中的軟體名可以與軟體包名不一樣,而且可以多個定義。
9~13行
定義包的名稱為helloworld
SECTION : 包的型別為utils
CATEGORY : 目錄為Utilitis,即檔案在menuconfig中的位置;有時還會有SUBMENU項,即子目錄.
TITLE : 用於軟體包的簡短描述,將顯示在menuconfig中.
URL : 軟體包的下載位置。
MAINTAINER : 維護者選項。
DEPENDS : 與其他軟體的依賴。即如編譯或安裝需要其他軟體時需要說明。如果存在多個依賴,則每個依賴需用空格分開。依賴前使用+號表示預設顯示,即物件沒有選中時也會顯示,使用@則預設為不顯示,即當依賴物件選中後才顯示。
15~17行
軟體包的詳細描述,將顯示在make menuconfig
19~23行
編譯準備方法,對於網上下載的軟體包不需要再描述。對於非網上下載或自行開發的軟體包必須說明編譯準備方法。本文所用的準備方法就是首先建立軟體包目錄,然後將原始碼拷貝到剛剛建立的目錄中。按OpenWrt的習慣,一般把自己設計的程式全部放在src目錄下。
25~29行
軟體包的安裝方法,包括一系列拷貝編譯好的檔案到指定位置。呼叫時會帶一個引數,就是嵌入系統的映象檔案系統目錄,因此$(1)表示嵌入系統的映象目錄。
INSTALL_DIR:=install -d -m0755 : 建立所屬使用者可讀寫、執行,其他使用者可讀可執行的目錄
INSTALL_BIN:=install -m0755 : 編譯好的檔案到映象檔案目錄
31行 $(eval $(call BuildPackage,helloworld))
完成前面定義後,必須使用eval函式實現各種定義。其格式為:
對於一般軟體包:$(eval $(call Package,$(PKG_NAME)))
或對於核心模組:$(eval $(call KernelPackage,$(PKG_NAME)))
如果一個軟體包有多個程式,例如:一個應用程式有自己的核心模組,上面使用的PKG_NAME需要靈活變通。eval函式可能設計多個。也可以當成多個軟體包處理。

這裡簡單地解釋了Makefile檔案,更具體地請參考

4.編譯軟體

至此我們的軟體已經基本完成,下面進行編譯
首先將檔案資料夾拷貝到openwrt目錄中的package檔案中,這裡我的原始碼目錄為~/openwrt,你需要把openwrt目錄替換為你的openwrt原始碼目錄.

$mv ~/temp/helloworld ~/openwrt/package

然後回到專案主目錄執行make menuconfig

$cd ~/openwrt
$make menuconfig

按”/”後,輸入helloworld,搜尋對應的路徑
搜尋
搜尋結果

接著到Utilities目錄下,找到helloworld並按空格開啟;
開啟編譯開關
儲存後退出;

$cd ~/openwrt
$make package/helloworld/compile V=s

編譯完成後,ipk應該已經生成

$find bin/ -name "helloworld*.ipk"

至此我們已經生成簡單的ipk,恭喜:)
最後可以通過winscp,將ipk安裝到開發板中.
結局

尾記

我比較薄弱的是Makefile方面的知識,剛好加強下這個方面的學習,歡迎交流~