摘要: 本文將與大家一起來研究OpenWrt包的Makefile格式以及其工作原理
上面一篇博文中,博主嘗試創(chuàng)建一個非常簡單的helloworld包,過程詳見博文:http://my.oschina.net/hevakelcj/blog/410633 本文將帶大家一起深入地學(xué)習(xí)一下OpenWrt包的 Makefile。我們不僅要知其然,還要知其所以然。 在上篇博文里,包里的 Makefile 內(nèi)容如下:
大概我們可以將簡代為如下的結(jié)構(gòu):
下面,,我們來一一拆解。 include $(TOPDIR)/rules.mk
首先,include $(TOPDIR)/rules.mk,,也就是將 SDK/rules.mk 文件中的內(nèi)容導(dǎo)入進(jìn)來,。 TOPDIR就是SDK的路徑。 在 SDK/rules.mk 文件中,,定義了許多變量,。 我們可以看出,在Makefile中,,賦值是用 := ,,而不是等號。 比如上面的 BUILD_DIR, INCLUDE_DIR 等,,都在這里定義,。還有: 還有關(guān)于 TARGET_CC, TARGET_CXX 等非常有用的變量定義。 還有 TAR,, FIND,, INSTALL_BIN, INSTALL_DIR, INSTALL_DATA等等非常重要的變量定義。 自定義 PKG_XXXX 變量
官網(wǎng)上指定有如下變量需要設(shè)置:
include $(INCLUDE_DIR)/package.mk跟上面的 include $(TOPDIR)/rules.mk 是一樣的,。就是把這個文件包含進(jìn)來,。 INCLUDE_DIR這個變量在 rules.mk 里已經(jīng)定義了: 那就是 SDK/include/package.mk 文件了,打開看看,。 主要有以下幾個功能: (1)它會配置默認(rèn)的變量如果某個變量我們沒有在上一部分里定義,,那里在這個文件里,它就會被指定為默認(rèn)值,,比如: 上面的用 ?= 來表示給未定義的變量賦默認(rèn)值,。比如,如果沒有指定 PKG_MD5SUM,,那么就默認(rèn)為 unknow,。 (2)推導(dǎo)其它變量
根據(jù)上部分用戶自定義的 PKG_XXXX 變量推導(dǎo)出更多相關(guān)的變量。 比如: 雖然我沒有看過相關(guān)的手冊,,根據(jù)多年的從業(yè)經(jīng)驗也能看出上面的意思來,。
我猜大概就是這樣,,如果不對請指正,。 再比如如下: 就這樣,,它為我們提供了大量有價值的變量,。 (3)包含其它mk文件
(4)定義默認(rèn)宏
在 Makefile 中,宏的定義格式是:
package.mk會把大部分需要的宏都定義好,。理想情況下,,用戶只需要定義好了 PKG_XXX 之后,不需要再自定義宏,默認(rèn)的宏就可以滿足需求,。 比如Build/Prepare/Default的定義: Build/Prepare宏是在編譯前進(jìn)行的,,是準(zhǔn)備工作。 可以看出,,它分了兩種情況: A,,定義了 USE_GIT_TREE,則按git的方式定義,。 B,,定義了 USB_SOURCE_DIR,則按源碼在本地的方案定義,。 (5)BuildPackage宏
最重要的一個宏是 BuildPackage,。它會在 Makefile 的最后一行被引用。它的實現(xiàn)也就是在 package.mk 文件里,。如下為其源碼:
總結(jié)一下語法: $() 表示要執(zhí)行的一條語句 $(if 條件, 成立執(zhí)行, 失敗執(zhí)行) if條件分支 $(foreach 變量, 成員列表, 執(zhí)行體) 成員遍歷語句 可以看出,語句是可以嵌套使用的,。 $(N) 表示第N個參數(shù) 自定義宏必須定義的宏
我定要為我們的package定義特定的宏:
在 Package/<包名> 宏中定義與包相關(guān)的信息,。 如Package/helloworld宏:
除了上面所列的 SECTION,CATEGORY,,TITLE變量外,,還可以定義:
可選定義的宏其它的宏可以選擇性地定義,,通常沒必要自己重寫,。但有些情況,package.mk中默認(rèn)的宏不能滿足我們的需求,。這時,,我們就需要自己重定義宏,。 比如,我們在為helloworld寫Makefile時,,我們要求在編譯之前,,將 SDK/package/helloworld/src/ 路徑下的文件復(fù)制到 PKG_BUILD_DIR 所指定的目錄下。 于是我們重新定義Build/Prepare宏:
如此以來,,在我們 make V=s 時,,make工具會在編譯之前執(zhí)行 Build/Prepare 宏里的命令。 再比如,,我們要指定包的安裝方法:
上面的這個宏就是指定了包的安裝過程,。其中 INSTALL_DIR 定義在 rules.mk 文件里。 INSTALL_DIR = install -d -m0755 INSTALL_BIN = install -m0755 $(1)為第一個參數(shù)是./configure時的--prefix參數(shù),,通常為"" 展開之后就是:
它的意思就一目了然了,。 除了上面所列舉的這兩個宏外,在官網(wǎng)上也說明了其它可選的宏: Package/conffiles (optional)由該包安裝的配置文件的列表,,一行一個文件,。 Package/description對包描述的純文本 Build/Prepare (optional)A set of commands to unpack and patch the sources. You may safely leave this undefined. Build/Configure (optional)You can leave this undefined if the source doesn't use configure or has a normal config script, otherwise you can put your own commands here or use "$(call Build/Configure/Default,)" as above to pass in additional arguments for a standard configure script. Build/Compile (optional)How to compile the source; in most cases you should leave this undefined, because then the default is used, which calls make. If you want to pass special arguments to make, use e.g. "$(call Build/Compile/Default,FOO=bar) Build/Install (optional)How to install the compiled source. The default is to call make install. Again, to pass special arguments or targets, use $(call Build/Install/Default,install install-foo) Note that you need put all the needed make arguments here. If you just need to add something to the "install" argument, don't forget the 'install' itself. Build/InstallDev (optional)For things needed to compile packages against it (static libs, header files), but that are of no use on the target device. Package/installA set of commands to copy files into the ipkg which is represented by the $(1) directory. As source you can use relative paths which will install from the unpacked and compiled source, or $(PKG_INSTALL_DIR) which is where the files in the Build/Install step above end up. Package/preinstThe actual text of the script which is to be executed before installation. Dont forget to include the #!/bin/sh. If you need to abort installation have the script return false. Package/postinstThe actual text of the script which is to be executed after installation. Dont forget to include the #!/bin/sh. Package/prermThe actual text of the script which is to be executed before removal. Dont forget to include the #!/bin/sh. If you need to abort removal have the script return false. Package/postrmThe actual text of the script which is to be executed after removal. Dont forget to include the #!/bin/sh. 之所以有些宏是以"Package/"開頭,有的又以"Build/",,是因為在一個Makefile里生成多個包,。OpenWrt默認(rèn)認(rèn)為一個Makefile里定義一個包,但我們也可以根據(jù)需要將其拆分成多個,。所以說,,如果我們只希望編譯一次,那么只要有一系列的"Build/"的宏定義就可以了,。但是,,我們也可以通過添加多個"Package/"宏定義,并調(diào)用
BuildPackage,,來創(chuàng)建多個包,。 使之生效
在Makefile的最后一行是:
最重要的 BuildPackage定義在 package.mk 文件里。見上面 BuildPackage 宏定義,。
|
|