Yocto实用技巧

转载自:https://www.kancloud.cn/digest/yocto/138623

相当详细的文章就是转运一下,方便大家阅读,原版文章可以看原链接。

对于大家使用Yocto中的一些疑问,使用寥寥数语进行解答,让大家快速高效地使用Yocto。

(1): Yocto 编译后文件放在了哪里 输出文件位置

编译完成后内核以及rootfs,内核,uboot以及dtb会放在相对于build目录的tmp/deploy/images/MACHINE/下面,这里MACHINE需要可能为空(对于老版本的poky/yocto),也可能是你的板子名字,例如sabresd。

对于toolchain,那么放在mp/deploy/sdk/MACHINE/下。

图片示例:

编译完成后内核以及rootfs以及dtb会放在相对于build目录的tmp/deploy/images/imx6qsabresd/下面

各个文件都有一个软连接来指向最新编译产生的文件,因此如果需要看到最新的文件,可以直接使用软链接即可:

(2): Yocto Linux内核编译目录在哪?

内核放在了哪里? 这个是放在了如下位置,我们可以用下面命令来确定:

bitbake -e linux-imx  | grep ^S=

图示:

(3): Yocto 如何重新编译Linux内核与dtb,并放到deploy目录?

编译内核,并生成uImage+dtb,编译的命令如下:

bitbake linux-imx -C compile

注意这里的-C的C是大写,和小写的c是有区别的。

注意这里的linux-imx是针对imx的内核,你的内核名字可能不一样,关于如何确定一个包的名字,请看:Yocto tips (4): Yocto 如何确定(找到)

(4): Yocto 如何确定(找到)一个包的名字

使用下面命令来却确定:

bitbake -s | grep XXX

其中XXX为包的关键字,例如linux或者uboot,这样就可以看到所有带有关键字的包了,如下图,就是为了找到内核:

(5): Yocto如何更改source code的下载与git clone地址

现象

Yocto中在fetch一些软件包的时候经常出现一天也下载不下来,这种情况极大浪费了我们的时间。

例如,下面有三个Package下载了一天也没有完成:

解决方法

确定下载的地址,手动下载

先确定软件包的下载地址,例如对于opencv与opencv-samples软件包:

可以看到他们的git地址都是一样的,因此,我们可以手动来git clone:

可以看到我们只使用了几十分钟而已。clone下来以后,我们就可以让软件包使用我们本地的这个repo了,而不需要忙忙的去远程repo去clone。

让package克隆时使用本地的git

找到软件包对应的bb文件

我们可以使用find命令来查找

更改bb文件

注意里面添加了一个protocol指定。

再一次获取

bitbake opencv -c fetch

结果如下:

提示找不到branch,于是我们到我们本地的repo中将此branch切出来,也可以将其制作成bare repo:

然后再一次进行fetch就可以了:

对于其他软件也是类似的。

(6): Yocto中如何共享已经下载的文件

Yocto的下载耗时可能会超过编译的时间,因此大家都希望下载一次后大家都用共用下载好了的文件,而不要再去下载。

Yocto中所有下载了的以及git clone的文件都放在环境变量DL_DIR指示的目录下,这个目录默认在machine build directory下面。

因此要共享下载文件只需要指定此变量到下载好了的目录即可,可以在local.conf中指定即可:

(7): Yocto Bitbake的clean与cleanall以及cleansstate的区别

Yocto中对于不同的Package,有不同的task,即可以执行不同的操作,有一些是所有包共通的,例如clean,build等。

我们可以使用下面命令来查看一个包都有哪些可执行的task:

bitbake Package -c listtasks

图示:

我们可以从里面看到clean与cleanall以及cleansstate的区别。

(8): Yocto 如何加快软件包的下载 如何只下载所有需要的软件包而不编译

加快下载

Yocto中下载是最耗时的,因此我们可以尽可能的开启最多的并行数量。

对此,我们可以在local.conf中将并行数目调大,例如我的CPU 是E3-1230 v2, 8核,所以我可以开启16个线程来下载,因为我们的网速慢,所以其实这些下载操作并非CPU密集型任务,很多包也很小,所以同时IO也不密集,因此可以适当调大:

效果如下:

下载所有需要的软件包而不编译

有的时候我们可能需要先将所有需要的软件包下载下来,等离线回家或者其他时机再编译,对此我们可以使用如下命令来完成:

bitbake fsl-image-qt5 -c fetchall

对于不同的目标,需要替换fsl-image-qt5为其他的,例如可能是core-image-minimal,我们可以看到fetchall的意义:

do_fetchall                    Fetches all remote sources required to build a target

(9): Yocto 软件包的下载地址在哪

一般而言,可以使用Yocto tips (5): Yocto如何更改source code的下载与git clone地址中提到的方法,但是有的时候一些地址是在bb文件include的文件中,而inc文件又可能层层包含,查找比较繁琐,因此直接到env中查找比较快。

例如要找到imx kenrel的fetch地址可以使用下面命令:

bitbake -e linux-imx | grep ^SRC_URI=

效果如下:

(10): Yocto hellworld 添加一个软件包

Yocto中一个软件包是放在bb文件中的,然后很多的bb文件集成一个recipe(配方),然后许多的recipe又组成一个meta layer,因此,要添加一个包其实就是在recipe下面添加一个bb(bitbake配置文件)。下面使用helloworld作为一个例子。

clone bb文件

首先是进入到一个recipe目录下,例如下面就是到了recipes-graphics:

$ pwd
/media/work/iMX6/Yocto/sources/meta-fsl-arm/recipes-graphics

然后clone Package配置与source目录的repo:

git clone https://github.com/tonyho/helloYocto.git

查看软件包是否已经在Yocto中

09:25 hexiongjun:imx6qsabresd_build $ bitbake -s | grep hello
hello                                                   :3-r0

确认在了以后,就可以执行编译等task了,如果有需要也可以deploy到rootfs中,这些操作可以参考我以前的一些博客。

一个软件包的结构

使用tree可以看到,其有一个bb文件,然后其中还有一个目录放着Makefile与source code:

其中的bb文件内容如下:

DESCRIPTION = "Hello World and Zlib test"
DEPENDS = "zlib"
SECTION = "libs"
LICENSE = "MIT"
PV = "3"
PR = "r0"

SRC_URI = " \
          file://helloYocto.c \
          file://zlibtest.c \
          file://makefile \
          "

LIC_FILES_CHKSUM = "file://helloYocto.c;md5=2dac018fa193620dc085aa1402e0b346"
S = "${WORKDIR}"
do_compile () {
    make
}

do_install () {
	install -d ${D}${bindir}/
	install -m 0755 ${S}/helloYocto ${D}${bindir}/
	install -m 0755 ${S}/zlibtest ${D}${bindir}/
}

FILES_${PN} = "${bindir}/helloYocto \
               ${bindir}/zlibtest "

可以看到,bb文件中指定了下面几个变量的值:

  1. SRC_URI
  2. LIC_FILES_CHKSUM:这个是checksum,如果是基于版本管理的source,那么不需要,例如git与svn
  3. FILES_$(PN):PN是Package number,指代软件版本使用的PV与PR结合表示,即前面bitbake -s中看到的3-r0

还有两个方法,这2个方法重载了bitbake中默认方法:

  1. do_compile
  2. do_install

这两个方法,对应了Package中的compile与install task。

(11): Yocto如何往最终的rootfs中添加软件

在Yocto中如果我们期望在rootfs中添加一些软件,例如可能是bash,可能是lsusb等,那么,我们可以有两种方法:

  1. 手动添加,一个个文件的拷贝
  2. 在bb文件中添加安装项目,让Yocto自动帮助我们添加

第一种方法需要手动将软件包的所有文件以及依赖都一个个添加进去,耗时耗力且易错,因此使用第二中方法比较合适。

Yocto中Rootfs中添加软件包的步骤

找到打包rootfs的最终bb

如果我们使用的是下面命令:

bitbake fsl-image-qt5

那么,我们可以按照如下来搜索fsl-image-qt5这个软件包(任务),使用的是哪个bb文件:

添加需要安装到rootfs的软件包

然后打开,并添加需要添加的包即可,例如下面添加的是linux-firmware:

保存,然后我们再一次使用bitbake构建系统,然后就可以看到rootfs中有对应的文件了:

(12): 使用Yocto帮组我们寻找难找的固件与固件放置路径

有很多的硬件需要firmware才能工作,而这些firmware需要不仅仅需要找到,还需要放置到正确的位置,一般这个位置是/lib/firmware下面,但是很多也不尽然。

手动去查找这些固件,容易出现遗漏或者混淆,也有可能是年久不匹配了的固件,例如在我前面的博客中:Yocto i.MX6 (TQIMX6) (02) : USB Wifi (TP-Link WN821N等设备)AR9170的Linux内核支持与固件使用,就出现了自己按照wiki与help去查找firmware,结果却花了大量时间也没有解决,而使用yocto中的linux-firmware软件包,非法快速的解决了这个问题。

对于firmware放置的path也是类似,例如有些驱动放置的path为非标准的path,例如下面这些都是放在各自的目录中的:

因此,直接将linux-firmware添加到打包rootfs,或者直接查看linux-firmware中的image文件夹就可以知道path了,例如前面的ar9170:

(13): Yocto 查看软件包的依赖关系

查看一个文件包的依赖,我们可以使用图形化来查看,下面是一些官方说明:

例如我们要查看weston的依赖:

bitbake --ui=depexp -g weston或者 bitbake -g  -u depexp  weston

这个会列出不同的依赖,例如中间的是编译时候需要依赖的东西,结果如下:

(14): Yocto中编译链的配置变更(tuning)

这个在我们自己编译toolchain以及针对不同的硬件自己调整toolchain的时候用得多。变更方法也很简单,只需要在poky对应的配置查找一个合适的即可。

例如针对armv7而言,我们可以到下面文件查找一个合适的来使用:

将自己选择好的写入到local.conf中:

(15): Yocto中的包管理器

使用包管理器

在local.conf中使能即可:

然后编译后就会有rpm包了:

配置文件服务器

可以使用ngix和apache,但是我们也可以只用使用python:

python -m SimpleHTTPServer

打开浏览器可以看到:

在机器上面查看包的status

smart status


在机器上面配置channel

对于rpm使用的smart工具,添加channel:

smart channel --add all type=rpm-md baseurl=http://192.168.2.100:8000/all
smart channel --add  cortexa9hf_vfp_neon  type=rpm-md baseurl=http://192.168.2.100:8000/cortexa9hf_vfp_neon 
smart channel --add cortexa9hf_vfp_neon_mx6qdl type=rpm-md baseurl=http://192.168.2.100:8000/cortexa9hf_vfp_neon_mx6qdl
smart channel --add imx6qsabresd type=rpm-md baseurl=http://192.168.2.100:8000/imx6qsabresd

添加参数之后,就可以update了:

smart update

正确的是下面命令的情形:

如果配置参数不对,那么就会出错,如果出错,那么检查IP与格式是否正确,例如下面的http少了两个//:

如果弄错了,那么可以先移除掉:

smart channel --remove all cortexa9hf_vfp_neon_mx6qdl imx6qsabresd cortexa9hf_vfp_neon

然后重新添加。

再看包的数量,可以看到变多了:

使用包管理器安装软件

使用smart install Package即可安装:

如果在PC中使用bitbake新编译了程序,那么需要使用下面命令重建index,否则客服端找不到新的软件包:

bitbake package-index

参考:

http://www.jumpnowtek.com/yocto/Using-your-build-workstation-as-a-remote-package-repository.html

package-manager-white-paper.pdf

(16): Yocto 制作SDK分发Toolchain 脱离Yocto环境开发

Yocto中SDK有两种:

  1. 只有Toolchain,或者Toolchain+某类GUI特性
  2. 有针对某个Distribution的SDK,即含有Toolchian也含有这个Distrbutition特殊的文件

下面分别说明。

第一类

这类的软件包有如下这些:

其实就是两类:

  1. meta-toolchain
  2. meta-toolchain-qt/qte/qt5

后者包含了qt相关的东西,qte是面向embed的,如果需要做qt相关的application开发,那么包含qt的是合适的选择,否则仅仅开发普通application,那么使用meta-toolchian即可。

第二类

这类SDK才是推荐使用的,这个在distribution的task中有一个特别的任务,专门用来制作这个SDK,叫做populate_sdk,例如对应要制作一个fsl-image-qt5 目标的Distribution(也叫做image),那么可以这样子:

bitbake fsl-image-qt5 -c populate_sdk

这两类制作完成后,可以在deploy中看到了:

其中xml文件是SDK包含了的文件列表。

SDK的安装

因为SDK文件是sh脚本+压缩的文件内容组成的,所以直接运行即可,例如:

在prompt提示中,输入安装的路径。

(17): Yocto License问题:restricted license not whitelisted in LICENSE_FLAGS_WHITELIST

Yocto中可以配置一个Distrbution的License,然后所有的软件包,都需要符合这个license才可以被shipped到image中,如果我们需要使用违反此license的软件包,那么就需要额外配置。

例如,在bitbake编译vlc的时候出现下面的错误log:

$ bitbake vlc
Parsing recipes: 100% |###################################################################################################################################| Time: 00:00:26
Parsing of 2029 .bb files complete (0 cached, 2029 parsed). 2524 targets, 210 skipped, 1 masked, 0 errors.
NOTE: Resolving any missing task queue dependencies
ERROR: Nothing PROVIDES 'ffmpeg' (but /media/work/iMX6/Yocto/sources/meta-openembedded/meta-multimedia/recipes-multimedia/vlc/vlc_2.1.4.bb DEPENDS on or otherwise requires it)
ERROR: libav PROVIDES ffmpeg but was skipped: because it has a restricted license not whitelisted in LICENSE_FLAGS_WHITELIST
ERROR: libav PROVIDES ffmpeg but was skipped: because it has a restricted license not whitelisted in LICENSE_FLAGS_WHITELIST
ERROR: Required build target 'vlc' has no buildable providers.
Missing or unbuildable dependency chain was: ['vlc', 'ffmpeg']

那么就是因为vlc依赖libav,但是libav,的license不符合Distribution的License而无法编译。在libav中的bb文件配置中,可以看到其license flag为commercial:

开启接受所有的commercial license软件包

因此如果我们需要添加一些commercial Lincense的软件包,就需要添加对commercial的支持,只需要在local.conf中添加一行即可:

LICENSE_FLAGS_WHITELIST="commercial"

只接受特定的commercial license软件包

但是如果我们只期望某些特殊的commercial软件包可以被编译放入到rootfs中,那么我们就需要逐个指定,例如指定libav等包可以被编译:

(18): Yocto SDK Toolchian中静态库的添加

Toolchian中静态库的添加

没有静态库,是无法静态编译应用程序的,因此,为了方便,还需要在SDK中添加静态库,例如libc。

这个特性在只需要开启即可,在local.conf中添加一行:

SDKIMAGE_FEATURES_append = "staticdev-pkgs"

Toolchian中静态库的验证

然后重新build SDK,并安装SDK之后,我们可以验证其是否存在。

首先source env,导入各种bash变量:

source ../qt5_sdk/environment-setup-cortexa9hf-vfp-neon-poky-linux-gnueabi

然后确认libgcc.a是否exist:

$CC -print-file-name=libgcc.a

如果输出的存在,那么就有了,例如:

(19): Yocto SDK Toolchian的使用

在使用之前需要先source env,导入各种环境变量(注意将路径变更成你自己的):

source ../qt5_sdk/environment-setup-cortexa9hf-vfp-neon-poky-linux-gnueabi

然后我们可以查看一下bash的env了,下面是多出来的一些env,直接在bash中输入export即可看到:

declare -x AR="arm-poky-linux-gnueabi-ar"
declare -x ARCH="arm"
declare -x AS="arm-poky-linux-gnueabi-as "
declare -x CC="arm-poky-linux-gnueabi-gcc  -march=armv7-a -mthumb-interwork -mfloat-abi=hard -mfpu=neon -mtune=cortex-a9 --sysroot=/media/work/iMX6/Yocto/qt5_sdk/sysroots
/cortexa9hf-vfp-neon-poky-linux-gnueabi"
declare -x CFLAGS=" -O2 -pipe -g -feliminate-unused-debug-types"
declare -x CONFIGURE_FLAGS="--target=arm-poky-linux-gnueabi --host=arm-poky-linux-gnueabi --build=x86_64-linux --with-libtool-sysroot=/media/work/iMX6/Yocto/qt5_sdk/sysro
ots/cortexa9hf-vfp-neon-poky-linux-gnueabi"
declare -x CONFIG_SITE="/media/work/iMX6/Yocto/qt5_sdk/site-config-cortexa9hf-vfp-neon-poky-linux-gnueabi"
declare -x CPP="arm-poky-linux-gnueabi-gcc -E  -march=armv7-a -mthumb-interwork -mfloat-abi=hard -mfpu=neon -mtune=cortex-a9 --sysroot=/media/work/iMX6/Yocto/qt5_sdk/sysr
oots/cortexa9hf-vfp-neon-poky-linux-gnueabi"
declare -x CPPFLAGS=""
declare -x CROSS_COMPILE="arm-poky-linux-gnueabi-"
declare -x CXX="arm-poky-linux-gnueabi-g++  -march=armv7-a -mthumb-interwork -mfloat-abi=hard -mfpu=neon -mtune=cortex-a9 --sysroot=/media/work/iMX6/Yocto/qt5_sdk/sysroot
s/cortexa9hf-vfp-neon-poky-linux-gnueabi"
declare -x CXXFLAGS=" -O2 -pipe -g -feliminate-unused-debug-types"
declare -x M4="m4"
declare -x MANDATORY_PATH="/usr/share/gconf/kde-plasma.mandatory.path"
declare -x NM="arm-poky-linux-gnueabi-nm"
declare -x OBJCOPY="arm-poky-linux-gnueabi-objcopy"
declare -x OBJDUMP="arm-poky-linux-gnueabi-objdump"
declare -x OECORE_ACLOCAL_OPTS="-I /media/work/iMX6/Yocto/qt5_sdk/sysroots/x86_64-pokysdk-linux/usr/share/aclocal"
declare -x OECORE_DISTRO_VERSION="1.7"
declare -x OECORE_NATIVE_SYSROOT="/media/work/iMX6/Yocto/qt5_sdk/sysroots/x86_64-pokysdk-linux"
declare -x OECORE_SDK_VERSION="1.7"
declare -x OECORE_TARGET_SYSROOT="/media/work/iMX6/Yocto/qt5_sdk/sysroots/cortexa9hf-vfp-neon-poky-linux-gnueabi"
declare -x OLDPWD="/media/work/iMX6/Yocto/video2lcd_arm/test"
declare -x PATH="/media/work/iMX6/Yocto/qt5_sdk/sysroots/x86_64-pokysdk-linux/usr/bin:/media/work/iMX6/Yocto/qt5_sdk/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi:/home/hexiongjun/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/hexiongjun/010editor:/home/hexiongjun/010editor"
declare -x PKG_CONFIG_PATH="/media/work/iMX6/Yocto/qt5_sdk/sysroots/cortexa9hf-vfp-neon-poky-linux-gnueabi/usr/lib/pkgconfig"
declare -x PKG_CONFIG_SYSROOT_DIR="/media/work/iMX6/Yocto/qt5_sdk/sysroots/cortexa9hf-vfp-neon-poky-linux-gnueabi"
declare -x PWD="/media/work/iMX6/Yocto/video2lcd_arm"
declare -x PYTHONHOME="/media/work/iMX6/Yocto/qt5_sdk/sysroots/x86_64-pokysdk-linux/usr"
declare -x QMAKESPEC="/home/hexiongjun/github/BBB/SDK/ti-sdk-am335x-evm-05.07.00.00/linux-devkit/arm-arago-linux-gnueabi/usr/share/qtopia/mkspecs/linux-g++"
declare -x QT_IM_MODULE="fcitx"
declare -x QT_PLUGIN_PATH="/home/hexiongjun/.kde/lib/kde4/plugins/:/usr/lib/kde4/plugins/"
declare -x RANLIB="arm-poky-linux-gnueabi-ranlib"
declare -x SDKTARGETSYSROOT="/media/work/iMX6/Yocto/qt5_sdk/sysroots/cortexa9hf-vfp-neon-poky-linux-gnueabi"
declare -x SESSION_MANAGER="local/hexiongjun-pc:@/tmp/.ICE-unix/3595,unix/hexiongjun-pc:/tmp/.ICE-unix/3595"

注意点

其中我们重点需要关注的是与编译相关的变量:

  1. CC/LD等编译相关
  2. ARCH/CROSS_COMPILE等croos编译相关

可以看到CC已经被重定义为cross toolchain了,而ARCH和CROSS_COMPILE也悉心的帮我们配置成了对应的。

因此,其实如果我们需要交叉编译一个app,那么很多变量将不再需要自己手动设定了。

同时因为各种tuning的指定,我们必须注意和硬件的匹配。例如这里指定了为cortex-a9而优化。

如何使用

最好的方法就是使用变量来使用Toolchian,例如使用$CC而不是使用arm-poky-XXX-gcc,因为我们可以看到CC其实是对arm-xxx-gcc添加了一些配置:

CC="arm-poky-linux-gnueabi-gcc  -march=armv7-a -mthumb-interwork -mfloat-abi=hard -mfpu=neon -mtune=cortex-a9 --sysroot=/media/work/iMX6/Yocto/qt5_sdk/sysroots
/cortexa9hf-vfp-neon-poky-linux-gnueabi"

其中最为核心的是sysroot这个选项,这个选项将告诉toolchian去哪里查找库与头文件,而如果不指定这个,那么就会出现问题,例如,我们直接使用arm-poky-gnueabi-gcc来编译:

$ make
make -C ./ -f /media/work/iMX6/Yocto/video2lcd_arm/Makefile.build
make[1]: Entering directory `/media/work/iMX6/Yocto/video2lcd_arm'
make -C convert -f /media/work/iMX6/Yocto/video2lcd_arm/Makefile.build
make[2]: Entering directory `/media/work/iMX6/Yocto/video2lcd_arm/convert'
arm-poky-linux-gnueabi-gcc -Wall -Werror -O2 -g -I /media/work/iMX6/Yocto/video2lcd_arm/include -I /media/work/iMX6/Yocto/imx6qsabresd_build/tmp/work/imx6qsabresd-poky-linux-gnueabi/fsl-image-qt5/1.0-r0/rootfs/usr/include/ -Wp,-MD,.convert_manager.o.d -c -o convert_manager.o convert_manager.c
In file included from /media/work/iMX6/Yocto/imx6qsabresd_build/tmp/work/imx6qsabresd-poky-linux-gnueabi/fsl-image-qt5/1.0-r0/rootfs/usr/include/features.h:389:0,
                 from /media/work/iMX6/Yocto/imx6qsabresd_build/tmp/work/imx6qsabresd-poky-linux-gnueabi/fsl-image-qt5/1.0-r0/rootfs/usr/include/stdio.h:27,
                 from /media/work/iMX6/Yocto/video2lcd_arm/include/config.h:5,
                 from convert_manager.c:2:
/media/work/iMX6/Yocto/imx6qsabresd_build/tmp/work/imx6qsabresd-poky-linux-gnueabi/fsl-image-qt5/1.0-r0/rootfs/usr/include/gnu/stubs.h:7:29: fatal error: gnu/stubs-soft.h: No such file or directory
 # include <gnu/stubs-soft.h>
                             ^
compilation terminated.
make[2]: *** [convert_manager.o] Error 1
make[2]: Leaving directory `/media/work/iMX6/Yocto/video2lcd_arm/convert'
make[1]: *** [convert] Error 2
make[1]: Leaving directory `/media/work/iMX6/Yocto/video2lcd_arm'
make: *** [all] Error 2

可以看到提示说找不到一些标准的头文件,其实这个是因为我们没有添加一些指定的选择来告诉其使用stubs-hard.h,所以默认的去查找stubs-soft.h。

例如我们编译一个helloworld,那么可以按照如下编译:

$CC hello.c -o hello

这样将省去了诸多选项的手动指定,也不会出问题。

猜你喜欢

转载自blog.csdn.net/lyn631579741/article/details/108183021