通过openeuler_fetch使用openEuler软件包

特性介绍

在openEuler Embedded构建镜像时,需要提前下载所有软件包,而openEuler Embedded由上百个软件包构成,完全下载耗时耗力。功能函数openeuler_fetch解决了该问题,它可以在openEuler Embedded构建镜像时,按需从上游源码包自动下载软件包。例如当你只想编译busybox这一个软件包,而不需要将其他软件包全部下载的时候,使用openeuler_fetch即可实现,你只需要初始化完环境即可进入编译环节。

openeuler_fetch运行机制

openeuler_fetch在classes/openeuler.bbclass中实现,函数名为do_openeuler_fetch,该函数在base_do_fetch:prepend中通过bb.build.exec_func()函数调用,即openeuler_fetch运行完还会继续执行do_fetch,这样做的原因是不管openeuler_fetch运行成功与否都可以让fetch继续补充,例如有一款软件包在gitee中不存在,或在配置中配置错误,或者源码目录有相关的改动导致openeuler_fetch运行失败,不用担心,do_fetch可以继续完成文件的查找。

openeuler_fetch运行逻辑

openeuler_fetch通过以下控制变量来完成相关包下载:

  • OPENEULER_REPO_NAME: 软件包名,该名一般和构建包名一致,但在特殊情况下需要改动,例如构建libtool-cross时,构建包名为libtool-cross,因此默认OPENEULER_REPO_NAME为libtool-cross,但是依赖包路径是libtool,则需要将OPENEULER_REPO_NAME改为libtool

  • OPENEULER_LOCAL_NAME: 软件包本地名称,即软件包在本地路径名称,一般该变量如果不设置则在系统处理时默认和OPENEULER_REPO_NAME一样,该变量意在解决软件包名和本地存储路径不一致问题

整体openeuler_fetch下载就是依靠以上相关变量确定下载的包信息,而获取下载包的信息是在openEuler Embedded的基线文件中记录的,该文件目录为.oebuild/manifest.yaml,如果在基线文件中能命中该包信息,则会进行下载,否则不做任何操作。基线文件中的包信息包含该包的version,因此在命中该包后会根据version来确定该包的版本,并且为了更快的完成下载任务,我们尽可能的减少下载的代码量,因此openeuler_fetch在下载代码时其深度设定为1。在对该包的匹配过程中,如果本地可以检出该包的version,则直接切换包版本,否则进行fetch操作,然后再进行包版本检出。

另外openeuler_fetch对于OPENEULER_REPO_NAME与OPENEULER_LOCAL_NAME的处理为如果设定了OPENEULER_LOCAL_NAME则选用OPENEULER_LOCAL_NAME作为reponame,用reponame来查找manifest.yaml中的相关包信息,否则选用OPENEULER_REPO_NAME作为reponame,因此对于同一个仓,由于不同的应用场景需要选用不同的分支,那么则需要设定不同的OPENEULER_LOCAL_NAME。

例如特性M与N,都依赖a仓,但是版本分支不同,因此对于M来说,其所设定的a仓的OPENEULER_LOCAL_NAME为a-1,对于N来说,其所设定的a仓的OPENEULER_LOCAL_NAME为a-2,而manifest.yaml中需要各自记录a-1与a-2的版本信息。

如何适配其他软件包

在构建openEuler Embedded时经常会引入其他相关包或修改非指定包版本,那么此时该如何做呢?直接修改基线文件即可,内核是例外,接下来我们以busybox为例进行讲解:

  • 如果想要某一个版本的busybox参与构建:在manifest.yaml中将busybox的version进行修改即可

  • 如果想要使用自有仓库的busybox参与构建:在manifest.yaml中将remote_url修改为自有仓库的链接即可

  • 如果需要其他代码仓的busybox参与构建:同理,直接在manifest.yaml中修改对应的busybox中remote_url即可

  • 另外,当构建busybox时需要的依赖并不会是某一款特定包,即不能直接通过depends添加依赖,而仅仅是需要某个路径下的文件,此时需要在bbappend中添加do_fetch:prepend,在该函数中添加需要依赖的包,例如:

python do_fetch:prepend() {
    repoList = [
        "yocto-embedded-tools",
        "libboundscheck",
        "dsoftbus_standard",
        "embedded-ipc"
        ]

    d.setVar("PKG_REPO_LIST", repoList)

    dd.build.exec_func("do_openeuler_fetchs", d)
}

通过repoList设置好需要依赖的包,同时列表中的包需要在manifest.yaml中有相关信息的记录,以以上的列表为例,我们需要在manifest.yaml中有关于yocto-embedded-tools的包信息,否则不会有任何下载功能,PKG_REPO_LIST变量的设定是为在do_openeuler_fetchs中获取依赖的包列表,do_openeuler_fetchs将依次解析PKG_REPO_LIST,并调用do_openeuler_fetch完成相关包的下载。

如何关闭openeuler_fetch功能

OPENEULER_FETCH有两种关闭方式:

  1. 在meta-openeuler/conf/layer.conf中有一个全局变量OPENEULER_FETCH,该值默认为enable,即openeuler_fetch是开启状态,如果想要关闭openeuler_fetch,设置该值为disable即可。

  2. 在oebuild执行generate指令时,将参数-df带上,也可以关闭openeuelr_fetch功能

另外 OPENEULER_FETCH 该值的作用域是全局的,我们在开发中可能会针对某一些包不需要运行openeuler_fetch,则可以在相关包的bb或bbappend中设定该值为disable