1、每個菜譜在其工作目錄中都有兩個sysroot,一個用於目標文件(recipe-sysroot),一個用於構建主機的本地文件(recipesysroot-native).
recipe-sysroot的文件是目標系統架構(arm)
recipe-sysroot的文件是構建主機架構(x86)
2、菜譜不能直接填充sysroot目錄
應該在${D}目錄中的do_install任務期間將文件安裝到標准位置
3、可以通過修改SYSROOT_DIRS來修改要填充到sysroot的目錄列表
SYSROOT_DIRS變量定義,do_populate_sysroot任務將使用do_install任務安裝的文件的子集來自動填充sysroot
例如將opt目錄添加到目錄列表里
SYSROOT_DIRS += "opt"
4、virtual 提供程序
在構建之前,如果您知道幾種不同的菜譜提供相同的功能,則可以使用虛擬提供程序(即virtual/*)作為實際提供程序的占位符,實際的提供者是在構建時確定。
使用虛擬提供程序的常見方案是內核recipes ,假如有3個內核菜譜:PN值分別為 kernel-big、kernel-mid、kernel-small,
這3個菜譜都使用PROVIDES將自己標識為能夠提供virtual/kernel
5、內核類提供virtual/kernel的方法
PROVIDES += "${@"virtual/kernel"if (d.getVar("KERNEL_PACKAGE_NAME") == "kernel") else""}"
繼承內核類的任何菜譜都可以利用PROVIDES語句,表面自己能夠提供virtual/kernel項目.
6、構建鏡像需要指定內核菜譜,怎么確定用哪個內核菜譜呢?
使用PREFERRED_PROVIDER 指定哪個菜譜,使用PREFERRED_VERSION 指定菜譜的版本
一個例子:/meta/conf/machine/include/x86-base.inc
PREFERRED_PROVIDER_virtual/kernel ??= "linux-yocto" PREFERRED_VERSION_linux-yocto ??= "5.2%"
另一個例子:meta-ti/conf/machine/include/ti33x.inc
PREFERRED_PROVIDER_virtual/kernel = "linux-ti-staging" PREFERRED_PROVIDER_virtual/bootloader = "u-boot-ti-staging" PREFERRED_PROVIDER_u-boot = "u-boot-ti-staging"
7、當菜譜需要使用virtual提供的依賴項時,不必硬編碼需要依賴的菜譜名稱,可以使用DEPENDS變量來聲明菜譜構建依賴於virtual/kernel
DEPENDS = "virtual/kernel"
8、在構建最終鏡像期間, OpenEmbedded構建系統將根據PREFERRED_PROVIDER變量選擇virtual/kernel依賴所需的正確recipes
如果要使用kernel-small內核,則可以用下面的方式配置構建環境選擇的菜譜
PREFERRED_PROVIDER_virtual/kernel ??= "kernel-small"
9、如果沒有被PREFERRED_PROVIDER選擇的PROVIDES virtual/* 項目的任何菜譜都不會生成,這提供了選擇內核菜譜的機制
10、菜譜發布前需要正確設置版本
例如:irssi_0.8.16-rc1.bb此菜譜處於候選發布階段(rc1),當正式發布時菜譜更名為irssi_0.8.16.bb
版本從irssi_0.8.16-rc1.bb -> irssi_0.8.16.bb 被看作是構建系統和包管理器的下降,因此產生的程序包將無法正確地觸發升級
為了確保版本比較正確,建議的慣例是將菜譜中的PV
設置為 “previous_version +
current_version
”。
您可以使用其他變量,以便可以在其他地方使用當前版本。這是一個例子
REALPV = "0.8.16-rc1" PV = "0.8.15 +${REALPV}"
11、postinst 腳本
主要完成軟件包(eg ".deb")安裝完成后所需的配置工作。安裝程序在目標上安裝程序包之后postinst 腳本立即運行。
要向軟件包中添加安裝后腳本,請將pkg_postinst_PACKAGENAME()函數添加到菜譜文件(.bb),然后將PACKAGENAME替換為您要附加到postinst 腳本的軟件包的名稱。
要將安裝后腳本應用於菜譜的主軟件包(通常必需的),請指定用${PN}代替PACKAGENAME.
postinst 格式
pkg_postinst_PACKAGENAME(){ #行執創建根文件系統的命令時,將調用postinst功能中定義的腳本.如果腳本成功,則將該軟件包標記為已安裝.如果腳本失敗,則將包標記為已解壓縮,並在再次引導映像時執行腳本. }
有時有必要將postinst腳本的執行延遲到首次啟動之前。例如,腳本可能需要在設備本身上執行。若要將腳本執行延遲到啟動時間,則必須顯式標記postinst才能推遲到目標設備。
您可以使用pkg_postinst_ontarget()或
從pkg_postinst()調用 postinst-intercepts defer_to_first_boot,pkg_postinst()
腳本的任何失敗(包括 exit 1)都會在do_rootfs
任務執行期間觸發錯誤.
如果您擁有使用pkg_postinst
功能的菜譜, 並且他們需要使用非標准本機工具,這些工具在rootfs構造過程中具有依賴性,則需要在菜譜中使用PACKAGE_WRITE_DEPS
變量來列出這些工具。
如果不使用此變量,則可能會缺少工具,並且postinst腳本的執行將推遲到首次啟動時執行。將腳本推遲到第一次啟動是不希望的,並且對於只讀rootfs是不可能的。
注意:通過pkg_preinst, pkg_prerm和pkg_postrm分別存在對預安裝,預卸載和后卸載腳本的等效支持。這些腳本與pkg_postinst的工作方式完全相同, 不同的是它們在不同的時間運行
另外,由於它們不同的運行時間,它們不適用於在映像創建時像pkg_postinst一樣運行。
12、使用本地文件的菜譜文件3中情況
12.1、使用單個hello.c文件
從本地存儲的單個文件(例如,在files下)構建應用程序需要菜譜包含SRC_URI
變量中列出的文件 。此外,您需要手動編寫 do_compile
和 do_install
任務。
S
變量定義包含源代碼的目錄,在這種情況下,WORKDIR
目錄被設置為 BitBake用於構建的目錄。
SUMMARY = "Simple helloworld application" SECTION = "examples" LICENSE = "MIT" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" SRC_URI = "file://helloworld.c" S = "${WORKDIR}" do_compile() { ${CC} helloworld.c -o helloworld } do_install() { install -d ${D}${bindir} install -m 0755 helloworld ${D}${bindir} }
默認情況下,helloworld,
helloworld-dbg,
helloworld-dev 包會被構建
12.2、自動工具包
使用 Autotools 的應用程序(例如:autoconf 和
automake
)需要一個在SRC_URI中列出了源歸檔文件的菜譜,並且該菜譜還繼承了autotools類,該類包含構建基於Autotool的應用程序所需的所有步驟的定義
構建結果將自動打包。並且,如果應用程序使用NLS進行本地化,則會生成帶有本地信息的程序包(每種語言一個程序包)。
以下是一個示例:(hello_2.3.bb
)
SUMMARY = "GNU Helloworld application" SECTION = "examples" LICENSE = "GPLv2+" LIC_FILES_CHKSUM = "file://COPYING;md5=751419260aa954499f7abaabaa882bbe" SRC_URI = "${GNU_MIRROR}/hello/hello-${PV}.tar.gz" inherit autotools gettext
12.3、基於Makefile的軟件包
使用GNU make的應用程序還需要一個菜譜,該菜譜的源歸檔文件列在SRC_URI中。不需要添加do_compile設置,因為默認情況下BitBake啟動make命令來編譯應用程序。
如果需要其他make屬性, 則應將其存儲在EXTRA_OEMAKE或PACKAGECONFIG_CONFARGS變量中。BitBake將這些選項傳遞到GNU make調用中。
注意, 仍然需要do_install任務。否則,默認情況下BitBake運行一個空的do_install任務.。
某些應用程序可能需要額外的參數才能傳遞給編譯器。例如,應用程序可能需要附加頭文件路徑,您可以通過添加到CFLAGS變量來完成此操作.
下面的示例顯示了這一點:
CFLAGS_prepend = "-I ${S}/include "
在下面這個例子中,mtd-utils是一個makefile-base的包
SUMMARY = "Tools for managing memory technology devices" SECTION = "base" DEPENDS = "zlib lzo e2fsprogs util-linux" HOMEPAGE = "http://www.linux-mtd.infradead.org/" LICENSE = "GPLv2+" LIC_FILES_CHKSUM = "file://COPYING;md5=0636e73ff0215e8d672dc4c32c317bb3 \ file://include/common.h;beginline=1;endline=17;md5=ba05b07912a44ea2bf81ce409380049c" # Use the latest version at 26 Oct, 2013 SRCREV = "9f107132a6a073cce37434ca9cda6917dd8d866b" SRC_URI = "git://git.infradead.org/mtd-utils.git \ file://add-exclusion-to-mkfs-jffs2-git-2.patch \ " PV = "1.5.1+git${SRCPV}" S = "${WORKDIR}/git" EXTRA_OEMAKE = "'CC=${CC}' 'RANLIB=${RANLIB}' 'AR=${AR}' 'CFLAGS=${CFLAGS} -I${S}/include -DWITHOUT_XATTR' 'BUILDDIR=${S}'" do_install () { oe_runmake install DESTDIR=${D} SBINDIR=${sbindir} MANDIR=${mandir} INCLUDEDIR=${includedir} } PACKAGES =+ "mtd-utils-jffs2 mtd-utils-ubifs mtd-utils-misc" FILES_mtd-utils-jffs2 = "${sbindir}/mkfs.jffs2 ${sbindir}/jffs2dump ${sbindir}/jffs2reader ${sbindir}/sumtool" FILES_mtd-utils-ubifs = "${sbindir}/mkfs.ubifs ${sbindir}/ubi*" FILES_mtd-utils-misc = "${sbindir}/nftl* ${sbindir}/ftl* ${sbindir}/rfd* ${sbindir}/doc* ${sbindir}/serve_image ${sbindir}/recv_image" PARALLEL_MAKE = "" BBCLASSEXTEND = "native"
13、將應用程序拆分為多個程序包
可以使用變量PACKAGES和FILES將應用程序拆分為多個程序包
以下是使用libxpm
配方的示例。默認情況下,此配方會生成一個包含程序庫和一些二進制文件的包
require xorg-lib-common.inc SUMMARY = "Xpm: X Pixmap extension library" LICENSE = "BSD" LIC_FILES_CHKSUM = "file://COPYING;md5=51f4270b012ecd4ab1a164f5f4ed6cf7" DEPENDS += "libxext libsm libxt" PE = "1" XORG_PN = "libXpm" PACKAGES =+ "sxpm cxpm" FILES_cxpm = "${bindir}/cxpm" FILES_sxpm = "${bindir}/sxpm"
在這個的示例中,我們希望將sxpm
和cxpm
二進制文件分別打包。由於 默認情況下bindir
會打包到主程序 PN
包中,因此我們在PACKAGES
變量之前加上了前綴,以便將其他程序包名稱添加到列表的開頭。
這將導致FILES_*
變量定義哪些文件和目錄被包含進哪些程序包的信息。較早版本的軟件包包含的文件被較早版本的軟件包跳過。因此,主PN
軟件包不包括上面列出的文件。
14、打包外部生成的二進制文件
有時,您需要向鏡像中添加預編譯的二進制文件。例如,假設存在專有代碼的二進制文件,這些二進制代碼是由公司的特定部門創建的。
公司需要將這些二進制文件用作要使用OpenEmbedded構建系統構建的映像的一部分。
因為您只有二進制文件,而沒有源代碼,所以您不能使用期望獲取SRC_URI中指定的源,然后進行編譯的典型菜譜.
14.1、一種方法是打包二進制文件,然后將其安裝為映像的一部分。通常,打包二進制文件不是一個好主意,因為,它可能會阻礙復制生成文件的能力,並可能導致將來與ABI的兼容性問題。但是,有時您別無選擇
14.2、最簡單的解決方案是創建一個使用bin_package類的菜譜,並確保您使用默認位置生成構件
在大多數情況下,bin_package
該類負責“跳過”配置和編譯步驟,並進行設置以從適當的區域獲取軟件包。
特別是bin_pacgage這個類在do_configure
和 do_compile 任務中都設置
noexec。
設置
FILES_${PN}為
"/" 以便他選擇所有的文件,並設置一個do_install任務,該任務將所有文件從${S}復制到${ D}
當提取到${S}中的文件已經按照應在目標上的布局方式進行布局時, bin_package類可以很好地工作
14.3、如果無法使用bin_package類,則需要確保您執行以下操作
14.3.1、創建一個菜譜,使其中do_configure和do_compile任務不起作用:
通常只要不在菜譜中定義這些任務就足夠了,因為除非在$(S}中找到Makefile,否則默認實現不執行任何操作
如果${S}可能包含一個Makefile,或者你繼承了一個用自定義版本替換do_configure和do_compile的類,那么你可以使用[
noexec
]標志,將任務轉變為(no-ops)無操作
如下所示:
do_configure[noexec] = "1" do_compile[noexec] = "1"
14.3.2、與 deleting the tasks 任務不同,noexec標志會將依賴關系鏈從do_fetch, do_unpack和do_patch任務保留到do_install任務
14.3.3、確保您的do_install任務正確安裝了二進制文件
14.3.4、確保您將FILES(通常是FILES_${PN})設置為指向已安裝的文件,這當然取決於安裝它們的位置以及這些文件是否位於默認位置之外的其他位置
15、菜譜的語法
https://www.yoctoproject.org/docs/3.0.2/mega-manual/mega-manual.html#bitbake-user-manual-metadata