跳过正文

yocto使用指南

·2769 字·13 分钟
jiladahe1997
作者
jiladahe1997
To see the world as it is, and to love it
目录

参考资料:
#




简介
#

什么是Yocto?
#

The Yocto Project (YP) is an open source collaboration project that helps developers create custom Linux-based systems regardless of the hardware architecture.

The project provides a flexible set of tools and a space where embedded developers worldwide can share technologies, software stacks, configurations, and best practices that can be used to create tailored Linux images for embedded and IOT devices, or anywhere a customized Linux OS is needed.   Yocto项目(YP)是一个开源协作项目,它帮助开发人员创建定制的基于Linux的系统,而不考虑硬件体系结构。

该项目提供了一套灵活的工具和空间,全球嵌入式开发人员可以共享技术、软件堆栈、配置和最佳实践,这些技术、软件堆栈、配置和最佳实践可用于为嵌入式和物联网设备或任何需要定制Linux操作系统的地方创建定制的Linux映像。

在进行嵌入式Linux开发的时候,通常需要进行N个方向的开发。比如要开发一个跑Linux的路由器:

  1. Uboot引导程序
  2. Linux内核
  3. 底层驱动(IIC、外部传感器)
  4. 基础环境(libssl、libcurl、ssh等移植)
  5. 上层应用(GUI、QT、APP)

每个部分的开发都很复杂,在大型公司,每个部分甚至都有单独的开发人员。

有多复杂呢?我举个例子,以第4部基础环境为例,编译ssh。 https://www.yuque.com/jiladahe1997/kk0t7q/vsz96g#N7rpX 这里我花了两天时间都没编译好一个ssh


Yocto:将上述的N个方向的开发都集成到了一起,并提供抽象层次。 例如,现在我同样要开发一个跑Linux的路由器,那么我只需要在配置文件中选择我需要的Uboot、内核、驱动、lib库等,然后执行**bitbake xxx**。 一个嵌入式Linux就开发好了。



架构分析
#

Yocto中有几个概念需要理解。

poky:
#

poky是Yocto默认的基础示例。 举个例子,大家学C语言的时候,第一课一定都是学的 “Hello World!"。 那么在学习Yocto的时候,最先使用的也是poky。

Hello World是C语言实现的最基础的功能;poky也是Yocto实现的一个最基础的示例。



bitbake:
#

bitbake是一个构建系统。如果你接触过其他编程语言,那么你可以很容易的理解这个概念,就是:

  • Java中的:Ant、Maven、Gradle
  • C/C++中的:make、autotools
  • JavaScript中的:webpack

其本质是一个应用程序。其原理是读取配置文件,从而调用网络、编译器、等对配置文件中所描述的东西进行下载、编译、打包等。

例如:执行bitbake core-image-minimal



openembeded(OE):
#

OpenEmbeded本身是一个类似Yocto的项目,可以理解OE是Yocto的前身。



recipe:
#

recipe是组成layer的概念,是最小的组成单位。 yocto会根据recipe中的*.bb文件,执行一些操作,例如下载ssh,编译。。。等等



layer:
#

https://docs.yoctoproject.org/dev-manual/common-tasks.html#understanding-and-creating-layers
layer由多个recipes,以及class、还有images等组成。
一般而言我们在嵌入式开发中,需要对uboot、kernel、rootfs、app进行更改,举个栗子:
假设使用正点原子的IMX6ULL开发板,做一个MP3播放器

  1. 先对kernel进行更改,改了网卡芯片,更改设备树、网卡驱动
  2. 定制化rootfs,实现ssh等基本功能
  3. 更改kernel,实现EC20驱动
  4. 编写QT的APP
  5. 更改rootfs,能够运行QT
  6. 更改kernel,实现开机画面修改
  7. 更改rootfs,实现开机调整音量等设置

可以看到我们需要进行很多操作,而每一步操作之间其实有一定的联系,例如,第123步组合起来能够实现所有基本功能,45能够实现基本的APP,67则是优化。
因此可以分为3层layer:

  1. meta-renmingrui-system-basic
  2. meta-renmingrui-system-app
  3. meta-renmingrui-system-app-beauty


image:
#

https://docs.yoctoproject.org/ref-manual/images.html
image是bitbake的直接操作目标,也是yocto的构建入口。 例如bitbake core-image-minimal中的core-image-minimal就是一个image。
由于bitbake本身是一个构建工具,其直接操作的目标只能是recipe,所以image其实也是一个recipe。

  • core-image-minimal的位置:meta/recipes-core/images/core-image-minimal.bb
  • ssh的位置**:**meta/recipes-connectivity/ssh-pregen-hostkeys

不难看出两者的位置其实是等价的。

因此image是一种特殊的recipe,bitbake image,会调用此image.bb这个文件,从而又会调用到其他的recipe。







例子:使用yocto构建imx6ull的linux发行版
#

  1. 首先根据yocto官方文档,下载yocto:

https://docs.yoctoproject.org/brief-yoctoprojectqs/index.html
git clone git://git.yoctoproject.org/poky
如果有特殊的版本需要,请切到特定的稳定分支,否则可以默认适用master分支。


  1. 切换到poky,执行环境初始化。
$ cd poky
$ source oe-init-build-env
You had no conf/local.conf file. This configuration file has therefore been
created for you with some default values. You may wish to edit it to, for
example, select a different MACHINE (target hardware). See conf/local.conf
for more information as common configuration options are commented.

You had no conf/bblayers.conf file. This configuration file has therefore
been created for you with some default values. To add additional metadata
layers into your configuration please add entries to conf/bblayers.conf.

The Yocto Project has extensive documentation about OE including a reference
manual which can be found at:
    https://docs.yoctoproject.org

For more information about OpenEmbedded see their website:
    http://www.openembedded.org/

### Shell environment set up for builds. ###

You can now run 'bitbake <target>'

Common targets are:
    core-image-minimal
    core-image-sato
    meta-toolchain
    meta-ide-support

You can also run generated QEMU images with a command like 'runqemu qemux86-64'

3.搜索并下载imx6ull的layer:
在这里搜索: https://layers.openembedded.org/layerindex/branch/master/machines/?q=imx6ull&search=1
下载对应的layer:git clone [https://git.yoctoproject.org/git/meta-freescale](https://git.yoctoproject.org/git/meta-freescale)


4.添加layer:
bitbake-layers add-layer ../meta-freescale


5.修改MACHINE
vim conf/local.conf
修改MACHINE变量为:imx6ullevk


6.配置代理:
yocto的bitbake配置代理:
https://wiki.yoctoproject.org/wiki/Working_Behind_a_Network_Proxy

export http_proxy='http://192.168.1.131:7890'
export https_proxy='http://192.168.1.131:7890'
export ftp_proxy='http://192.168.1.131:7890'
export ALL_PROXY='socks://192.168.1.131:7890'
export all_proxy='socks://192.168.1.131:7890'
export GIT_PROXY_COMMAND="oe-git-proxy"

7.编译即可:
bitbake -k core-image-minimal



Yocto中更改根文件rootfs的类型:
#

默认编译出来是 rootfs.wic.gc ,是SD卡的格式。
通过在 build/conf/local.conf中加上IMAGE_FSTYPES+="tar.bz2"




Yocto 中最简单的添加软件包(添加recipe)
#

最简单的方式:
https://docs.yoctoproject.org/dev-manual/common-tasks.html#customizing-images



添加systemd支持:
#

https://yocto.yoctoproject.narkive.com/4FfIrwaI/how-to-use-systemd-as-system-init-manager

DISTRO_FEATURES_append = " systemd"
DISTRO_FEATURES_BACKFILL_CONSIDERED += "sysvinit"
VIRTUAL-RUNTIME_init_manager = "systemd"
VIRTUAL-RUNTIME_initscripts = "systemd-compat-units"


//或者
//meta/conf/distro/include/init-manager-systemd.inc
# Use systemd for system initialization
DISTRO_FEATURES:append = " systemd"
DISTRO_FEATURES_BACKFILL_CONSIDERED:append = " sysvinit"
VIRTUAL-RUNTIME_init_manager ??= "systemd"
VIRTUAL-RUNTIME_initscripts ??= "systemd-compat-units"
VIRTUAL-RUNTIME_login_manager ??= "shadow-base"
VIRTUAL-RUNTIME_dev_manager ??= "systemd"

***注:如果配合NFS rootfs食用,需配合 chown 更改nfs的文件夹的用户组为 root: **_**chown -R root:root ~/nfs/**_




Yocto 配置 kernel:
#

Yocto可以在recipe中对kernel进行定制化,详情见:
https://www.yoctoproject.org/docs/2.5/kernel-dev/kernel-dev.html

问题处理:
#

bitbake -c menuconfig linux-fscl报错:
No valid terminal found, unable to open devshell.

解决: https://blog.csdn.net/zhangjianjun521/article/details/86552804


重新编译kernel
#

batbake -c cleansstate linux


kernel module
#

在yocto中编译kernel时,可以加上这个recipe,编译的module可以自动加载: https://github.com/OSSystems/oe-core/blob/master/meta/classes/kernel-module-split.bbclass




Yocto卡在do_fetch linux-fslc问题:
#

⭐Yocto查看日志
#

检查日志:
./build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/temp/

renmingrui@renmingrui-IdeaCentre-GeekPro-15ICK:~/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/temp$ cat log.do_fetch.2049 
DEBUG: Executing python function extend_recipe_sysroot
NOTE: Direct dependencies are []
NOTE: Installed into sysroot: []
NOTE: Skipping as already exists in sysroot: []
DEBUG: Python function extend_recipe_sysroot finished
DEBUG: Executing python function do_fetch
DEBUG: Executing python function base_do_fetch
DEBUG: Trying PREMIRRORS
DEBUG: For url ['git', 'github.com', '/Freescale/linux-fslc.git', '', '', OrderedDict([('branch', '5.12.x+fslc')])] comparing ['bzr', '.*', '/.*', '', '', OrderedDict()] to ['http', 'downloads.yoctoproject.org', '/mirror/sources/', '', '', OrderedDict()]
DEBUG: For url ['git', 'github.com', '/Freescale/linux-fslc.git', '', '', OrderedDict([('branch', '5.12.x+fslc')])] comparing ['cvs', '.*', '/.*', '', '', OrderedDict()] to ['http', 'downloads.yoctoproject.org', '/mirror/sources/', '', '', OrderedDict()]
DEBUG: For url ['git', 'github.com', '/Freescale/linux-fslc.git', '', '', OrderedDict([('branch', '5.12.x+fslc')])] comparing ['git', '.*', '/.*', '', '', OrderedDict()] to ['http', 'downloads.yoctoproject.org', '/mirror/sources/', '', '', OrderedDict()]
DEBUG: For url git://github.com/Freescale/linux-fslc.git;branch=5.12.x+fslc returning http://downloads.yoctoproject.org/mirror/sources/git2_github.com.Freescale.linux-fslc.git.tar.gz
DEBUG: For url ['http', 'downloads.yoctoproject.org', '/mirror/sources/git2_github.com.Freescale.linux-fslc.git.tar.gz', '', '', OrderedDict()] comparing ['bzr', '.*', '/.*', '', '', OrderedDict()] to ['http', 'downloads.yoctoproject.org', '/mirror/sources/', '', '', OrderedDict()]
DEBUG: For url ['http', 'downloads.yoctoproject.org', '/mirror/sources/git2_github.com.Freescale.linux-fslc.git.tar.gz', '', '', OrderedDict()] comparing ['cvs', '.*', '/.*', '', '', OrderedDict()] to ['http', 'downloads.yoctoproject.org', '/mirror/sources/', '', '', OrderedDict()]
DEBUG: For url ['http', 'downloads.yoctoproject.org', '/mirror/sources/git2_github.com.Freescale.linux-fslc.git.tar.gz', '', '', OrderedDict()] comparing ['gitsm', '.*', '/.*', '', '', OrderedDict()] to ['http', 'downloads.yoctoproject.org', '/mirror/sources/', '', '', OrderedDict()]
DEBUG: For url ['http', 'downloads.yoctoproject.org', '/mirror/sources/git2_github.com.Freescale.linux-fslc.git.tar.gz', '', '', OrderedDict()] comparing ['hg', '.*', '/.*', '', '', OrderedDict()] to ['http', 'downloads.yoctoproject.org', '/mirror/sources/', '', '', OrderedDict()]
DEBUG: For url ['http', 'downloads.yoctoproject.org', '/mirror/sources/git2_github.com.Freescale.linux-fslc.git.tar.gz', '', '', OrderedDict()] comparing ['osc', '.*', '/.*', '', '', OrderedDict()] to ['http', 'downloads.yoctoproject.org', '/mirror/sources/', '', '', OrderedDict()]
DEBUG: For url ['http', 'downloads.yoctoproject.org', '/mirror/sources/git2_github.com.Freescale.linux-fslc.git.tar.gz', '', '', OrderedDict()] comparing ['p4', '.*', '/.*', '', '', OrderedDict()] to ['http', 'downloads.yoctoproject.org', '/mirror/sources/', '', '', OrderedDict()]
DEBUG: For url ['http', 'downloads.yoctoproject.org', '/mirror/sources/git2_github.com.Freescale.linux-fslc.git.tar.gz', '', '', OrderedDict()] comparing ['svn', '.*', '/.*', '', '', OrderedDict()] to ['http', 'downloads.yoctoproject.org', '/mirror/sources/', '', '', OrderedDict()]
DEBUG: For url ['git', 'github.com', '/Freescale/linux-fslc.git', '', '', OrderedDict([('branch', '5.12.x+fslc')])] comparing ['gitsm', '.*', '/.*', '', '', OrderedDict()] to ['http', 'downloads.yoctoproject.org', '/mirror/sources/', '', '', OrderedDict()]
DEBUG: For url ['git', 'github.com', '/Freescale/linux-fslc.git', '', '', OrderedDict([('branch', '5.12.x+fslc')])] comparing ['hg', '.*', '/.*', '', '', OrderedDict()] to ['http', 'downloads.yoctoproject.org', '/mirror/sources/', '', '', OrderedDict()]
DEBUG: For url ['git', 'github.com', '/Freescale/linux-fslc.git', '', '', OrderedDict([('branch', '5.12.x+fslc')])] comparing ['osc', '.*', '/.*', '', '', OrderedDict()] to ['http', 'downloads.yoctoproject.org', '/mirror/sources/', '', '', OrderedDict()]
DEBUG: For url ['git', 'github.com', '/Freescale/linux-fslc.git', '', '', OrderedDict([('branch', '5.12.x+fslc')])] comparing ['p4', '.*', '/.*', '', '', OrderedDict()] to ['http', 'downloads.yoctoproject.org', '/mirror/sources/', '', '', OrderedDict()]
DEBUG: For url ['git', 'github.com', '/Freescale/linux-fslc.git', '', '', OrderedDict([('branch', '5.12.x+fslc')])] comparing ['svn', '.*', '/.*', '', '', OrderedDict()] to ['http', 'downloads.yoctoproject.org', '/mirror/sources/', '', '', OrderedDict()]
DEBUG: Fetching http://downloads.yoctoproject.org/mirror/sources/git2_github.com.Freescale.linux-fslc.git.tar.gz using command '/usr/bin/env wget -t 2 -T 30 --passive-ftp --no-check-certificate -c -P /home/renmingrui/workspace/poky/build/downloads 'http://downloads.yoctoproject.org/mirror/sources/git2_github.com.Freescale.linux-fslc.git.tar.gz''
DEBUG: Fetcher accessed the network with the command /usr/bin/env wget -t 2 -T 30 --passive-ftp --no-check-certificate -c -P /home/renmingrui/workspace/poky/build/downloads 'http://downloads.yoctoproject.org/mirror/sources/git2_github.com.Freescale.linux-fslc.git.tar.gz'
DEBUG: Running export PSEUDO_DISABLED=1; export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus"; export all_proxy="socks://192.168.1.131:7890"; export ALL_PROXY="socks://192.168.1.131:7890"; export ftp_proxy="http://192.168.1.131:7890"; export https_proxy="http://192.168.1.131:7890"; export http_proxy="http://192.168.1.131:7890"; export PATH="/home/renmingrui/workspace/poky/build/tmp/sysroots-uninative/x86_64-linux/usr/bin:/home/renmingrui/workspace/poky/scripts:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/bin/arm-poky-linux-gnueabi:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot/usr/bin/crossscripts:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/sbin:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/bin:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/sbin:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/bin:/home/renmingrui/workspace/poky/bitbake/bin:/home/renmingrui/workspace/poky/build/tmp/hosttools"; export HOME="/home/renmingrui"; /usr/bin/env wget -t 2 -T 30 --passive-ftp --no-check-certificate -c -P /home/renmingrui/workspace/poky/build/downloads 'http://downloads.yoctoproject.org/mirror/sources/git2_github.com.Freescale.linux-fslc.git.tar.gz' --progress=dot -v
--2021-06-23 07:45:26--  http://downloads.yoctoproject.org/mirror/sources/git2_github.com.Freescale.linux-fslc.git.tar.gz
Connecting to 192.168.1.131:7890... connected.
Proxy request sent, awaiting response... 206 Partial Content
Length: 1455234486 (1.4G), 1450443319 (1.4G) remaining [application/octet-stream]
Saving to: ‘/home/renmingrui/workspace/poky/build/downloads/git2_github.com.Freescale.linux-fslc.git.tar.gz’

        [ skipping 4650K ]

2021-06-23 07:55:08 (2.47 MB/s) - Read error at byte 1426914008/1455234486 (Connection timed out). Retrying.

--2021-06-23 07:55:09--  (try: 2)  http://downloads.yoctoproject.org/mirror/sources/git2_github.com.Freescale.linux-fslc.git.tar.gz
Connecting to 192.168.1.131:7890... connected.
Proxy request sent, awaiting response... 206 Partial Content
Length: 1455234486 (1.4G), 28320478 (27M) remaining [application/octet-stream]
Saving to: ‘/home/renmingrui/workspace/poky/build/downloads/git2_github.com.Freescale.linux-fslc.git.tar.gz’

         [ skipping 1393450K ]

2021-06-23 07:56:18 (412 KB/s) - ‘/home/renmingrui/workspace/poky/build/downloads/git2_github.com.Freescale.linux-fslc.git.tar.gz’ saved [1455234486/1455234486]

DEBUG: Running 'export PSEUDO_DISABLED=1; export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus"; export all_proxy="socks://192.168.1.131:7890"; export ALL_PROXY="socks://192.168.1.131:7890"; export ftp_proxy="http://192.168.1.131:7890"; export https_proxy="http://192.168.1.131:7890"; export http_proxy="http://192.168.1.131:7890"; export PATH="/home/renmingrui/workspace/poky/build/tmp/sysroots-uninative/x86_64-linux/usr/bin:/home/renmingrui/workspace/poky/scripts:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/bin/arm-poky-linux-gnueabi:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot/usr/bin/crossscripts:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/sbin:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/bin:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/sbin:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/bin:/home/renmingrui/workspace/poky/bitbake/bin:/home/renmingrui/workspace/poky/build/tmp/hosttools"; export HOME="/home/renmingrui"; tar -xzf /home/renmingrui/workspace/poky/build/downloads/git2_github.com.Freescale.linux-fslc.git.tar.gz' in /home/renmingrui/workspace/poky/build/downloads/git2/github.com.Freescale.linux-fslc.git
DEBUG: Running 'export PSEUDO_DISABLED=1; export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus"; export all_proxy="socks://192.168.1.131:7890"; export ALL_PROXY="socks://192.168.1.131:7890"; export ftp_proxy="http://192.168.1.131:7890"; export https_proxy="http://192.168.1.131:7890"; export http_proxy="http://192.168.1.131:7890"; export PATH="/home/renmingrui/workspace/poky/build/tmp/sysroots-uninative/x86_64-linux/usr/bin:/home/renmingrui/workspace/poky/scripts:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/bin/arm-poky-linux-gnueabi:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot/usr/bin/crossscripts:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/sbin:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/bin:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/sbin:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/bin:/home/renmingrui/workspace/poky/bitbake/bin:/home/renmingrui/workspace/poky/build/tmp/hosttools"; export HOME="/home/renmingrui"; git -c core.fsyncobjectfiles=0 branch --contains 55f71ca4e7196e3c667c720b55d4fd1117d0a051 --list 5.12.x+fslc 2> /dev/null | wc -l' in /home/renmingrui/workspace/poky/build/downloads/git2/github.com.Freescale.linux-fslc.git
DEBUG: Running 'export PSEUDO_DISABLED=1; export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus"; export all_proxy="socks://192.168.1.131:7890"; export ALL_PROXY="socks://192.168.1.131:7890"; export ftp_proxy="http://192.168.1.131:7890"; export https_proxy="http://192.168.1.131:7890"; export http_proxy="http://192.168.1.131:7890"; export PATH="/home/renmingrui/workspace/poky/build/tmp/sysroots-uninative/x86_64-linux/usr/bin:/home/renmingrui/workspace/poky/scripts:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/bin/arm-poky-linux-gnueabi:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot/usr/bin/crossscripts:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/sbin:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/bin:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/sbin:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/bin:/home/renmingrui/workspace/poky/bitbake/bin:/home/renmingrui/workspace/poky/build/tmp/hosttools"; export HOME="/home/renmingrui"; git -c core.fsyncobjectfiles=0 remote' in /home/renmingrui/workspace/poky/build/downloads/git2/github.com.Freescale.linux-fslc.git
DEBUG: Running 'export PSEUDO_DISABLED=1; export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus"; export all_proxy="socks://192.168.1.131:7890"; export ALL_PROXY="socks://192.168.1.131:7890"; export ftp_proxy="http://192.168.1.131:7890"; export https_proxy="http://192.168.1.131:7890"; export http_proxy="http://192.168.1.131:7890"; export PATH="/home/renmingrui/workspace/poky/build/tmp/sysroots-uninative/x86_64-linux/usr/bin:/home/renmingrui/workspace/poky/scripts:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/bin/arm-poky-linux-gnueabi:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot/usr/bin/crossscripts:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/sbin:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/bin:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/sbin:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/bin:/home/renmingrui/workspace/poky/bitbake/bin:/home/renmingrui/workspace/poky/build/tmp/hosttools"; export HOME="/home/renmingrui"; git -c core.fsyncobjectfiles=0 remote rm origin' in /home/renmingrui/workspace/poky/build/downloads/git2/github.com.Freescale.linux-fslc.git
DEBUG: Running 'export PSEUDO_DISABLED=1; export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus"; export all_proxy="socks://192.168.1.131:7890"; export ALL_PROXY="socks://192.168.1.131:7890"; export ftp_proxy="http://192.168.1.131:7890"; export https_proxy="http://192.168.1.131:7890"; export http_proxy="http://192.168.1.131:7890"; export PATH="/home/renmingrui/workspace/poky/build/tmp/sysroots-uninative/x86_64-linux/usr/bin:/home/renmingrui/workspace/poky/scripts:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/bin/arm-poky-linux-gnueabi:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot/usr/bin/crossscripts:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/sbin:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/bin:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/sbin:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/bin:/home/renmingrui/workspace/poky/bitbake/bin:/home/renmingrui/workspace/poky/build/tmp/hosttools"; export HOME="/home/renmingrui"; git -c core.fsyncobjectfiles=0 remote add --mirror=fetch origin git://github.com/Freescale/linux-fslc.git' in /home/renmingrui/workspace/poky/build/downloads/git2/github.com.Freescale.linux-fslc.git
DEBUG: Fetcher accessed the network with the command LANG=C git -c core.fsyncobjectfiles=0 fetch -f --progress git://github.com/Freescale/linux-fslc.git refs/*:refs/*
DEBUG: Running 'export PSEUDO_DISABLED=1; export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus"; export all_proxy="socks://192.168.1.131:7890"; export ALL_PROXY="socks://192.168.1.131:7890"; export ftp_proxy="http://192.168.1.131:7890"; export https_proxy="http://192.168.1.131:7890"; export http_proxy="http://192.168.1.131:7890"; export PATH="/home/renmingrui/workspace/poky/build/tmp/sysroots-uninative/x86_64-linux/usr/bin:/home/renmingrui/workspace/poky/scripts:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/bin/arm-poky-linux-gnueabi:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot/usr/bin/crossscripts:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/sbin:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/bin:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/sbin:/home/renmingrui/workspace/poky/build/tmp/work/imx6ullevk-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/bin:/home/renmingrui/workspace/poky/bitbake/bin:/home/renmingrui/workspace/poky/build/tmp/hosttools"; export HOME="/home/renmingrui"; LANG=C git -c core.fsyncobjectfiles=0 fetch -f --progress git://github.com/Freescale/linux-fslc.git refs/*:refs/*' in /home/renmingrui/workspace/poky/build/downloads/git2/github.com.Freescale.linux-fslc.git        

可以看到,虽然 _meta-freescale/recipes-kernel/linux/linux-fslc.inc _这个文件中有指定:
SRC_URI = "git://github.com/Freescale/linux-fslc.git;branch=${KBRANCH}"
实际上还是在从 http://downloads.yoctoproject.org/mirror/sources/git2_github.com.Freescale.linux-fslc.git.tar.gz 这个地址下载linux-fslc。 可以看到,yocto还是会智能的去寻找镜像。

更多关于镜像请参考: https://wiki.yoctoproject.org/wiki/How_do_I#Q:How_do_I_create_my_own_source_download_mirror.3F


通过分析上述日志,可以看到实际上是卡在了_git -c core.fsyncobjectfiles=0 fetch -f --progress git://github.com/Freescale/linux-fslc.git refs/*:refs/*_ 这里,

因此经过我的排除法,发现是这样的原因:

https://cms-sw.github.io/tutorial-proxy.html
https://github.com/cms-sw/cms-git-tools/blob/master/git-proxy

cd ~ && mkdir bin && cd bin
wget https://github.com/cms-sw/cms-git-tools/blob/master/git-proxy
chmod -x git-proxy

//重新登录ssh
export GIT_PROXY_COMMAND='git-proxy'
export SOCKS_PROXY="192.168.1.131:7890"
git clone git://xxxx

再进一步观察日志,可以看到

DEBUG: Fetcher failure: Fetch command export PSEUDO_DISABLED=1; export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus"; export GIT_PROXY_COMMAND="git-proxy"; export all_proxy="socks://192.168.1.131:7890"; export ALL_PROXY="socks://192.168.1.131:7890"; export ftp_proxy="http://192.168.1.131:7890"; export https_proxy="http://192.168.1.131:7890"; export http_proxy="http://192.168.1.131:7890"; export PATH="/home/renmingrui/workspace/poky/build/tmp/sysroots-uninative/x86_64-linux/usr/bin:/home/renmingrui/workspace/poky/scripts:/home/renmingrui/workspace/poky/build/tmp/work/dabai-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/bin/arm-poky-linux-gnueabi:/home/renmingrui/workspace/poky/build/tmp/work/dabai-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot/usr/bin/crossscripts:/home/renmingrui/workspace/poky/build/tmp/work/dabai-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/sbin:/home/renmingrui/workspace/poky/build/tmp/work/dabai-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/bin:/home/renmingrui/workspace/poky/build/tmp/work/dabai-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/sbin:/home/renmingrui/workspace/poky/build/tmp/work/dabai-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/bin:/home/renmingrui/workspace/poky/bitbake/bin:/home/renmingrui/workspace/poky/build/tmp/hosttools"; export HOME="/home/renmingrui"; 
	LANG=C git -c core.fsyncobjectfiles=0 fetch -f --progress git://github.com/Freescale/linux-fslc.git refs/*:refs/* failed with exit code 128, output:
error: cannot run git-proxy: No such file or directory
fatal: cannot start proxy git-proxy

DEBUG: Running 'export PSEUDO_DISABLED=1; export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus"; export GIT_PROXY_COMMAND="git-proxy"; export all_proxy="socks://192.168.1.131:7890"; export ALL_PROXY="socks://192.168.1.131:7890"; export ftp_proxy="http://192.168.1.131:7890"; export https_proxy="http://192.168.1.131:7890"; export http_proxy="http://192.168.1.131:7890"; export PATH="/home/renmingrui/workspace/poky/build/tmp/sysroots-uninative/x86_64-linux/usr/bin:/home/renmingrui/workspace/poky/scripts:/home/renmingrui/workspace/poky/build/tmp/work/dabai-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/bin/arm-poky-linux-gnueabi:/home/renmingrui/workspace/poky/build/tmp/work/dabai-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot/usr/bin/crossscripts:/home/renmingrui/workspace/poky/build/tmp/work/dabai-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/sbin:/home/renmingrui/workspace/poky/build/tmp/work/dabai-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/usr/bin:/home/renmingrui/workspace/poky/build/tmp/work/dabai-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/sbin:/home/renmingrui/workspace/poky/build/tmp/work/dabai-poky-linux-gnueabi/linux-fslc/5.12.11+gitAUTOINC+55f71ca4e7-r0/recipe-sysroot-native/bin:/home/renmingrui/workspace/poky/bitbake/bin:/home/renmingrui/workspace/poky/build/tmp/hosttools"; export HOME="/home/renmingrui"; 
    LANG=C git -c core.fsyncobjectfiles=0 fetch -f --progress https://github.com/Freescale/linux-fslc.git refs/*:refs/*' in /home/renmingrui/workspace/poky/build/downloads/git2/github.com.Freescale.linux-fslc.git
remote: Enumerating objects: 3880368        
remote: Enumerating objects: 4140383        
remote: Enumerating objects: 4512554, done.  

因此,虽然设置了 git-proxy,但是直接报错了:No such file or directory。 yocto自动的转到了http协议上去了。
log.do_fetch.2052.log


解决方案:之前系统好像会自动去找~/bin,就没有手动暴露。应该把git-proxy放在 ~/bin中去,并且在.bashrc中 export PATH=$PATH:~/bin。





Yocto语法:
#

https://www.yoctoproject.org/docs/1.6/bitbake-user-manual/bitbake-user-manual.html#basic-syntax

  • = 赋值(不立即计算右值)
  • := 立即计算右值赋值
  • ?= 默认立即赋值
  • ??= 默认最后赋值
  • += 末尾添加(自动补空格
  • =+ 开头添加(自动补空格
  • .= 末尾立即添加(不补空格
  • =. 开头立即添加(不补空格
  • _append 末尾最后添加 (不补空格
  • _prepend 开头最后添加(不补空格


yocto内置全局变量
#

文档: https://docs.yoctoproject.org/ref-manual/variables.html





Yocto bitbake编译错误:
#

在do_compile阶段按CTRL+C中断某个包的构建通常会造成这个包再次构建失败。可以使用如下命令删除缓存:
bitbake -c cleanall ${recipe-name}



Yocto bitbake调试
#

bitbake -e ${recipe-name}可以调试某个recipe



内核virtual-provider:
#

https://docs.yoctoproject.org/dev-manual/common-tasks.html#using-virtual-providers




Yocto uboot和kernel的编译规则:
#

  • 如果只是空的配置文件:
    • 只会编译rootfs
  • 如果配置了_PREFERRED_PROVIDER_virtual/kernel_
    • 则会编译kernel

如果配置了_PREFERRED_PROVIDER_virtual/bootloader_ 以及 _DEPENDS += "virtual/bootloader"_

  • 则会编译uboot
meta-freescale/conf/machine/imx_test.conf

//必须要这一行否则bitbake提示必须要tune文件
require conf/machine/include/tune-cortexa9.inc

//编译kernel
//这一行给主要是因为 linux-fslc 中限定了 MACHINE 必须是mx6否则不允许编译
MACHINEOVERRIDES =. "mx6:mx6ull:"
PREFERRED_PROVIDER_virtual/kernel ??= "linux-fslc"

//编译u-boot
PREFERRED_PROVIDER_virtual/bootloader ??= "u-boot"
DEPENDS += "virtual/bootloader"





⭐示例:Yocto 构建自己的内核recipe
#

1.创建layer 和 增加machine:
#

# change dir to poky
cd .. 

bitbake-layers create-layer meta-xxx
source oe-init-build-env
bibtake-layers add-layer ../meta-xxx
conf/machine/dabai.conf

require conf/machine/include/tune-cortexa9.inc

PREFERRED_PROVIDER_virtual/kernel ??= "linux-icl-dabai"

SERIAL_CONSOLES = "115200;ttymxc0"

2.增加recipe
#

# change dir to meta-xxx
cd ..

# 参考mete层和meta-freescale曾,标准的内核recipe名称及位置
mkdir recipes-kernel/linux
cd recipes-kernel/linux

# 创建.bb文件,recipe的入口
touch linux-icl.bb

# 创建deconfig文件,用于配置内核
# 注意defconfig的位置:meta-xxx/recipes-kernel/linux/linux-icl/defconfig
mkdir linux-icl
cd linux-icl
touch defconfig

#

linux-icl.bb
#

linux-icl.bb

# 必须inherit kernel
# 因为在kernel.bbclass:184
# PACKAGES_DYNAMIC += "^${KERNEL_PACKAGE_NAME}-module-.*"
# 这里添加了所有的 kernel-module-* 虚拟包
# 如果inherit kernel,bitbake会报错, not found kernel-module-ip-tables
inherit kernel

# 这几行文件描述必须加,bitbake也会检查
SUMMARY = "linux-icl"
DESCRIPTION = "a recipe which use 'mainline' linux"
LICENSE = "MIT"

# 添加 providers,详情见上述“内核virtual-provider章节”
PROVIDES += "virtual/kernel"

# 添加 git源代码路径
# 添加 defconfig
# 参考:https://www.yoctoproject.org/docs/latest/ref-manual/ref-manual.html#var-SRC_URI
SRC_URI = "git://github.com/torvalds/linux.git \
           file://defconfig"

# 代码分支 commit ID
SRCREV = "44db63d1ad8d71c6932cbe007eb41f31c434d140"

# license的位置以及MD5,会根据MD5及时通知用户lic发生了变化
# 以linux kernel为例,先去代码仓库看lic的位置,:https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/
# 在根目录下,计算MD5,百度在线MD5计算
LIC_FILES_CHKSUM = "file://COPYING;md5=6bc538ed5bd9a7fc9398086aedcd7e46"

# 2022/02/17更新,可以不用LIC:
#LICENSE="CLOSED"
#LIC_FILES_CHKSUM = ""

# 编译的时候会报错:lzop: not found
# 这里的native,参考:
# https://wiki.yoctoproject.org/wiki/Technical_FAQ#What_does_.22native.22_mean.3F
DEPENDS += "lzop-native"

# 编译出来的设备树,如果不加的话,最后的deploy里面没有.dtb
KERNEL_DEVICETREE = " \
	imx6ull-14x14-evk.dtb \
"

#https://docs.yoctoproject.org/ref-manual/variables.html#term-S
#配置工作目录,对于git仓库的recipe必须配置
S = "${WORKDIR}/git"

defconfig
#

defconfig (copy from arch/arm/configs/imx_v6_v7_defconfig)

CONFIG_KERNEL_LZO=y
CONFIG_SYSVIPC=y
CONFIG_NO_HZ=y
...
...
CONFIG_DEBUG_FS=y
# CONFIG_SCHED_DEBUG is not set
CONFIG_PROVE_LOCKING=y
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_FTRACE is not set

3.⭐recipe过程分析
#

①task:
#

参考文档1: https://docs.yoctoproject.org/bitbake/bitbake-user-manual/bitbake-user-manual-metadata.html#tasks
参考文档2所有的task: https://docs.yoctoproject.org/ref-manual/tasks.html#
参考文档3: https://docs.yoctoproject.org/bitbake/bitbake-user-manual/bitbake-user-manual-metadata.html#functions
task是recipe的执行最小单位。当执行一个recipe的时候,流程如下:

  1. 解析 .bb文件,执行变量的赋值操作
  2. 开始执行task,(task的执行顺序很重要,但是目前我还没有找到相关资料。)
    1. 默认的task:do_fetch、do_configure、do_compile、…(哪些是默认的task,也没有讲清楚)
    2. 自定义的task:do_custom…..

因此上述的_ linux-icl.bb _文件基本上都是继承的 kernel.bbclass 这个文件的所有task。

②kernel.bbclass->do_configur分析:
#

KERNEL_CONFIG_COMMAND ?= 
"oe_runmake_call -C ${S} CC="${KERNEL_CC}" LD="${KERNEL_LD}" O=${B} olddefconfig || oe_runmake -C ${S} O=${B} CC="${KERNEL_CC}" LD="${KERNEL_LD}" oldnoconfig"

kernel_do_configure() {
	# fixes extra + in /lib/modules/2.6.37+
	# $ scripts/setlocalversion . => +
	# $ make kernelversion => 2.6.37
	# $ make kernelrelease => 2.6.37+
	touch ${B}/.scmversion ${S}/.scmversion

	if [ "${S}" != "${B}" ] && [ -f "${S}/.config" ] && [ ! -f "${B}/.config" ]; then
		mv "${S}/.config" "${B}/.config"
	fi

	# Copy defconfig to .config if .config does not exist. This allows
	# recipes to manage the .config themselves in do_configure_prepend().
	if [ -f "${WORKDIR}/defconfig" ] && [ ! -f "${B}/.config" ]; then
		cp "${WORKDIR}/defconfig" "${B}/.config"
	fi

	${KERNEL_CONFIG_COMMAND}
}

EXPORT_FUNCTIONS do_compile do_install do_configure

首先,根据参考文档3,可以得出,kernel_do_configure就是 do_configure。 因此这里就好理解了,_linux-icl.bb_会直接执行到这里,执行 oe_runmake_call ... ... oldnoconfig,这里的意思是保存当前配置。


4.添加machine
#

meta-xxx/conf/machine/my_machine.conf

require conf/machine/include/tune-cortexa9.inc

PREFERRED_PROVIDER_virtual/kernel ??= "linux-icl"

参考上述章节的 “Yocto uboot和kernel的编译规则”这一章写conf即可。


5.编译
#

执行bitbake core-image-minimal
结果如下:

image.png






⭐示例:Yocto增加quectel-CM构建
#

1.增加layer,略
#

2.增加bb文件
#

1.增加基本信息
#

# @author: renmingrui
# @date:   2021/09/01
# @brief:
#       This recipe add quectel-CM app to systemd service, used by ec20 to connect
#       to network.
SUMMARY = "quectel-CM app"
DESCRIPTION = "This recipe add quectel-CM app to systemd service, used by ec20 to connect to network."
LICENSE = "MIT"

2.增加代码仓库:
#

SRC_URI = "git://codehub.devcloud.huaweicloud.com/db20zggzqrs_renmingrui00001/QConnectManager_Linux_V1.5.git;protocol=https \
        file://quectel-CM.service "
SRCREV = "dff481866a1be59ad0c4028b96af308ecd2e6a8a"
LIC_FILES_CHKSUM = "file://LICENSE;md5=e49f4652534af377a713df3d9dec60cb"
S = "${WORKDIR}/git" 
B = "${S}/quectel-CM"

3.增加编译步骤
#

这里直接默认使用的是make进行编译,yocto默认也是使用make进行编译,无需修改

https://docs.yoctoproject.org/ref-manual/tasks.html

6.1.2 do_compile
#

Compiles the source code. This task runs with the current working directory set to ${ B}. The default behavior of this task is to run the oe_runmake function if a makefile (Makefile, makefile, or GNUmakefile) is found. If no such file is found, the do_compile task does nothing.

4.编译完后,可执行文件拷贝到systemroot目录:
#

do_install:append () {
    install -d ${D}/config
    install -m 0755 ${B}/quectel-CM ${D}/config

    # systemd
    install -d ${D}${systemd_unitdir}/system
    install -m 0644 ${WORKDIR}/quectel-CM.service ${D}${systemd_unitdir}/system/
}

5.systemroot目录中,指定需要最终打包的文件:
#

FILES:${PN} = "/config/quectel-CM"

6.指定systemd相关的文件:
#

inherit systemd
SYSTEMD_SERVICE:${PN} = "quectel-CM.service"
#这一行的作用是,在后面systemd.bb中会解析此变量,然后使用systemctl enable xxx

7.打两个修复:
#

#quectel的make中,已经加了-s选项,去除debug信息。 而yocto会自动再检查一遍,如果yocto发现没有debug信息,会报错。
#这一行告诉yocto跳过这个文件的检查
#QA Issue: File '/config/quectel-CM' from quectel-CM was already stripped, this will prevent future debugging! [already-stripped]
INSANE_SKIP:${PN} += "already-stripped"
#QA Issue: File /config/quectel-CM in package quectel-CM doesn't have GNU_HASH (didn't pass LDFLAGS?) [ldflags]
INSANE_SKIP:${PN} += "ldflags"

8.最终文件
#

# @author: renmingrui
# @date:   2021/09/01
# @brief:
#       This recipe add quectel-CM app to systemd service, used by ec20 to connect
#       to network.

inherit systemd

SUMMARY = "quectel-CM app"
DESCRIPTION = "This recipe add quectel-CM app to systemd service, used by ec20 to connect to network."
LICENSE = "MIT"

S = "${WORKDIR}/git"
B = "${S}/quectel-CM"
SRC_URI = "git://codehub.devcloud.huaweicloud.com/db20zggzqrs_renmingrui00001/QConnectManager_Linux_V1.5.git;protocol=https \
        file://quectel-CM.service "
SRCREV = "dff481866a1be59ad0c4028b96af308ecd2e6a8a"
LIC_FILES_CHKSUM = "file://LICENSE;md5=e49f4652534af377a713df3d9dec60cb"

do_install:append () {
    install -d ${D}/config
    install -m 0755 ${B}/quectel-CM ${D}/config

    # systemd
    install -d ${D}${systemd_unitdir}/system
    install -m 0644 ${WORKDIR}/quectel-CM.service ${D}${systemd_unitdir}/system/
}

FILES:${PN} = "/config/quectel-CM"
SYSTEMD_SERVICE:${PN} = "quectel-CM.service"

#quectel的make中,已经加了-s选项,去除debug信息。 而yocto会自动再检查一遍,如果yocto发现没有debug信息,会报错。
#这一行告诉yocto跳过这个文件的检查
#QA Issue: File '/config/quectel-CM' from quectel-CM was already stripped, this will prevent future debugging! [already-stripped]
INSANE_SKIP:${PN} += "already-stripped"
#QA Issue: File /config/quectel-CM in package quectel-CM doesn't have GNU_HASH (didn't pass LDFLAGS?) [ldflags]
INSANE_SKIP:${PN} += "ldflags"



Yocto 流水线CI架构
#

image.png




Yocto使用第三方的编译工具链:
#

https://elinux.org/images/c/c8/ExternalToolchainsInYocto.pdf




NTP时间同步:
#

chrony: https://chrony.tuxfamily.org/comparison.html

ntpd: https://linux.die.net/man/8/ntpd

systemd-timesyncd: https://www.freedesktop.org/software/systemd/man/timesyncd.conf.html#

The systemd-timesyncd service implements SNTP only. This minimalistic service will step the system clock for large offsets or slowly adjust it for smaller deltas. Complex use cases that require full NTP support (and where SNTP is not sufficient) are not covered by systemd-timesyncd. 该systemd-timesyncd服务仅实现 SNTP。这种简约的服务将步进系统时钟以获得大偏移或缓慢调整它以获得较小的增量。需要完整 NTP 支持(以及 SNTP 不够用)的复杂用例不在 systemd-timesyncd.‘

查看当前时间同步状态:
#

timedatectl

手动时间同步:
#

//https://askubuntu.com/questions/254826/how-to-force-a-clock-update-using-ntp
sudo service ntp stop
sudo ntpd -gq
sudo service ntp start




DNS域名解析:
#

参考:【Anatomy of a Linux DNS Lookup – Part I】 https://zwischenzugs.com/2018/06/08/anatomy-of-a-linux-dns-lookup-part-i/
【How to take back control of /etc/resolv.conf on Linux】 https://www.ctrl.blog/entry/resolvconf-tutorial.html

域名解析的功能是通过域名->拿到ip地址。
比如执行ping baidu.com。得到的回复是:

[root@iZj6cdls5a0h7p2oaypip0Z poky]# ping baidu.com
PING baidu.com (220.181.38.148) 56(84) bytes of data.
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=1 ttl=47 time=82.7 ms
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=2 ttl=47 time=90.3 ms
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=3 ttl=47 time=90.0 ms
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=4 ttl=47 time=92.3 ms

可以看到这个过程中,已经进行了域名到IP地址的转换,也就是DNS。

再看一行代码:

#include <stdio.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{
    if(argc != 2)
    {
        printf("ERROR: usage %s\n", argv[0]);
        return 1;
    }

    char *ptr, **pptr;
    char buf[1024];
    struct hostent *hent;
    if((hent = gethostbyname(argv[1])) == NULL)
    {
        printf("ERROR: gethostbyname error for hostname: %s\n", argv[1]);
        return 0;
    }

    printf("Official hostname: %s\n", hent->h_name);
    for(pptr = hent->h_aliases; *pptr != NULL; pptr++)
        printf("Alias hostname: %s\n", *pptr);

    printf("Host Address Type: %d(AF_INET: %d)\n", hent->h_addrtype, (int)AF_INET);

    for(pptr = hent->h_addr_list; *pptr != NULL; pptr++)
    {
        printf("IP Address: %s\n", inet_ntop(hent->h_addrtype, *pptr, buf, sizeof buf));
    }
    return 0;
}

//output:
renmingrui@renmingrui-IdeaCentre-GeekPro-15ICK:~/workspace/test/golang$ ./main www.baidu.com
Official hostname: www.a.shifen.com
Alias hostname: www.baidu.com
Host Address Type: 2(AF_INET: 2)
IP Address: 220.181.38.149
IP Address: 220.181.38.150

好吧,不止一行代码。

上述两个例子说明了linux中通过命令行和通过代码都可以进行DNS解析,那么他们是怎么实现的呢?
执行下列命令:

strace -e trace=openat -f ping -c1 baidu.com
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libcap.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgcrypt.so.20", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libresolv.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgpg-error.so.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/share/locale/zh_CN/LC_MESSAGES/iputils.mo", O_RDONLY) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/usr/share/locale/zh/LC_MESSAGES/iputils.mo", O_RDONLY) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/usr/share/locale-langpack/zh_CN/LC_MESSAGES/iputils.mo", O_RDONLY) = 3
openat(AT_FDCWD, "/usr/share/locale-langpack/zh/LC_MESSAGES/iputils.mo", O_RDONLY) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/iputils.mo", O_RDONLY) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/usr/share/locale-langpack/en/LC_MESSAGES/iputils.mo", O_RDONLY) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 5
openat(AT_FDCWD, "/etc/host.conf", O_RDONLY|O_CLOEXEC) = 5
openat(AT_FDCWD, "/etc/resolv.conf", O_RDONLY|O_CLOEXEC) = 5
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 5
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 5
openat(AT_FDCWD, "/etc/hosts", O_RDONLY|O_CLOEXEC) = 5
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 5
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libnss_mdns4_minimal.so.2", O_RDONLY|O_CLOEXEC) = 5
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 5
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libnss_dns.so.2", O_RDONLY|O_CLOEXEC) = 5
openat(AT_FDCWD, "/etc/gai.conf", O_RDONLY|O_CLOEXEC) = 5
PING baidu.com (220.181.38.251) 56(84) bytes of data.
openat(AT_FDCWD, "/etc/hosts", O_RDONLY|O_CLOEXEC) = 5
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 5
64 比特,来自 220.181.38.251 (220.181.38.251): icmp_seq=1 ttl=52 时间=37.5 毫秒

--- baidu.com ping 统计 ---
已发送 1 个包, 已接收 1 个包, 0% 包丢失, 耗时 0 毫秒
rtt min/avg/max/mdev = 37.523/37.523/37.523/0.000 ms
+++ exited with 0 +++

可以看到执行ping命令之后,会去读取/etc/resolv.conf这个文件进行DNS解析。

再对刚才的程序执行同样的操作:

strace -e trace=openat -f ./main baidu.com
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/etc/host.conf", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/etc/resolv.conf", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/etc/hosts", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libnss_mdns4_minimal.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libresolv.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libnss_dns.so.2", O_RDONLY|O_CLOEXEC) = 3
Official hostname: baidu.com
Host Address Type: 2(AF_INET: 2)
IP Address: 220.181.38.148
IP Address: 220.181.38.251
+++ exited with 0 +++

同样也去读取了 /etc/resolv.conf这个文件。

因此可以大致的推断出Linux上DNS的步骤:

  • DNS不涉及到系统内核层面
  • 需要进行DNS的程序,自己通过调用底层的库,例如上面的glibc,glibc又去读取 /etc/resolv.conf文件,然后进行DNS解析过程。
  • /etc/resolv.conf就是一个很关键的文件了。有很多个不同的程序都在管理这个文件:

综上所述,如果你需要更改你系统中的DNS,你需要知道你电脑中安装了哪些可能更改/etc/resolv.conf的软件,直接对这些软件进行配置。




路由表
#

路由表决定网络数据包的流向。
命令:route /route -n可以查看当前路由表

切换网卡时
route delete default删除当前默认路由
route add default xxx添加默认路由
建议使用 udhcpc -i eth0命令,会自动添加默认路由