在编写Yocto recipe的时候,可能会用到其他recipe的文件。这里简单总结一下recipe之间共享文件的几种方法,以及使用过程中遇到的问题。
¶方法一:DEPENDS
这种方法是最常用的,也是最推荐使用的。假设foo.bb安装了${D}${includedir}/foo.h。
1 | # foo.bb |
而bar.bb需要用到foo.h,那么只需要在bar.bb加上DEPENDS += 'foo',那么bar.bb就能使用foo.h了。
1 | # bar.bb |
简简单单一句DEPENDS,yocto在背后做了很多工作。下面来追以下yocto是如何实现的。
¶准备共享文件do_populate_sysroot
首先,foo.bb要准备好共享给其他recipe的文件,这一步由foo.bb的do_populate_sysroot任务完成。这个任务会复制文件到SYSROOT_DESTDIR目录(即${WORKDIR}/sysroot-destdir)。简单看一下这个任务的实现,首先会调用函数sysroot_stage_all,这个函数会完成实际的复制动作;然后调用sysroot_strip,会对ELF文件做strip;SYSROOT_PREPROCESS_FUNCS注册了一些预处理的函数,如果想对共享的文件做一些个性化处理,可以向这个变量注册函数;最后是BB_MULTI_PROVIDER_ALLOWED(不知道有啥用)。
1 | def do_populate_sysroot(d): |
关键是函数sysroot_stage_all,这个函数会将${D}下面的文件复制到${SYSROOT_DESTDIR}。当然,不是所有的文件都会复制,只会复制${SYSROOT_DIRS}变量列出的目录,还会删除${SYSROOT_DIRS_IGNORE}变量列出的目录。
1 | sysroot_stage_dir() { |
下面是SYSROOT_DIRS和SYSROOT_DIRS_IGNORE变量的默认值。所以如果没有把文件安装到SYSROOT_DIRS包含的目录,或者把文件安装到了SYSROOT_DIRS_IGNORE列出的目录,那么其他的recipe就拿不到文件。
1 | SYSROOT_DIRS = " \ |
¶获取共享文件do_prepare_recipe_sysroot
do_prepare_recipe_sysroot任务会根据DEPENDS变量,将文件安装到STAGING_DIR_HOST目录或STAGING_DIR_NATIVE目录。
Installs the files into the individual recipe specific sysroots (i.e. recipe-sysroot and recipe-sysroot-native under ${WORKDIR} based upon the dependencies specified by DEPENDS). See the “staging” class for more information.
这个任务的实现比较复杂,看不太懂。
¶kernel.bbclass
需要注意的是,kernel.bbclass将SYSROOT_DIRS变量清空了。这意味其他recipes拿不到kernel recipe安装到${D}下面的文件(被坑了一把,一度怀疑人生)。
1 | # We don't need to stage anything, not the modules/firmware since those would clash with linux-firmware |
在yocto 4.0.6之前,是重写了sysroot_stage_all函数。
1 | # We don't need to stage anything, not the modules/firmware since those would clash with linux-firmware |
¶方法二:work-shared
work-shared目录在${TMPDIR}/work-sahred,一般情况下是build/tmp/work-sahred。recipe可以将文件安装到此目录下,其他recipe就可以在此路径下拿到文件。从Yocto文档看,只用于gcc及其变种,但这个限制不是强制的。
4.2.24 build/tmp/work-shared/
For efficiency, the OpenEmbedded build system creates and uses this directory to hold recipes that share a work directory with other recipes. In practice, this is only used for gcc and its variants (e.g. gcc-cross, libgcc, gcc-runtime, and so forth).
¶方法三:DEPLOY_DIR_IMAGE
与work-shared目录类似,也是recipe安装文件到DEPLAY_DIR_IMAGE目录,其他recipe通过此目录读取。
DEPLOY_DIR_IMAGE
…
Instead, it’s only useful when a recipe needs to “read” a file already deployed by a dependency.
¶总结
通过DEPENDS可以很方便的拿到其他recipe安装到${D}目录的文件。但要注意SYSROOT_DIRS和SYSROOT_DIRS_IGNORE变量,一个控制什么目录会共享,一个控制什么目录不会共享。通过检查${SYSROOT_DESTDIR}可以确认共享给其他recipe的文件。
此外,还能通过work-shared和DEPLOY_DIR_IMAGE目录拿到其他recipe安装的文件。