yocto-第43篇-bb文件中函数实操演示(1)

By: fu linux
E-mail: fulinux@sina.com
Blog: https://blog.csdn.net/fulinus
喜欢的盆友欢迎点赞和订阅!
你的喜欢就是我写作的动力!

开篇简述

bitbake工具可以和其他语言一样可以使用函数来做相应的功能和任务,比如:

...
do_configure()
do_compile()
do_install()
...
  • 1
  • 2
  • 3
  • 4
  • 5

bitbake支持的函数类型有

  • shell函数:用shell脚本编写的函数,直接作为函数或任务执行,或同时作为函数和任务执行。它们也可以被其他shell函数调用;
  • BitBake风格的python函数:用Python编写并由BitBake或其他Python函数使用bb.build.exec_func()执行的函数;
  • Python函数:用Python编写并由Python执行的函数;
  • 匿名(Anonymous)的Python函数:Python函数在解析过程中自动执行;

shell函数

这样的函数形如:

some_function () {
	echo "Hello World"
}
  • 1
  • 2
  • 3

在recipe或class文件中创建这些类型的函数时,需要遵循shell编程规则。脚本由/bin/sh执行,它可能不是bash shell,但可能是dash之类的东西,所以不应该使用特定于bash的脚本
可以在函数后加上_append或者_prepend关键词来规定执行顺序。

我们在前面 yocto-第4篇-创建自己的layer 文章中创建的example_1.0.bb文件:

poky]$ vim meta-mylayer/recipes-example/example/example_0.1.bb
...
do_foo() {
    bbplain first
    fn  
}

fn_prepend() {
    bbplain second
}

fn() {
    bbplain third
    echo "third 3th"
}

do_foo_append() {
    bbplain fourth
}

addtask foo 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

重点看下上面4个函数是执行顺序,运行结果如下:

poky]$ source oe-init-build-env
build]$ bitbake example -c cleanall 
build]$ bitbake example -c foo
...
first
second
third
fourth
...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在这里插入图片描述

BitBake风格的Python函数

这个类型的函数通常是用Python语言写的,通过bitbake或者其他Python函数使用bb.build.exec_func()调用执行。
实例如下:

python do_some_python_function () {
	d.setVar("TEXT", "Hello World")
    print d.getVar("TEXT")
}
  • 1
  • 2
  • 3
  • 4

Python依赖的"bb"和"os" Python模块已经自动导入了。
看上面的例子中TEXT被赋值为“Hello World”字符串,在引用的时候不是用${TEXT},而是用d.getVar(“TEXT”)。这点差异记住。

其实在poky/meta-mylayer/recipes-example/example/example_0.1.bb文件中已经有用到Python函数的例子了,如下:

python do_compile() {
    bb.plain("***********************************************");
    bb.plain("*                                             *");
    bb.plain("*  Example recipe created by bitbake-layers   *");
    bb.plain("*                                             *");
    bb.plain("***********************************************");
}

addtask compile
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

继续在这个example_0.1.bb文件中,举个例子,同时熟悉Tasks的内容:

python do_printdate() {
    DATE = "${@time.strftime('%Y%m%d', time.gmtime())}"
    bb.plain(d.getVar("DATE"))
}

addtask printdate after do_fetch before do_build
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这里面用到了获取时间,以及打印时间的一些技巧,最后运行的结果如下:

build]$ bitbake example -c cleanall
build]$ bitbake example
...
WARNING: python should use 4 spaces indentation, but found tabs in example_0.1.bb, line 38
**20210222**
...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这里插入图片描述
日期是20210222,这个字符串对于某些软件使用时间做版本还是很有帮助的,直接定义某个C宏,让其作为版本,而不用每次修改版本信息很有帮助。函数也可以用_append或者_prepend后缀来规定执行顺序。
你学费了吗?

Python函数

这些函数是用Python编写的,由其他Python代码执行。
直接上栗子:

poky/meta-mylayer/recipes-example/example/example_0.1.bb
...
def get_depends(d):
    if d.getVar('SOMECONDITION'):
        return "libABC"
    else: #there is ":" 
        return "libXYZ"

SOMECONDITION = "1"
DEPENDS = "${@get_depends(d)}"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

我们知道在执行某个recipe时,会首先执行其依赖的recipe,用DEPENDS关键词,那么这里是什么呢?
这个例子用到了一个条件变量SOMECONDITION,当其存在时,返回“libABC”,不存在时返回“libXYZ”。
执行结果如下:

build]$ bitbake example
  • 1

在这里插入图片描述
上面因为没有libABC_*.bb recipe所以会出现依赖关系不存在的情况,就报错了。
相反如果我们将

SOMECONDITION = ""
  • 1

设置为空,运行结果如下:
在这里插入图片描述
同理,libXYZ也不存在,所以也报错了。
报错了可能这个例子后期就是一个麻烦,这里我们替换其中一个依赖,改为leanyocto项目。如下:

def get_depends(d):
    if d.getVar('SOMECONDITION'):
        return "learnyocto"
    else: #there is ":" 
        return "libXYZ"

SOMECONDITION = "1" 
DEPENDS = "${@get_depends(d)}"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

条件存在时依赖learnyocto项目,我们先将learnyocto recipe清空,然后在构建build的时候就可以看到learnyocto执行的过程了:

build]$ bitbake learnyocto -c cleanall
build]$ bitbake example
  • 1
  • 2

自己看运行过程

Python函数特点

  • 可以带参数,例如get_depends(d)
  • BitBake数据存储不是自动可用的。因此,必须将其作为参数传递给函数, 就是上面参数d
  • “bb"和"os” Python模块自动可用,不需要导入它们。

给我点个赞呗! 在这里插入图片描述