<pkg>.mk
這邊的『.mk』檔的內容格式會跟一般的makefile不一樣,裡面會是一堆連續的變數定義,變數的名字都必須用大寫的英文為開頭在加一個『 _ 』,然後檔案的最後都要定義想要使用套件的架構巨集。
下面舉的例子來說:
可以看到上面的變數名稱都是以大寫的『XZ』為開頭,然後結尾是以呼叫『target』和『host』的autotools-package架構,代表這兩種架構都會用到。
除了上面提到的在『.mk』檔的命名規則以外,還有個就是之前提到的『Config.in』裡面這個套件的開關『BR2_PACKAGE_<PKG>』,這個<PKG>也必須是這個套件的大寫名稱。
底下來說明一下最主要的幾個變數
<pkg>_SITE
這是這個套件的下載位址,有可能是http(s)或是ftp協定的tarball的位址,或是像是版本管控系統的repo。
<pkg>_VERSION
這個套件的版本,有可能是tarball,最近一次commit或是tag的版本等等。
<pkg>_SOURCE
這個套件的名字,所以跟『<pkg>_SITE』搭起來就會變成『$(<pkg>_SITE)/$(<pkg>_SOURCE)』。
<pkg>_PATCH
在建置套件之前如果有patch需要套用的話,可以由這邊去定義,patch的套用有兩種方式,一個就是在這邊定義,另一種就是只要副檔名是『.patch』,而且是跟這個『.mk』同一個路徑的話,就會自動套用。
<pkg>_EXTRA_DOWNLOADS
如果有一些其他的檔案在建置過程中會用到的話,可以在這邊定義,系統會幫你自動下載,然後你自己必須去定義如何使用它。
如之前已經列過的,buildroot可以支援的下載協定/方式如下:
- wget, 使用FTP/HTTP的方式。
- scp, 使用SSH/SCP來取得。
- svn, 給Subversion系統用的。
- cvs, 給CVS用的。
- git, 給Git用的。
- hg, 給Mercurial用的。
- bzr, 給Bazaar用的。
- file, 如果你的tarball是在本地端的話。
- local, 本地端的資料夾。
預設的話,下載方式都是用『 <pkg>_SITE』變數,但是如果像是Git,SVN或是Mercurial這些用HTTP或是SSH來存取的方式,或是套件在本地端的話就必須特別指定『 <pkg>_SITE_METHOD』。
底下是兩個free-electrons舉的例子:
CJSON_VERSION = 58
CJSON_SITE_METHOD = svn
CJSON_SITE = http://svn.code.sf.net/p/cjson/code
MYAPP_SITE = $(TOPDIR)/../apps/myapp
MYAPP_SITE_METHOD = local
第一個是通過HTTP來存取svn的repo,第二個例子就是存取本地端資料夾。
File integrity checking
因為buildroot的套件大多都是用網路下載,只要在下載過程有一點差錯,就會造成專案建置失敗,所以為了確保至少套件下載到主機時是正確的,所以buildroot也提供了『 <package>.hash』的機制,來驗證檔案的完整性。
每當這個被下載的的套件被使用時,buildroot都會去檢查這個hash,如果比對出來的值跟這個hash table不一樣時,就會嘗試重新下載,下載失敗就會停止建置。
Package dependencies
剛剛在介紹『Config.in』時已經有介紹過『select』和『depends on』,這兩個只能描述相依性但是不能夠保證建置順序,假設你希望在建置某個套件A之前,能夠把其他相依性的套件B,C,D都給建置好,這樣才拿的到相對應的函式庫之類的,你就必須要使用『 <pkg>_DEPENDENCIES』這個變數。
看個『python.mk
』的例子:
PYTHON_DEPENDENCIES = host-python libffi
ifeq ($(BR2_PACKAGE_PYTHON_READLINE),y)
PYTHON_DEPENDENCIES += readline
endif
上面這個例子就是你要建置python之前,你必須要先建置host-python和libffi,如果有啟動readline的話,也要先建置readline。所以host-python和libffi就是必備的相依性( Mandatory dependency),而readline就是選擇性的相依性(Optional dependency),必備相依性就是只要你需要這個套件,他就一定會去建置,但是選擇性相依性就是你必須要開這個開關才會去建置,最好是使用sub-option的方式,就像下面這個例子一樣:
package/mpd/Config.in
menuconfig BR2_PACKAGE_MPD
bool "mpd"
depends on BR2_INSTALL_LIBSTDCPP
[...]
select BR2_PACKAGE_BOOST
select BR2_PACKAGE_LIBGLIB2
select BR2_PACKAGE_LIBICONV if !BR2_ENABLE_LOCALE
[...]
config BR2_PACKAGE_MPD_FLAC
bool "flac"
select BR2_PACKAGE_FLAC
help
Enable flac input/streaming support.
Select this if you want to play back FLAC files.
package/mpd/mpd.mk
MPD_DEPENDENCIES = host-pkgconf boost libglib2
[...]
ifeq ($(BR2_PACKAGE_MPD_FLAC),y)
MPD_DEPENDENCIES += flac
MPD_CONF_OPTS += --enable-flac
else
MPD_CONF_OPTS += --disable-flac
endif
可以看到在『Config.in』裡面有個sub-option叫做『BR2_PACKAGE_MPD_FLAC』,通常這個選項都是會由使用者使用menuconfig主動的去打開,然後在『.mk』時就會讀到,然後建置。
這邊總結一下,總而言之就是主要的相依性要使用『select』和『depends』,如果要強調順序的話,就在使用『<pkg>_DEPENDENCIES』去描述。
Configure and build
剛剛在前兩章有描述過『generic-package』的架構,它只會對套件進行下載,解壓縮和套用patch,至於其他行為,都要由你自行去定義,像是剛剛的相依性等一下要介紹的組態,建置和安裝等等。
- <pkg>_CONFIGURE_CMDS
這個變數會定義這個套件在編譯之前怎麼去設定組態。 - <pkg>_BUILD_CMDS 這個變數定義怎麼去編譯這個套件。
Installation
上面介紹過『.mk』的幾個重要的變數,還有相依性,最後當然是講解一下,建置完的安裝相關變數。
對於target套件建置完後,你有三種位置可以選擇安裝,
- $(TARGET_DIR)
這個資料夾就是會變成target board的root filesystem。 - $(STAGING_DIR) 編譯器的sysroot。
- $(BINARIES_DIR) 最後的映像檔位置。
除了上面的變數以外,還有其他三種搭配:
- 如果 『<pkg>_INSTALL_TARGET』為yes,則『<pkg>_INSTALL_TARGET_CMDS』會被呼叫。
- 如果『<pkg>_INSTALL_STAGING』為yes,則『<pkg>_INSTALL_STAGING_CMDS』會被呼叫。
- 如果『<pkg>_INSTALL_IMAGES』為yes,則『<pkg>_INSTALL_IMAGES_CMDS』會被呼叫。
上面點出了這幾個安裝的變數,位置和呼叫關係,底下則說明了在什麼狀況之下要怎麼去使用上面的搭配:
安裝到target board的軟體套件
只安裝到『$(TARGET_DIR)』就好,因為『<pkg>_INSTALL_TARGET』本身就預設為yes,所以不用修改什麼。動態函式庫(shared library)的套件
必須安裝到 『$(TARGET_DIR)』 和『 $(STAGING_DIR)』,必須設定『<pkg>_INSTALL_STAGING』 = yes。純標頭檔(pure header-based)的函式庫或是靜態函式庫( static-only)套件
只安裝到『$(STAGING_DIR)』,必須設定『<pkg>_INSTALL_TARGET= NO』和『<pkg>_INSTALL_STAGING = YES』。安裝在bootloader或是kernel的套件
只安裝到『$(BINARIES_DIR)』,必須設定『<pkg>_INSTALL_IMAGES = YES』。
其他有用的變數:
- $(@D) 代表目前這個套件的source資料夾。
- $(MAKE) 理論上預設是呼叫make。
- $(MAKE1) 如果這個套件不支援parallel building的話,就會被重新分配到這個$(MAKE1)。
- $(TARGET_MAKE_ENV)
- $(HOST_MAKE_ENV) 這邊要傳你的PATH進去,這樣$(MAKE)才會抓到你的設定。
- $(TARGET_CONFIGURE_OPTS)
- $(HOST_CONFIGURE_OPTS) 其他的Flag參數要在這邊傳入,eg. CC, LD, CFLAGS...。