這篇文章主要為大家展示了“OpenWRT中包的Makefile內(nèi)容是什么”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“OpenWRT中包的Makefile內(nèi)容是什么”這篇文章吧。
創(chuàng)新互聯(lián)公司是網(wǎng)站建設(shè)專家,致力于互聯(lián)網(wǎng)品牌建設(shè)與網(wǎng)絡(luò)營(yíng)銷,專業(yè)領(lǐng)域包括網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、電商網(wǎng)站制作開發(fā)、重慶小程序開發(fā)公司、微信營(yíng)銷、系統(tǒng)平臺(tái)開發(fā),與其他網(wǎng)站設(shè)計(jì)及系統(tǒng)開發(fā)公司不同,我們的整合解決方案結(jié)合了恒基網(wǎng)絡(luò)品牌建設(shè)經(jīng)驗(yàn)和互聯(lián)網(wǎng)整合營(yíng)銷的理念,并將策略和執(zhí)行緊密結(jié)合,且不斷評(píng)估并優(yōu)化我們的方案,為客戶提供全方位的互聯(lián)網(wǎng)品牌整合方案!
包里的 Makefile 內(nèi)容如下:
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))
大概我們可以將簡(jiǎn)代為如下的結(jié)構(gòu):
include $(TOPDIR)/rules.mk # 這里定義一系列的 PKG_XX include $(INCLUDE_DIR)/package.mk # 定義各種 Package, Build 宏 $(eval $(call BuildPackage,包名))
下面,我們來一一拆解。
首先,include $(TOPDIR)/rules.mk,也就是將 SDK/rules.mk 文件中的內(nèi)容導(dǎo)入進(jìn)來。
TOPDIR就是SDK的路徑。
在 SDK/rules.mk 文件中,定義了許多變量。
我們可以看出,在Makefile中,賦值是用 := ,而不是等號(hào)。
比如上面的 BUILD_DIR, INCLUDE_DIR 等,都在這里定義。還有:
還有關(guān)于 TARGET_CC, TARGET_CXX 等非常有用的變量定義。
還有 TAR, FIND, INSTALL_BIN, INSTALL_DIR, INSTALL_DATA等等非常重要的變量定義。
官網(wǎng)上指定有如下變量需要設(shè)置:
PKG_NAME - The name of the package, as seen via menuconfig and ipkg
PKG_VERSION - The upstream version number that we're downloading
PKG_RELEASE - The version of this package Makefile
PKG_LICENSE - The license(s) the package is available under, SPDX form.
PKG_LICENSE_FILE- file containing the license text
PKG_BUILD_DIR - Where to compile the package
PKG_SOURCE - The filename of the original sources
PKG_SOURCE_URL- Where to download the sources from (directory)
PKG_MD5SUM - A checksum to validate the download
PKG_CAT - How to decompress the sources (zcat, bzcat, unzip)
PKG_BUILD_DEPENDS - Packages that need to be built before this package, but are not required at runtime. Uses the same syntax as DEPENDS below.
PKG_INSTALL - Setting it to "1">
PKG_INSTALL_DIR - Where "make install" copies the compiled files
PKG_FIXUP - ???
PKG_SOURCE_PROTO - the protocol to use for fetching the sources (git, svn)
PKG_REV - the svn revision to use, must be specified if proto is "svn"
PKG_SOURCE_SUBDIR - must be specified if proto is "svn" or "git", e.g. "PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)"
PKG_SOURCE_VERSION - must be specified if proto is "git", the commit hash to check out
PKG_CONFIG_DEPENDS - specifies which config options depend on this package being selected
跟上面的 include $(TOPDIR)/rules.mk 是一樣的。就是把這個(gè)文件包含進(jìn)來。
INCLUDE_DIR這個(gè)變量在 rules.mk 里已經(jīng)定義了:
那就是 SDK/include/package.mk 文件了,打開看看。
主要有以下幾個(gè)功能:
如果某個(gè)變量我們沒有在上一部分里定義,那里在這個(gè)文件里,它就會(huì)被指定為默認(rèn)值,比如:
上面的用 ?= 來表示給未定義的變量賦默認(rèn)值。比如,如果沒有指定 PKG_MD5SUM,那么就默認(rèn)為 unknow。
根據(jù)上部分用戶自定義的 PKG_XXXX 變量推導(dǎo)出更多相關(guān)的變量。
比如:
雖然我沒有看過相關(guān)的手冊(cè),根據(jù)多年的從業(yè)經(jīng)驗(yàn)也能看出上面的意思來。
#如果定義了宏,就... ifdef 宏名 ... endif #如果宏相等 ifeq (宏1,宏2) ... endif strip $宏名 #將宏對(duì)應(yīng)的值去除前后的空白字符 VAR += xxxx #在變量 VAR 后面追加 xxxx
我猜大概就是這樣,如果不對(duì)請(qǐng)指正。
再比如如下:
就這樣,它為我們提供了大量有價(jià)值的變量。
在 Makefile 中,宏的定義格式是:
define XXX/xxxx <宏的實(shí)體...> endef
package.mk會(huì)把大部分需要的宏都定義好。理想情況下,用戶只需要定義好了 PKG_XXX 之后,不需要再自定義宏,默認(rèn)的宏就可以滿足需求。
比如Build/Prepare/Default的定義:
Build/Prepare宏是在編譯前進(jìn)行的,是準(zhǔn)備工作。
可以看出,它分了兩種情況:
A,定義了 USE_GIT_TREE,則按git的方式定義。
B,定義了 USB_SOURCE_DIR,則按源碼在本地的方案定義。
最重要的一個(gè)宏是 BuildPackage。它會(huì)在 Makefile 的最后一行被引用。它的實(shí)現(xiàn)也就是在 package.mk 文件里。如下為其源碼:
define BuildPackage $(Build/IncludeOverlay) $(eval $(Package/Default)) #定義在package-defaults.mk文件里 $(eval $(Package/$(1))) #調(diào)用用戶自定義的 Package/<包名> 宏 ifdef DESCRIPTION $$(error DESCRIPTION:= is obsolete, use Package/PKG_NAME/description) endif #檢查有沒有定義 Package/<包名>/description宏,如果沒有定義,則以TITLE默認(rèn)定義一個(gè) ifndef Package/$(1)/description define Package/$(1)/description $(TITLE) endef endif BUILD_PACKAGES += $(1) $(STAMP_PREPARED): $$(if $(QUILT)$(DUMP),,$(call find_library_dependencies,$(DEPENDS))) #檢查 TITLE, CATEGORY, SECTION, VERSION 是否定義,如果沒有定義則報(bào)錯(cuò) $(foreach FIELD, TITLE CATEGORY SECTION VERSION, ifeq ($($(FIELD)),) $$(error Package/$(1) is missing the $(FIELD) field) endif ) #如果有定義DUMP,那就引入Dumpinfo/Package宏的內(nèi)部。 #如果沒有,那么就引用 Packaget/<包名>/targets里面的每一個(gè)target,如果沒有定義Packaget/<包名>/targets宏,那么將PKG_TARGETS里的每個(gè)target取出來, #如果也沒有定義PKG_TARGETS,那就默認(rèn)ipkg作為target。將每一個(gè)target,引用 BuildTarget/$(target)。 $(if $(DUMP), \ $(Dumpinfo/Package), \ $(foreach target, \ $(if $(Package/$(1)/targets),$(Package/$(1)/targets), \ $(if $(PKG_TARGETS),$(PKG_TARGETS), ipkg) \ ), $(BuildTarget/$(target)) \ ) \ ) $(if $(PKG_HOST_ONLY)$(DUMP),,$(call Build/DefaultTargets,$(1))) endef
總結(jié)一下語法:
$() 表示要執(zhí)行的一條語句
$(if 條件, 成立執(zhí)行, 失敗執(zhí)行) if條件分支
$(foreach 變量, 成員列表, 執(zhí)行體) 成員遍歷語句
可以看出,語句是可以嵌套使用的。
$(N) 表示第N個(gè)參數(shù)
我定要為我們的package定義特定的宏:
Package/<包名> #包的參數(shù)
在 Package/<包名> 宏中定義與包相關(guān)的信息。
如Package/helloworld宏:
define Package/helloworld SECTION:=utils CATEGORY:=Utilities TITLE:=Helloworld -- prints a snarky message endef
除了上面所列的 SECTION,CATEGORY,TITLE變量外,還可以定義:
SECTION - 包的種類
CATEGORY - 顯示在menuconfig的哪個(gè)目錄下
TITLE - 簡(jiǎn)單的介紹
DESCRIPTION - (deprecated) 對(duì)包詳細(xì)的介紹
URL - 源碼所在的網(wǎng)絡(luò)路徑
MAINTAINER - (required for new packages) 維護(hù)者是誰(出錯(cuò)了聯(lián)系誰)
DEPENDS - (optional) 需要依事的包,See below for the syntax.
USERID - (optional) a username:groupname pair to create at package installation time.
其它的宏可以選擇性地定義,通常沒必要自己重寫。但有些情況,package.mk中默認(rèn)的宏不能滿足我們的需求。這時(shí),我們就需要自己重定義宏。
比如,我們?cè)跒閔elloworld寫Makefile時(shí),我們要求在編譯之前,將 SDK/package/helloworld/src/ 路徑下的文件復(fù)制到 PKG_BUILD_DIR 所指定的目錄下。
于是我們重新定義Build/Prepare宏:
define Build/Prepare mkdir -p $(PKG_BUILD_DIR) $(CP) ./src/* $(PKG_BUILD_DIR)/ endef
如此以來,在我們 make V=s 時(shí),make工具會(huì)在編譯之前執(zhí)行 Build/Prepare 宏里的命令。
再比如,我們要指定包的安裝方法:
define Package/helloworld/install $(INSTALL_DIR) $(1)/bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/helloworld $(1)/bin/ endef
上面的這個(gè)宏就是指定了包的安裝過程。其中 INSTALL_DIR 定義在 rules.mk 文件里。
INSTALL_DIR = install -d -m0755
INSTALL_BIN = install -m0755
$(1)為第一個(gè)參數(shù)是./configure時(shí)的--prefix參數(shù),通常為""
展開之后就是:
define Package/helloworld/install install -d -m0755 /bin install -m0755 $(PKG_BUILD_DIR)/helloworld /bin/ endef
它的意思就一目了然了。
除了上面所列舉的這兩個(gè)宏外,在官網(wǎng)上也說明了其它可選的宏:
由該包安裝的配置文件的列表,一行一個(gè)文件。
對(duì)包描述的純文本
A set of commands to unpack and patch the sources. You may safely leave this undefined.
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,)">
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)
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.
For things needed to compile packages against it (static libs, header files), but that are of no use on the target device.
A 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.
The 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.
The actual text of the script which is to be executed after installation. Dont forget to include the #!/bin/sh.
The 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.
The actual text of the script which is to be executed after removal. Dont forget to include the #!/bin/sh.
之所以有些宏是以"Package/"開頭,有的又以"Build/",是因?yàn)樵谝粋€(gè)Makefile里生成多個(gè)包。OpenWrt默認(rèn)認(rèn)為一個(gè)Makefile里定義一個(gè)包,但我們也可以根據(jù)需要將其拆分成多個(gè)。所以說,如果我們只希望編譯一次,那么只要有一系列的"Build/"的宏定義就可以了。但是,我們也可以通過添加多個(gè)"Package/"宏定義,并調(diào)用 BuildPackage,來創(chuàng)建多個(gè)包。
在Makefile的最后一行是:
$(eval $(call BuildPackage,helloworld))
最重要的 BuildPackage定義在 package.mk 文件里。見上面 BuildPackage 宏定義。
以上是“OpenWRT中包的Makefile內(nèi)容是什么”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!