[yocto] The BitBake equivalent of "Hello, World!"

Evade Flow evadeflow at gmail.com
Thu Oct 4 14:26:24 PDT 2012


Thanks, this is great! I was looking for something exactly like this.
I'm going to have a play wit it right now.  If you (or anyone) can think
of any ways this example doesn't adhere to current bitbake best
practices (other than not inheriting from OECore's more full-featured
base classes), please let me know...


On Thu, Oct 4, 2012 at 2:58 PM, Rudolf Streif <rudolf.streif at linux.com> wrote:
> [Warning: lengthy post, and probably boring to most.]
>
> My Bitbake "Hello World" is a little more than a basic "Hello World". It's
> idea is to incorporate a layer and use a structure similar to what OE and
> Yocto are using. You can do it simpler if you want to. I did this a while
> ago with Bitbake 1.12.0. I would think it works with newer versions too
> although I have not tested it. This is the layout I am using:
>
> bbtest/
> ├── conf
> │   ├── bblayers.conf
> │   └── bitbake.conf
> ├── downloads
> │   └── /* need to create but will be populated with downloads */
> ├── meta-test
> │   ├── classes
> │   │   └── base.bbclass
> │   ├── conf
> │   │   └── layer.conf
> │   └── recipes-test
> │       └── nano
> │         └── nano.bb
> └── tmp
>     └── /* will be created and populated when building */
>
> The first thing Bitbake looks for is a conf/bblayers.conf file in the
> directory you started it from. This file must provide an initial setting for
> BBPATH:
>
> bblayers.conf:
>
> BBPATH := "${TOPDIR}"
> BBFILES ?= ""
> BBLAYERS = " \
>   ${TOPDIR}/meta-test \
>   "
>
> Without BBPATH Bitbake will not find any conf/<filename>.conf files and
> recipe files at all. It will also not find bitbake.conf. I simply copied
> bitbake.conf from the Bitbake download and edited DL_DIR:
>
> bitbake.conf:
>
> # comments omitted
> B = "${S}"
> CVSDIR = "${DL_DIR}/cvs"
> DEPENDS = ""
> DEPLOY_DIR = "${TMPDIR}/deploy"
> DEPLOY_DIR_IMAGE = "${DEPLOY_DIR}/images"
> DL_DIR = "${TOPDIR}/downloads"
> FETCHCOMMAND = ""
> FETCHCOMMAND_cvs = "/usr/bin/env cvs -d${CVSROOT} co ${CVSCOOPTS}
> ${CVSMODULE}"
> FETCHCOMMAND_svn = "/usr/bin/env svn co ${SVNCOOPTS} ${SVNROOT}
> ${SVNMODULE}"
> FETCHCOMMAND_wget = "/usr/bin/env wget -t 5 --passive-ftp -P ${DL_DIR}
> ${URI}"
> FILESDIR = "${@bb.utils.which(bb.data.getVar('FILESPATH', d, 1), '.')}"
> FILESPATH =
> "${FILE_DIRNAME}/${PF}:${FILE_DIRNAME}/${P}:${FILE_DIRNAME}/${PN}:${FILE_DIRNAME}/files:${FILE_DIRNAME}"
> FILE_DIRNAME = "${@os.path.dirname(bb.data.getVar('FILE', d))}"
> GITDIR = "${DL_DIR}/git"
> IMAGE_CMD = "_NO_DEFINED_IMAGE_TYPES_"
> IMAGE_ROOTFS = "${TMPDIR}/rootfs"
> MKTEMPCMD = "mktemp -q ${TMPBASE}"
> MKTEMPDIRCMD = "mktemp -d -q ${TMPBASE}"
> OVERRIDES = "local:${MACHINE}:${TARGET_OS}:${TARGET_ARCH}"
> P = "${PN}-${PV}"
> PERSISTENT_DIR = "${TMPDIR}/cache"
> PF = "${PN}-${PV}-${PR}"
> PN = "${@bb.parse.BBHandler.vars_from_file(bb.data.getVar('FILE',d),d)[0] or
> 'defaultpkgname'}"
> PR = "${@bb.parse.BBHandler.vars_from_file(bb.data.getVar('FILE',d),d)[2] or
> 'r0'}"
> PROVIDES = ""
> PV = "${@bb.parse.BBHandler.vars_from_file(bb.data.getVar('FILE',d),d)[1] or
> '1.0'}"
> RESUMECOMMAND = ""
> RESUMECOMMAND_wget = "/usr/bin/env wget -c -t 5 --passive-ftp -P ${DL_DIR}
> ${URI}"
> S = "${WORKDIR}/${P}"
> SRC_URI = "file://${FILE}"
> STAMP = "${TMPDIR}/stamps/${PF}"
> SVNDIR = "${DL_DIR}/svn"
> T = "${WORKDIR}/temp"
> TARGET_ARCH = "${BUILD_ARCH}"
> TMPDIR = "${TOPDIR}/tmp"
> UPDATECOMMAND = ""
> UPDATECOMMAND_cvs = "/usr/bin/env cvs -d${CVSROOT} update ${CVSCOOPTS}"
> UPDATECOMMAND_svn = "/usr/bin/env svn update ${SVNCOOPTS}"
> WORKDIR = "${TMPDIR}/work/${PF}"
> PERSISTENT_DIR = "${TMPDIR}/cache"
>
> That's more than you need but it's convenient.
>
> Bitbake will require a base.bbclass file somewhere in a classes subdirectory
> of BBPATH. I used the base.bbclass file from the Bitbake download. As a
> minimum it should contain a do_build task. That's the target that Bitbake
> invokes by default if you do not use the -c option explicitly. It's empty
> and does not do anything but it functions as an anchor for tasks you define
> in your recipes:
>
> base.bbclass:
>
> # comments omitted
> die() {
>         bbfatal "$*"
> }
>
> bbnote() {
>         echo "NOTE:" "$*"
> }
>
> bbwarn() {
>         echo "WARNING:" "$*"
> }
>
> bbfatal() {
>         echo "FATAL:" "$*"
>         exit 1
> }
>
> addtask showdata
> do_showdata[nostamp] = "1"
> python do_showdata() {
>         import sys
>         # emit variables and shell functions
>         bb.data.emit_env(sys.__stdout__, d, True)
>         # emit the metadata which isnt valid shell
>         for e in bb.data.keys(d):
>                 if bb.data.getVarFlag(e, 'python', d):
>                         sys.__stdout__.write("\npython %s () {\n%s}\n" % (e,
> bb.data.getVar(e, d, 1)))
> }
>
> addtask listtasks
> do_listtasks[nostamp] = "1"
> python do_listtasks() {
>         import sys
>         for e in bb.data.keys(d):
>                 if bb.data.getVarFlag(e, 'task', d):
>                         sys.__stdout__.write("%s\n" % e)
> }
>
> addtask build
> do_build[dirs] = "${TOPDIR}"
> do_build[nostamp] = "1"
> python base_do_build () {
>         bb.note("The included, default BB base.bbclass does not define a
> useful default task.")
>         bb.note("Try running the 'listtasks' task against a .bb to see what
> tasks are defined.")
> }
>
> EXPORT_FUNCTIONS do_clean do_mrproper do_build
>
> Again, it's more than you need. It's just convenient to use it. I put this
> file inside the layer but you can also create a classes directory in
> ${TOPDIR} (bbtest in this example). Next, create a layer (meta-bbtest in my
> example, name does not matter, meta-* is convention). It needs a
> conf/layer.con file:
>
> layer.conf:
>
> # We have a metadata layer directory, add to BBPATH
> BBPATH .= ":${LAYERDIR}"
>
> # We have a recipe directory, add to BBFILES
> BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
>             ${LAYERDIR}/recipes-*/*/*.bbappend"
>
> BBFILE_COLLECTIONS += "test"
> BBFILE_PATTERN_test := "^${LAYERDIR}/"
> BBFILE_PRIORITY_test = "5"
>
> The path expression for the recipes is more complex than necessary, it just
> follows the convention. Finally a recipe to build the Nano editor:
>
> DESCRIPTION = "Recipe to build the 'nano' editor"
>
> PN = "nano"
> PV = "2.2.6"
>
> SRC_URI = "http://www.nano-editor.org/dist/v2.2/nano-2.2.6.tar.gz"
>
> python do_fetch() {
>    bb.note("Downloading source tarball from ${SRC_URI} ...")
>
>    src_uri = (bb.data.getVar('SRC_URI', d, True) or "").split()
>    if len(src_uri) == 0:
>       bb.fatal("Empty URI")
>
>    try:
>       bb.fetch.init(src_uri, d)
>       bb.fetch.go(d)
>    except FetchError:
>       bb.fatal("Could not fetch source tarball.")
>
>    bb.note("Download successful.")
> }
>
> addtask fetch before do_build
>
>
> python do_unpack() {
>    bb.note("Unpacking source tarball ...")
>
>    os.system("tar x -C ${WORKDIR} -f ${DL_DIR}/${P}.tar.gz")
>
>    bb.note("Unpacked source tarball.")
> }
>
> addtask unpack before do_build after do_fetch
>
>
> python do_configure() {
>    bb.note("Configuring source package ...")
>
>    os.system("cd ${WORKDIR}/${P} && ./configure")
>
>    bb.note("Configured source package.")
> }
>
> addtask configure before do_build after do_unpack
>
>
> python do_compile() {
>    bb.note("Compiling package...")
>
>    os.system("cd ${WORKDIR}/${P} && make")
>
>    bb.note("Compiled package.")
> }
>
> addtask compile before do_build after do_configure
>
>
> Nano is an autotooled package. This recipe simply at a very basic level does
> what you would do manually. OECore's autotools.bbclass is much more
> sophisticated and so are the fetcher class files.
>
> :rjs
>
>
>
> _______________________________________________
> yocto mailing list
> yocto at yoctoproject.org
> https://lists.yoctoproject.org/listinfo/yocto
>



More information about the yocto mailing list